什么是文件
文件:文件就是保存数据的地方,比如word文档,txt文件,excel文件-
文件流
文件在程序中是以流的形式来操作的
图片.png
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
常用的文件操作
- 创建文件对象相关构造器和方法
相关方法:
new File(String pathname) //根据路径构建一个File对象
new File(File parent,String child) //根据父目录文件+子路径构建
new File(String parent,String child) //根据父目录+子路径构建
createNewFile 创建新文件
@Test
public void create01(){
String filePath = "d:\\news1.txt";
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void create02(){
File parentFile = new File("d:\\");
String fileName = "news2.txt";
File file = new File(parentFile, fileName);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void create03(){
String parentPath = "d:\\";
String fileName = "news3.txt";
File file = new File(parentPath, fileName);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
- 获取文件的相关信息
getName、getAbssolutePath、getParent、length、exists、isFile、isDirectory
@Test
//获取文件的信息
public void info(){
//先创建文件对象
File file = new File("d:\\news1.txt");
//调用相应方法得到对应信息
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
System.out.println(file.getParent());
System.out.println(file.length());
System.out.println(file.exists());
System.out.println(file.isFile());
System.out.println(file.isDirectory());
}
- 目录的操作和文件删除
mkdir创建一级目录、mkdirs创建多层目录、delete删除空目录或文件
IO流原理及流的分类
1、I/O是Input/Output的缩写,I/O技术是非常使用的技术,用于处理数据传输。如读/写文件,网络通讯等
2、Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行
3、java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
4、输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
5、输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
-
流的分类
1、按操作数据单位不同分为:字节流(8bit)二进制文件(声音文件、视频文件、word文件),字符流(按字符),字符流主要操作文本文件
2、按数据流的流向不同分为:输入流、输出流
3、按流的角色的不同分为:节点流、处理流/包装流
image.png
1)Java的IO流共涉及40多个类,实际非常规则,都是从如上四个抽象基类派生的
2)由这四个派生出来的子类名称都是以其父类名作为子类后缀
IO流体系图-常用的类
- InputStream:字节输入流
InputStream抽象类是所有字节输入流的超类
InputStream常用的子类
1、FileInputStream:文件输入流
2、BufferedInputStream:缓冲字节输入流
3、ObjectInputStream:对象字节输入流
fileInputStream代码示例:
public class FileInputStream {
public static void main(String[] args) {
}
/**
* 演示读取文件
* 单个字节的读取,效率比较低
* ->使用read(byte[] b)
* */
@Test
public void readFile01(){
java.io.FileInputStream fileInputStream = null;
String filePath = "D:\\hello.txt";
int readData = 0;
try {
//创建FileInputStream对象,用于读取文件
fileInputStream = new java.io.FileInputStream(filePath);
//从该输入流读取一个字节的数据,如果没有输入可用,此方法将阻止
//如果返回-1.表示读取完毕
while ((readData = fileInputStream.read()) != -1){
System.out.print((char) readData); //转成char显示
}
}catch (IOException e){
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 使用read(byte[] b)读取文件,提高效率
* */
@Test
public void readFile02(){
java.io.FileInputStream fileInputStream = null;
String filePath = "D:\\hello.txt";
byte[] bytes = new byte[8]; //一次读取8个字节
int readLen = 0;
try {
fileInputStream = new java.io.FileInputStream(filePath);
//如果返回-1,表示读取完毕
//如果读取正常,返回实际读取的字节数
while ((readLen = fileInputStream.read(bytes)) != -1){
System.out.print(new String(bytes,0,readLen)); //显示
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
fileInputStream、fileOutputStream实现对图片的拷贝操作代码示例
public class FileCopy {
public static void main(String[] args) throws IOException {
//完成文件拷贝,将D:\\hello.png 拷贝 D:\\hello2.png
/**
* 思路分析
* 1、创建文件的输入流,将文件读取到程序
* 2、创建文件输出流,将读取的数据写入到指定的盘符(文件)
* */
//要读取的文件路径
String srcPath = "D:\\hello.png";
//存储文件路径
String destPath = "D:\\hello2.png";
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
//将文件数据读取到程序
try {
fileInputStream = new FileInputStream(srcPath);
fileOutputStream = new FileOutputStream(destPath);
//定义一个字节数组,提高读取效率
byte[] buf = new byte[1024];
int readLen = 0;
while ((readLen = fileInputStream.read(buf)) != -1){
//读取到数据后写入到指定的文件
//即,是一边读一边写
fileOutputStream.write(buf,0,readLen); //一定要使用这种方法
}
System.out.println("拷贝ok~~");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//关闭输入、输出流释放资源
if (fileInputStream != null){
fileInputStream.close();
}
if (fileOutputStream != null){
fileOutputStream.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
FileReader和FileWriter介绍
FileReader和FileWriter是字符流,即按照字符来操作ioFileReader相关方法
1、new FileReader(File/String)
2、read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
3、read(char[] ch):批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾返回-1
相关API:
1、new String(char[]):将char[]转换成String
2、new String(char[],off,len):将cahr[]的指定部分转换成String示例代码:
@Test
public void readFile01(){
String filePath = "D:\\story.txt";
int data = 0;
char[] chars = new char[1024];
FileReader fileReader = null;
//1、创建FileReader对象
try {
fileReader = new FileReader(filePath);
//循环读取,单个字符读取
while ((data = fileReader.read()) != -1){
System.out.print((char) data);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void readerFile02(){
String filePath = "D:\\story.txt";
FileReader fileReader = null;
int data = 0;
char[] chars = new char[8];
try {
fileReader = new FileReader(filePath);
//循环读取,使用read(buf),返回的是实际读取到的字符数组
//如果返回-1,说明到文件结束
while ((data = fileReader.read(chars)) != -1){
System.out.println(new String(chars,0,data));
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader != null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- FileWriter常用方法
1、new FileWriter(File/String):覆盖模式,相当于流的指针在首端
2、new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
3、write(int):写入单个字符
4、writer(char[]):写入指定数组
5、write(char[],off,len):写入指定数组的指定部分
6、wirte(string):写入整个字符串
7、write(string,off,len):写入字符串的指定部分
相关API:String类:toCharArray:将String转换成char[]
FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!
代码示例:
@Test
public void fileWriter01(){
String filePath = "D:\\note.txt";
//创建FilwWriter对象
FileWriter fileWriter = null;
char[] chars = {'1','2','C','W'};
try {
fileWriter = new FileWriter(filePath); //默认是覆盖写入
fileWriter.write('H');
fileWriter.write(chars);
fileWriter.write("美丽湄潭".toCharArray(),0,4);
//写入整个字符串
fileWriter.write("你好北京");
fileWriter.write("我的青春",0,2);
//在数据量大的情况下,可以使用循环操作
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileWriter != null){
try {
//对应FileWriter,一定要关闭,或者flush才能真正的把数据写入到文件
fileWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("程序执行结束");
}
节点流和处理流
-
基本介绍
1、节点流可以从一个特定的数据源(存放数据的地方)读写数据,如FileReader 、FileWriter
image.png
2、处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活。如BufferedReader、BufferedWriter
-
节点流和处理流一览图
image.png 节点流和处理流的区别和联系
1、节点流是底层流/低级流,直接跟数据源相接
2、处理流(包装流),既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
3、处理流(也叫包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连【模拟修饰器设计模式】处理流的功能主要体现在以下两个方面:
1、性能的提高:主要以增加缓冲的方式来提高输入输出的效率
2、操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便。处理流-BufferedReader和BufferedWriter
BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的,关闭处理流时,只需要关闭外层流即可应用案例
1、使用BufferedReader读取文本文件,并显示在控制台
@Test
public void BufferedReader01(){
String filePath = "D:\\Recovery.java";
BufferedReader bufferReader = null;
//创建BufferedReader对象
try {
bufferReader = new BufferedReader(new FileReader(filePath));
//读取
String line; //按行读取,效率高
//说明:1.bufferReader.readLine()是按行读取文件,
//2.当返回为null时,表示读取完毕
while ((line = bufferReader.readLine()) != null){
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferReader != null){
try {
//关闭流,这里注意:只需要关闭 bufferReader,因为底层会自动的去关闭节点流FileReader
bufferReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
2、使用BufferedWriter 将"hello,我亲爱的Java对象",写入到文件中
@Test
public void BufferWriter01(){
String filePath = "D:\\BufferWriter.txt";
//创建BufferedWriter对象
BufferedWriter bufferedWriter = null;
try {
bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,我亲爱的Java对象1");
bufferedWriter.newLine();
bufferedWriter.write("hello,我亲爱的Java对象2");
bufferedWriter.newLine();
bufferedWriter.write("hello,我亲爱的Java对象3");
bufferedWriter.newLine();
bufferedWriter.write("hello,我亲爱的Java对象4");
bufferedWriter.newLine();
bufferedWriter.write("hello,我亲爱的Java对象5");
bufferedWriter.newLine();
bufferedWriter.write("hello,我亲爱的Java对象6");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedWriter != null){
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("写入数据到文件结束。。。。");
}
3、使用BufferedReader 和 BufferedWriter 完成 文本文件拷贝,注意文件编码
@Test
public void BufferedCopy01(){
//要拷贝的文件
String srcFilePath = "D:\\Recovery.java";
//拷贝目的地
String desFilePath = "D:\\note.java";
//创建BufferedReader对象
BufferedReader bufferedReader = null;
//创建BufferedWriter对象
BufferedWriter bufferedWriter = null;
String line;
//读取文件
try {
bufferedReader = new BufferedReader(new FileReader(srcFilePath));
bufferedWriter = new BufferedWriter(new FileWriter(desFilePath));
//循环读取文件,bufferedReader.readLine()方法返回null时表示读取完毕
while ((line = bufferedReader.readLine()) != null){
//将读取的文件保存
bufferedWriter.write(line);
bufferedWriter.newLine();
}
System.out.println("拷贝完毕。。。。");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
//读取和写入完毕后需要关闭处理流
if (bufferedReader != null){
bufferedReader.close();
}
if (bufferedWriter != null){
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 处理流-BufferedInputStream和BufferedOutputStream用来处理二进制文件
BufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组
BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次写入调用底层系统
案例:使用BufferedInputStream 、BufferedOutputStream 字节输入/输出处理流完成图片音频文件的拷贝
@Test
public void copy(){
//声明图片存储地址
String srcFile = "D:\\hello.png";
//声明图片存储地址
String desFile = "D:\\cesi.png";
//声明字节输入处理流对象
BufferedInputStream bufferedInputStream = null;
//声明字节输出处理流对象
BufferedOutputStream bufferedOutputStream = null;
try {
bufferedInputStream = new BufferedInputStream(new FileInputStream(srcFile));
bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(desFile));
//循环读取文件,并写入到存储目的地
byte[] buf = new byte[1024];
int readLine = 0;
while ((readLine = bufferedInputStream.read(buf)) != -1){
bufferedOutputStream.write(buf,0,readLine);
}
System.out.println("拷贝完毕!!");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedInputStream != null){
try {
bufferedInputStream.close();
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- 对象流-ObjectInputStream和ObjectOutputStream
序列化和反序列化
1、序列化就是在保存数据时,保存数据的值和数据类型
2、反序列化就是在恢复数据时,恢复数据的值和数据类型
3、需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下的两个接口之一:
a、Serializable //这是一个标记接口
b、Externalizable //该接口有方法需要实现,因此我们一般使用上面的Serializable
基本介绍
1、功能:提供了对基本类型或对象类型的序列化和反序列化的方法
2、ObjectInputStream提供反序列化功能
3、ObjectOutputStream提供序列化功能
案例:使用ObjectOutputStream保存序列化后的数据的值和类型
@Test
public void method01() throws Exception {
//序列化后,保存的文件格式不是存文本的,而是按照它的格式保存的
String filePath = "D:\\data.dat";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePath));
//序列化数据到D:\data.dat
objectOutputStream.write(100); //int ->Integer(实现了Serializable接口)
objectOutputStream.writeBoolean(true); //boolean -> Boolean(实现了Serializable接口)
objectOutputStream.writeChar('a'); //char ->Character(实现了Serializable接口)
objectOutputStream.writeDouble(9.6); //double ->Double(实现了Serializable接口)
objectOutputStream.writeUTF("让生活变好"); //String
//保存一个Dog对象
objectOutputStream.writeObject(new Dog(10,"旺财"));
objectOutputStream.close();
System.out.println("数据保存完毕(序列化形式)!!!");
}
}
//如果需要序列化某个类的对象,实现接口Serializable
class Dog implements Serializable {
private Integer age;
private String name;
public Dog(Integer age, String name) {
this.age = age;
this.name = name;
}
}
案例:使用ObjectInputStream反序列化将存储的数据恢复到程序中去(需要将数据的类型和值都恢复回来)
@Test
public void method01() throws IOException, ClassNotFoundException {
//指定反序列化的文件
String filePath = "D:\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
//读取
//读取(反序列化)的顺序需要和你保存的数据(序列化)的顺序一致
System.out.println(ois.readInt());
System.out.println(ois.readBoolean());
System.out.println(ois.readChar());
System.out.println(ois.readDouble());
System.out.println(ois.readUTF());
Object dog = ois.readObject();
System.out.println(dog.getClass());
System.out.println("dog信息"+dog);//底层Onject ->Dog
//关闭外层流即可,底层会自动关闭FileInputStream
ois.close();
}
- 对象处理流注意事项和细节说明
1)读写顺序要一致
2)要求实现序列化或反序列化对象,需要实现Serializable
3)序列化的类中建议添加SerialVersionUID,为提高版本的兼容性
4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
5)序列化对象时,要求里面属性的类型也需要实现序列化接口
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
标准输入流输出流
介绍
类型 默认设备
System.in 标准输入 InputStream 键盘
System.out 标准输出 PrintStream 显示器转换流-InputStreamReader 和 OutputStreamWriter
作用:将字节流转换为字符流
介绍
1、inputStreamReader:Reader的子类,可以将inputStream(字节流)包装成Reder(字符流)
2、OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
3、当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换为字符流
4、可以在使用时指定编码格式(比如:utf-8、gbk、gb2312、ISO8859-1等)
案例:InputStreamReader 使用
public class InputStreamReader {
public static void main(String[] args) throws IOException {
String filePath = "D:\\story.txt";
java.io.InputStreamReader inputStreamReader = new java.io.InputStreamReader(new FileInputStream(filePath),"gbk");
BufferedReader reader = new BufferedReader(inputStreamReader);
String s = reader.readLine();
System.out.println("读取内容=="+s);
reader.close();
}
}
案例:OutputStreamWriter使用
public class OutputStreamWriter {
public static void main(String[] args) throws IOException {
String srcFile = "D:\\story.txt";
String desFile = "D:\\outFile.txt";
String readLine = "";
InputStreamReader gbk = new InputStreamReader(new FileInputStream(srcFile), "gbk");
BufferedReader reader = new BufferedReader(gbk);
java.io.OutputStreamWriter gbk1 = new java.io.OutputStreamWriter(new FileOutputStream(desFile), "gbk");
BufferedWriter bufferedWriter = new BufferedWriter(gbk1);
while ((readLine = reader.readLine()) != null){
bufferedWriter.write(readLine);
}
System.out.println("拷贝完毕~~");
reader.close();
bufferedWriter.close();
}
}
- Properties类
看一下需求:
如下的一个配置文件:mysql.properties
ip = 192.168.3.15
user = root
pwd = 12345
请问编程读取ip、user、pwd的值是多少?
- 基本介绍
1)专门用于读写配置文件的集合类
配置文件的格式:
键=值
键=值
2)注意:键值对不需要有空格,值不需要用引号引起来,默认类型是String
3)Properties的常见方法- load:加载配置文件键值对到Properties对象
- list:将数据显示到指定设备
- getProperties(key):根据键获取值
- setProperties(key,value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
http://tool.chinaz.com/tools/unicodea.aspx unicode码查询工具
- 应用案例
1、使用Properties类完成对mysql.properties的读取
public class Properties02 {
public static void main(String[] args) throws IOException {
//创建Properties类
Properties properties = new Properties();
/**
* Properties类的load方法中需要传入一个Reader(字符输入流)
* 在加载的时候需要先读取配置文件内容然后再加载到Properties中
* */
properties.load(new FileReader("D:\\codeApp\\practice\\尚硅谷Java第一阶段\\第一阶段\\src\\mysql.properties"));
properties.list(System.out);
//通过键获取值
String user = properties.getProperty("user");
String pwd = properties.getProperty("pwd");
System.out.println("用户是:"+user+",密码是:"+pwd);
}
}
2、使用Properties类添加key-val到新文件mysql2.properties中
3、使用Properties类完成对mysql.properties的读取,修改某个key-val
public class Properties03 {
public static void main(String[] args) throws IOException {
Properties properties = new Properties();
properties.setProperty("ip","127.0.0.1");
properties.setProperty("user","库里");
properties.setProperty("pwd","admin@123");
properties.setProperty("pwd","123456");
//目前数据信息存储在内存中,需要把数据存储到文件中,可调用properties的store方法
FileOutputStream fileOutputStream = new FileOutputStream("D:\\codeApp\\practice\\尚硅谷Java第一阶段\\第一阶段\\src\\mysql2.properties");
properties.store(fileOutputStream,null);
System.out.println("存储完毕~~~");
}
}
本章综合案例:
(1)要编写一个dog.properties
name=tom
age=10
color=red
(2)编写Dog类(name,age,color)创建一个dog对象,读取dog.proeprties用相应的内容完成属性初始化,并输出
(3)将创建的Dog对象,序列化到文件dog.dat文件
示例代码:
public class Homework03 {
public static void main(String[] args) {
BufferedWriter bufferedWriter = null;
ObjectOutputStream objectOutputStream = null;
Properties properties = new Properties();
properties.setProperty("name","tom");
properties.setProperty("age","5");
properties.setProperty("color","red");
//将内存中的数据存储到对应的文件中
String filePath = "D:\\codeApp\\practice\\尚硅谷Java第一阶段\\第一阶段\\src\\homework.properties";
try {
bufferedWriter = new BufferedWriter(new FileWriter(filePath));
//将数据加载进指定的流中保存
properties.store(bufferedWriter,"家庭作业3配置文件");
//然后获取其中的name、age、color值
String name = properties.getProperty("name");
Integer age = Integer.valueOf(properties.getProperty("age"));
String color = properties.getProperty("color");
Dog dog = new Dog(name, age, color);
System.out.println(dog);
//将dog序列化到dog.dat文件中
String dogFile = "D:\\dog.dat";
objectOutputStream = new ObjectOutputStream(new FileOutputStream(dogFile));
objectOutputStream.writeObject(dog);
System.out.println("序列化dog对象完成~~");
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedWriter != null){
try {
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (objectOutputStream != null){
try {
objectOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
该文章仅用于学习,借此希望该文章能对大家有所帮助!! 感觉可以点个赞赞呗~
该文章笔记内容源自B站韩顺平零基础30天学Java视频,如有侵权,请私信删除文章。