【io】流及File对象的处理(一)
IO的处理
本文主要介绍流的相关内容
1. 流的概念
是内存与存储设备之间传输数据的通道。
2. 流的分类
# 1. 按照方向分: (1)输入流:将<存储设备>中的内容读入到<内存>中 (2)输出流:将<内存>中的内容写入到<存储设备>中 # 2. 按处理单位分: (1)字节流:以字节为单位,可以读写所有数据 (2)字符流:以字符为单位,只能读写文本数据 # 3. 按功能分: (1)节点流:具有实际传输数据的读写功能。 (2)过滤流:在节点流的基础之上增强功能。
3. 字节流
3.1 字节流
# 字节流的父类(抽象类) (1)InputStream:字节输入流(read) (2)OutputStream:字节输出流(write) # 文件字节流 #(1)FileInputStream: #(2)FileOutputStream:
例子:

# 单个字节读取 public static void main(String[] args) throws Exception {//这里为了代码可读性,异常暂时抛出 //1. 创建FileInputStream,并指定文件路径 FileInputStream fis = new FileInputStream("d:\\aa.txt"); //2. 读取文件 data对象用来保存我们读取的字节 int data = 0; //如果都读取完了,会返回-1 ,不过这个read方法读取比较慢,是一个字节一个字节的读 while ((data=fis.read())!=-1){ System.out.println((char)data);//假设txt文件中存的是abcdefg ,那么每次会输出一个 } //3. 关闭 fis.close(); } # 多个字节读取 public static void main(String[] args) throws Exception{ //1. 创建FileInputStream,并指定文件路径 FileInputStream fis = new FileInputStream("d:\\aa.txt"); //2. 创建一个数组用来存放读取到的字节,这里暂定长度为3 byte[] buf = new byte[3]; //3. 读取文件 count就是我们实际读取的字节数 int count = 0; //如果都读取完了,会返回-1 ,这个read方法,是按照上面数组的长度,即三个三个的读 while ((count=fis.read(buf))!=-1){ System.out.println(new String(buf,0,count));//假设txt文件中存的是abcdefg ,那么每次会输出三个 } //4. 关闭 fis.close(); } # 输出流写入 public static void main(String[] args) throws Exception{ //1. 创建文件字节输出流对象 ,没有此文件会创建,有此文件调用下面的write方法的时候会覆盖txt里的内容。 FileOutputStream fos = new FileOutputStream("d:\\bb.txt"); //可以通过加参数 true 来实现非覆盖而是追加的效果 //FileOutputStream fos = new FileOutputStream("d:\\bb.txt",true); //2. 写入文件. String str = "helloword"; //str.getBytes()意思为获取这个字符串所对应的字符数组 fos.write(str.getBytes()); //3. 关闭 fos.close(); } # 使用文件字节流(输入流和输出流)实现文件的复制 # 注意:文件字节流不带缓冲效率会比较低 public static void main(String[] args) throws Exception{ //1. 创建流 //1.1 文件字节输入流 ,如果没有会报错java.io.FileNotFoundException: d:\001.jpg (系统找不到指定的文件。) FileInputStream fis = new FileInputStream("d:\\001.jpg"); //1.2 文件字节输出流 FileOutputStream fos = new FileOutputStream("d:\\002.jpg"); //2. 一边读,一边写 byte[] buf = new byte[1024]; int count =0; while((count=fis.read(buf))!=-1){ fos.write(buf,0,count); } //3. 关闭 fis.close(); fos.close(); }
3.2 字节缓冲流
# 缓冲流:BufferedInputStream/BufferedOutputStream (1)提高IO效率,减少访问磁盘的次数 (2)数据存储在缓存区中,flush是将缓存区的内容写入文件中,也可以直接close.
例子:

//输入缓冲流 public static void main(String[] args) throws Exception{ //1. 创建文件输入流 FileInputStream fis = new FileInputStream("d:\\aa.txt"); //2. 创建缓冲流,来增强文件输入流 BufferedInputStream bis = new BufferedInputStream(fis); //3. 读取 int data = 0; //注意:这里read并非一个个的读,而是一次读8k到缓冲区,即BufferedInputStream源码中的private static int DEFAULT_BUFFER_SIZE = 8192; while ((data=bis.read())!=-1){ System.out.println((char)data); } //当然也可以自己定义缓冲区 //byte[] buf = new byte[1024]; //int count =0; //while ((count=bis.read(buf))!=-1){ //System.out.println(new String(buf,0,count)); //} //4. 关闭 只关闭缓冲流即可,它内部会把文件输入流也关闭了. bis.close(); } //输出缓冲流 public static void main(String[] args) throws Exception{ //1. 创建字节输出流 FileOutputStream fos = new FileOutputStream("d:\\cc.txt"); //2. 创建字节输出缓冲流 BufferedOutputStream bos = new BufferedOutputStream(fos); //3. 写入文件 for(int i=0;i<10;i++){ bos.write("helloworld".getBytes());//只要不超过8k都会写入到8k缓冲区,此时文件中实际上是没有内容的 bos.flush();//只有刷新才会将数据刷新到硬盘 } //4. 关闭(内部也会调用flush方法) bos.close(); }
3.3 对象流+(反)序列号
Serializable接口 # 对象流:ObjectOutputStream/ObjectInputStream 使用流传输对象的过程称为序列化/反序列化 (1)增强了缓冲区功能 (2)增强了读写8中基本数据类型和字符串功能 (3)增强了读写对象的功能 readObject() 从流中读取一个对象 writeObject(Object obj) 向流中写入一个对象 # 要求: (1)序列化类必须要实现Serializable接口 (2)序列化类中对象属性也要求实现Serializable接口 (3)序列化版本号ID(serialVersionUID),保证序列化的类和反序列化的类是同一个类 (4)使用transient(瞬间的)修饰属性,这个属性不能序列化 (5)静态属性也不能序列化 (6)序列化多个对象 即下面的例子中可以创建多个对象,之后将多个对象放入一个list中,当然获取的时候返回的也是一个List即可
例子:

//使用ObjectOutputStream实现对象的序列化 public static void main(String[] args) throws Exception{ //1. 创建文件输出流 FileOutputStream fos = new FileOutputStream("d:\\stu.bin"); //2. 创建文件输入流 ObjectOutputStream oos = new ObjectOutputStream(fos); //3. 创建一个对象并赋值 //注意:这里要求必须要对象实现序列化,否则会报错java.io.NotSerializableException: com.company.Student Student stu = new Student(); stu.setAge(21); stu.setName("张三"); //4. 写入操作(序列化) oos.writeObject(stu); //5. 关闭 oos.close(); } //这里要求对象必须实现序列化 public class Student implements Serializable { private String name; private int age; //private transient int age;//被transient修饰的不能序列化,即序列化后再反序列化是没值的 private static final long serialVersionUID = -8778349856468359639L; //省略setter、getter、toString方法 } //使用ObjectInputStream实现反序列化(读取重构成对象) public static void main(String[] args) throws Exception{ //1. 创建文件输入流 FileInputStream fis = new FileInputStream("d:\\stu.bin"); //2. 创建对象流 ObjectInputStream ois = new ObjectInputStream(fis); //3. 读取文件(反序列化) Student stu = (Student)ois.readObject(); //4. 关闭 ois.close(); System.out.println(stu.toString());//结果: Student{name='张三', age=21} }
4. 编码方式
# 常见字符编码 # 1. ISO-8859-1 收录除了ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号 # 2. UTF-8 针对Unicode码表的可变长度字符编码 # 3. GB2312 简体中文 # 4. GBK 简体中文、扩充 # 5. BIG5 台湾,简体中文 # 当编码方式和解码方式不一致时,会出现乱码。
5. 字符流
5.1 字符流
# 涉及到汉字的一般用字符流 FileReader/FileWriter # 字符流的父类(抽象类): (1)Reader:字符输入流 read() (2)Writer:字符输出流 write()
例子:

//FileReader读取文件 public static void main(String[] args) throws Exception{ //1. 创建FileReader 文件字符输入流 FileReader fr = new FileReader("d:\\hello.txt"); //2. 读取 (单个字符读取) int data = 0; while ((data=fr.read())!=-1){ System.out.println((char)data); } //3. 关闭 fr.close(); } //FileWriter写入文件 public static void main(String[] args) throws Exception{ //1. 创建FileWriter对象 FileWriter fw = new FileWriter("d:\\write.txt"); //2. 写入 for(int i=0;i<10;i++){ fw.write("你好"); fw.flush(); } //3. 关闭 fw.close(); } //使用FileWriter和FileReader复制文件 //注意:只能复制文本文件,不能复制图片和二进制文件(声音/视频等) 字节流可以复制任何文件 public static void main(String[] args) throws Exception{ //1. 创建FileWriter和FileReader FileReader fr = new FileReader("d:\\write.txt"); FileWriter fw = new FileWriter("d:\\write2.txt"); //2. 读写 int data=0; while ((data=fr.read())!= -1){ fw.write(data); fw.flush(); } //3. 关闭 fr.close(); fw.close(); }
5.2 字符缓冲流
# 缓冲流:BufferedReader/BufferedWriter (1)高效读写(缓冲区) (2)支持输入换行符 (3)可一次读/写一行
例子:

//使用字符缓冲流读取文件 (单个字符读+一行一行读) public static void main(String[] args) throws Exception{ //1. 创建缓冲流 FileReader fr = new FileReader("d:\\write.txt"); BufferedReader br = new BufferedReader(fr); //2. 读取 //2.1 第一种 //char[] buf = new char[1024]; //int count = 0; //while ((count=br.read())!=-1){ //System.out.println(new String(buf,0,count)); //} //2.2 第二种 一行一行读 String line = null; while ((line=br.readLine())!=null){ System.out.println(line); } //3. 关闭 br.close(); } //使用字符缓冲流写入文件 public static void main(String[] args) throws Exception{ //1. 创建缓冲流 FileWriter fw = new FileWriter("d:\\buffer.txt"); BufferedWriter bw = new BufferedWriter(fw); //2. 写入 for(int i=0;i<10;i++){ bw.write("你好"); bw.newLine();//写入一个换行符 windows:\r\n linux:\n bw.flush(); } //3. 关闭 bw.close(); }
6. 打印流
# PrintWriter: (1)封装了print() / println() 方法,支持写入后换行 (2)支持数据原样打印
例子:

//PrintWriter的使用 public static void main(String[] args) throws Exception{ //1. 创建打印流 PrintWriter pw = new PrintWriter(""); //2. 打印 pw.println(97);//换行 打印到文件之后不会变成a,仍然是97 pw.print(true);//不换行 打印到文件里是true字符串 pw.println('a');//打印到文件里是a //3. 关闭 pw.close(); }
7. 转换流
# 又称为桥转换流:InputStreamReader/OutputStreamWriter (1)可将字节流转换为字符流 (2)可设置字符的编码方式
例子:

//使用InputStreamReader读取文件,指定使用的编码 public static void main(String[] args) throws Exception{ //1. 创建InputStreamReader对象 FileInputStream fis = new FileInputStream("d:\\write.txt"); InputStreamReader isr = new InputStreamReader(fis,"utf-8");//gbk //2. 读取文件 int data=0; while ((data=isr.read())!=-1){ System.out.println((char)data); } //3. 关闭 isr.close(); } //使用OutputStreamWriter写入文件,指定使用的编码 public static void main(String[] args) throws Exception{ //1. 创建OutputStreamWriter对象 FileOutputStream fos = new FileOutputStream("d:\\info.txt"); OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk"); //2. 写入文件 for(int i=0;i<10;i++){ osw.write("你好"); osw.flush(); } //3. 关闭 osw.close(); }
持续更新!!!