I/O流
一、I/O的概念
- I是指input,输入
- O是指output,输出
二、流的分类方式
- 按照流的方向分:输入流和输出流
- 按照流的单位分:字节流和字符流
- 按照流的功能分:节点流和过滤流
三、字节输入流和字节输出流
-
流的使用基本结构:
- 创建流对象
- 使用流对象执行操作代码
- 关闭流对象(释放资源)
-
父类:
- 输入流:public abstract class InputStream
- 输出流:public abstract class OutputStream
-
子类:
-
字节输出流:FileOutputStream
- 构造方法:
- public FileOutputStream(String name):通过指定文件所在位置创建流对象
- public FileOutputStream(String name,boolean append):通过指定文件所在位置创建流对象并且指定是否在原有数据后进行追加(true表示追加)
- 成员方法:
- write(int b):一次写入一个字节
- write(byte[] b):一次写入一个字节数组
- write(byte[] b,int index,int length):写入数组的一部分,从index下标开始,总计length个元素
- 特点:
- 如果没有文件,则会创建文件
- 如果没有文件夹,不会创建文件夹
package com.baizhi.testIO; import java.io.FileOutputStream; import java.io.OutputStream; public class TestFileOutputStream { public static void main(String[] args) throws Exception { // 创建流对象 OutputStream fos = new FileOutputStream("a.txt"); // 当需要在文件末尾继续追加内容的时候 // OutputStream fos = new FileOutputStream("a.txt",true); // 操作流对象 fos.write(65); // 关闭流对象 fos.close(); } }
- 构造方法:
-
字节输入流:FileInputStream
- 构造方法:public FileInputStream(String name):通过指定文件所在位置创建流对象
- 成员方法:
- int read():一次读取一个字节,如果返回-1,则代表读取到文件的末尾
- int read(byte[] bs):一次读取一个数组,返回本次读取到的数量,如果返回-1,则代表读取到文件的末尾
package com.baizhi.testIO; import java.io.FileInputStream; import java.io.InputStream; public class TestFileInputStream { public static void main(String[] args) throws Exception { // 创建流对象 InputStream is = new FileInputStream("a.txt"); // 操作流对象 while (true) { int i = is.read(); if(i == -1) break; System.out.println((char)i); } // 关闭流对象 is.close(); } }
-
-
异常的积极处理
package com.baizhi.testIO; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; public class TestFileOutputStream { public static void main(String[] args) { // 将流对象的声明作用域扩大,以便于在finally中可以对该对象进行关闭 OutputStream fos = null; try { fos = new FileOutputStream("a.txt",true); fos.write(65); // 将创建流对象可能会抛出的异常进行处理 }catch (FileNotFoundException e) { e.printStackTrace(); // 将文件写出操作可能会抛出的异常进行处理 }catch (IOException e) { e.printStackTrace(); } finally { // 任何情况下都应该进行资源的释放 if(fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
-
文件的复制:通过输入流将文件进行读取,通过输出流对文件进行写出
-
一次写一个字节的方式进行复制
package com.baizhi.testIO; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; public class TestFileCopy { public static void main(String[] args) throws Exception { // 创建输入和输出流,将a文件复制成b文件 InputStream is = new FileInputStream("a.txt"); OutputStream os = new FileOutputStream("b.txt"); // 输入之后,进行写出 while (true) { int i = is.read(); if(i == -1) break; os.write(i); } // 关闭流对象 is.close(); os.close(); } }
-
一次写一个字节数组的方式进行复制
package com.baizhi.testIO; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; public class TestFileCopy { public static void main(String[] args) throws Exception { // 创建输入和输出流,将a文件复制成b文件 InputStream is = new FileInputStream("a.txt"); OutputStream os = new FileOutputStream("b.txt"); // 输入之后,进行写出 byte[] bs = new byte[1024]; while (true) { int i = is.read(bs); if(i == -1) break; os.write(bs,0,i); } // 关闭流对象 is.close(); os.close(); } }
-
四、字节过滤流
-
缓冲流
-
字节过滤输入流:BufferedInputStream
- 构造方法public BufferedInputStream(InputStream is)
- 成员方法:同FileInputStream
- 特点:具有缓冲区,读入更高效
package com.baizhi.testIO; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.InputStream; public class TestBufferedInputStream { public static void main(String[] args) throws Exception{ // 创建节点流 InputStream is = new FileInputStream("a.txt"); // 包装过滤流 BufferedInputStream bis = new BufferedInputStream(is); // 操作流对象 while (true) { int i = bis.read(); if(i == -1) break; System.out.println((char)i); } // 关闭过滤流 bis.close(); } }
-
字节过滤输出流:BufferedOutputStream
- 构造方法public BufferedOutputStream(OutputStream os)
- 成员方法
- flush():对缓冲区进行刷新
- 其他的同FileOutputStream
- 特点:具有缓冲区
package com.baizhi.testIO; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.OutputStream; public class TestBufferedOutputStream { public static void main(String[] args) throws Exception{ // 创建节点流 OutputStream os = new FileOutputStream("b.txt"); // 包装过滤流 BufferedOutputStream bos = new BufferedOutputStream(os); // 操作流对象 bos.write(65); // 关闭流对象 bos.close(); } }
-
基于过滤流的文件复制
package com.baizhi.testIO; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream; public class TestFileCopy { public static void main(String[] args) throws Exception { // 创建节点流,将a文件复制成b文件 InputStream is = new FileInputStream("a.txt"); OutputStream os = new FileOutputStream("b.txt"); // 包装过滤流 BufferedInputStream bis = new BufferedInputStream(is); BufferedOutputStream bos = new BufferedOutputStream(os); // 输入之后,进行写出 while (true) { int i = bis.read(); if(i == -1) break; bos.write(i); } // 关闭流对象 bis.close(); bos.close(); } }
-
-
缓冲流
- PrintStream
- 只有输出,没有对应的输入流
- 可以进行文件的写出,但是通常用于打印
- 打印语句使用的就是这个流
- 这个流具有缓冲区
- PrintStream
-
对象流
-
对象输出流:ObjectOutputStream
-
构造方法:public ObjectOutputStream(OutputStream os)
-
成员方法:writeObject(Object o)
-
要求:需要实现序列化接口 Serializable
package com.baizhi.testIO; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; public class Test { public static void main(String[] args) throws Exception{ OutputStream os = new FileOutputStream("a.txt"); ObjectOutputStream oos = new ObjectOutputStream(os); Person p1 = new Person("zhangs", 30); Person p2 = new Person("guox", 29); oos.writeObject(p1); oos.writeObject(p2); oos.close(); } } class Person implements Serializable{ String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
-
对于不需要被序列化的属性,使用 transient 关键字修饰
transient String name;
-
-
对象输入流:ObjectInputStream
-
构造方法:public ObjectInputStream(InputStream os)
-
成员方法:Object readObject()
-
要求:实现序列化接口
package com.baizhi.testIO; import java.io.EOFException; import java.io.FileInputStream; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.Serializable; public class Test { public static void main(String[] args) throws Exception{ InputStream is = new FileInputStream("a.txt"); ObjectInputStream ois = new ObjectInputStream(is); try { while(true) { Object o = ois.readObject(); System.out.println(o); } }catch (EOFException e) { System.out.println("文件读取结束"); } ois.close(); } } class Person implements Serializable{ String name; int age; public Person(String name, int age) { super(); this.name = name; this.age = age; } public Person() { super(); } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } }
-
-
五、编码与字符集
- 将十进制字符转换为二进制数字的过程称为编码
- 将二进制数字转换为十进制字符的过程称为解码
- 存储二进制数字与十进制字符之间映射关系的图表称为编码字符集
- 常见的编码字符集:
- ASCII:美国信息交换标准码
- ISO8859-1:西欧常用编码格式
- GB2312:早期的简体中文字符集
- GBK:现阶段常用的简体中文字符集
- Big5:繁体中文字符集,常见于台湾地区
- UTF-8:底层采用unicode的编码形式,世界通用的编码字符集
- 乱码的常见原因:编码和解码使用的字符集不一致
六、字符输入流和字符输出流
- 父类:
- 输入流:public abstract class Reader
- 输出流:public abstract class Writer
- 子类:
-
输入流:FileReader
- 构造方法:public FileReader(String path):通过指定文件所在位置创建流对象
- 成员方法:
- public int read():一次读取一个字符,如果返回-1,则代表读取到文件的末尾
- public int read(char[] cs):一次读取一个数组,返回本次读取到的数量,如果返回-1,则代表读取到文件的末尾
package com.baizhi.testIO; import java.io.FileReader; import java.io.Reader; public class TestFileReader { public static void main(String[] args) throws Exception{ // 创建流对象 Reader r = new FileReader("a.txt"); // 操作流对象 while (true) { int i = r.read(); if(i == -1) break; System.out.println((char)i); } // 关闭流对象 r.close(); } }
-
输出流:FileWriter
- 构造方法:
- public FileWriter(Srting path):通过指定文件所在位置创建流对象
- public FileWriter(Srting path,boolean append):通过指定文件所在位置创建流对象并且指定是否在原有数据后进行追加(true表示追加)
- 成员方法:
- public void write(int c):一次写入一个字符
- public void write(char[] cs):一次写入一个字符数组
- public void write(char[] cs,int index,int length):写入数组的一部分,从index下标开始,总计length个元素
- 特点:
- 如果没有文件,则会创建文件
- 如果没有文件夹,不会创建文件夹
package com.baizhi.testIO; import java.io.FileWriter; import java.io.Writer; public class TestFileWriter { public static void main(String[] args) throws Exception{ // 创建流对象 Writer w = new FileWriter("b.txt"); // 当需要在文件末尾继续追加内容的时候 // Writer w = new FileWriter("b.txt",true); // 操作流对象 w.write('流'); // 关闭流对象 w.close(); } }
- 构造方法:
-
七、字符过滤流
-
缓冲流:
-
字符过滤输入流:BufferedReader
- 构造方法:public BufferedReader(Reader in)
- 成员方法:
- public String readLine():一次读取一整行,如果返回null,则代表读到文件尾
- 其他成员方法和FileReader一致
package com.baizhi.testIO; import java.io.BufferedReader; import java.io.FileReader; import java.io.Reader; public class TestBufferedReader { public static void main(String[] args) throws Exception { // 创建节点流 Reader reader = new FileReader("a.txt"); // 创建过滤流 BufferedReader br = new BufferedReader(reader); // 一次读取一整行 while (true) { String line = br.readLine(); if(line == null) break; System.out.println(line); } // 关闭流对象 br.close(); } }
-
字符过滤输出流:BufferedWriter
- 构造方法:public BufferedWriter(Writer out)
- 成员方法:
- public void flush():对缓冲区进行刷新
- public void newLine():写换行符,适用于所有平台
- 其他成员方法和FileWriter一致
package com.baizhi.testIO; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.Writer; public class TestBufferedWriter { public static void main(String[] args) throws Exception { // 创建节点流 Writer writer = new FileWriter("b.txt"); // 包装过滤流 BufferedWriter bw = new BufferedWriter(writer); // 写完一行之后换行 bw.write("zhangs"); bw.newLine(); // 关闭流对象 bw.close(); } }
-
-
缓冲流:
- 过滤流:PrintWriter
- 只有输出,没有对应的输入流
- 可以进行文件的写出
- 向浏览器输出字符
- 这个流具有缓冲区
- 过滤流:PrintWriter
八、桥转换流
-
可以将字节流转换为字符流的流称为桥转换流
-
类名:
-
输入流:InputStreamReader
- 构造方法:
- public InputStreamReader(InputStream in):使用字节流作为参数构造桥转换流
- public InputStreamReader(InputStream in,String charsetName):使用字节流作为参数构造桥转换流,并且指定读取时所使用的的编码字符集格式
- 成员方法:与字符流一致
- 构造方法:
-
输出流:OutputStreamWriter
- 构造方法:
- public OutputStreamWriter(OutputStream out):使用字节流作为参数构造桥转换流
- public OutputStreamWriter(OutputStream out,String charsetName):使用字节流作为参数构造桥转换流,并且指定写出时所使用的的编码字符集格式
- 成员方法:与字符流一致
- 构造方法:
-
InputStreamReader和OutputStreamWriter本身也是过滤流,但是建议使用BufferedReader和BufferedWriter对文件进行操作
package com.baizhi.testIO; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; public class TestReaderAndWriter { public static void main(String[] args) throws Exception { // 创建字节流 InputStream is = new FileInputStream("a.txt"); OutputStream fos = new FileOutputStream("b.txt"); // 创建桥转换流 InputStreamReader isr = new InputStreamReader(is); OutputStreamWriter osw = new OutputStreamWriter(fos); // 创建字符过滤流 BufferedReader reader = new BufferedReader(isr); BufferedWriter writer = new BufferedWriter(osw); // 文件复制 while (true) { String line = reader.readLine(); if(line == null) break; writer.write(line); writer.newLine(); } // 关闭流对象 reader.close(); writer.close(); } }
-
九、File类
- File类:用于操作硬盘上文件的类
- File对象和文件的关系:File对象是JVM堆内存中的对象,通过该对象的成员方法对硬盘上的文件进行操作
- 构造方法:public File(String pathname):根据文件的路径创建File对象
- 成员方法:
- public boolean createNewFile(): 创建文件,创建成功返回true,如果文件存在返回值为false。
- public boolean mkdir(): 创建目录,创建成功返回true,如果文件存在返回值为false。
- public boolean delete(): 删除目录/文件,删除成功返回true,否则为false。
- 当删除目录时,只有当目录为空时,才可以删除;
- 而删除文件时,不管文件内容是否为空,都会被删除。
- public String getName(): 获取文件名(含扩展名)、目录名
- public boolean exists(): 判断一个文件或是目录是否存在,存在返回true,否则为false。
- public String getAbsolutePath (): 获得绝对路径
- public File[] listFiles(): 获取当前目录下所有的文件和子目录
- public boolean isFile(): 判断File对象所对应的是否为文件
- public boolean isDirectory(): 判断File对象所对应的是否为目录
- 注意:isFile()和isDirectory()如果返回false,不能说明该File一定是目录或者文件,还有可能对应的文件不存在