目录
I/O
I:input 输入
O:output 输出
输入 输出 字节 InputStream OutputStream 字符 Reader Writer
- 流关闭原则 :先开后关,后开先关
- 流关闭后不可再次调用
File类 文件类
java.io.File是文件和目录路径名的抽象表示,主要用于目录的创建、查找和删除等操作。
构造方法:
- File(String pathName) 通过给定路径创建File实例
- File(String parent,String child)通过父子路径创建File实例
- File(File parent,String child) 通过父抽象路径及子路径创建File实例
一个File对象代表硬盘中实际存在的一个文件或目录
无论该路径下是否存在文件或目录,都不影响File对象的创建
输出流
OutputStream 字节输出流
常用方法:
- close() 关闭流,释放资源
- flush() 刷新流,并强制缓冲的输出字节写出
- write(byte[ ] b) 将b.length字节从指定字节数组写入此输出流
- write(byte[ ] b,int off,int len)从off开始,输出len长度字节到此输出流
- write(int b) 将指定的字节输出流
FileOutputStream 文件输出流
构造方法:
- FileOutputStream(File file) 使用File对象创建流对象,创建文件输出流,以写入由指定的File对象表示的文件
- FileOutputStream(String path)使用文件名称创建流对象,创建文件输出流,以指定名称写入文件
创建一个流对象时,必须传入一个文件路径。
该路径下,如果没有这个文件,会创建该文件;如果有这个文件,会清空这个文件的数据。
//写出字节数据 //write(int b),每次可以写出一个字节数据. FileOutputStream fos = new FileOutputStream("fos.txt"); fos.write(97); fos.close(); //输出结果在fos.txt中显示a //写出字节数组 //write(byte[] b),每次可以写出数组中的数据 byte[] b = "测试字符串".getBytes(); fos.write(b); fos.close(); //输出:测试字符串 //写出指定长度字节数组 //write(byte[] b,int off,int len),从off索引开始,写出len个字节 byte[] b = "abcde".getBytes(); fos.write(b,2,2); fos.close(); //输出:cd //数据追加续写 //FileOutputStream(File file,boolean append); //FileOutputStream(String name,boolean append); //当取值为true时,表示在文件末尾追加数据,无此参数时,默认为false FileOutputStream fos = new FileOutputStream("fos.txt",true); byte[] b = "abcde".getBytes(); fos.write(b); fos.close(); //文件操作前内容:cd 文件操作后内容:cdabcde //写出换行 fos.write("\r\n".getBytes());
输入流
InPutStream 字节输入流
java.io.InputStream 是所有字节输出流的超类,作用为读取字节信息到内存中,定义了字节输入流的基本共性方法。
常用方法:
- close() 关闭流,释放资源
- int read() 从输入流读取数据的下一个字节
- int read(byte[ ] b)从输出流中读取字节数,并存储在字节数组b中
FileInputStream 文件输入流
构造方法:
- FileInputStream(File file)通过打开与实际文件的连接来创建一个FileInputStream对象,参数为file
- FileInputStream(File file)通过打开与实际文件的连接来创建一个FileInputStream对象,参数为文件路径
创建输入流对象时,必须传入一个文件路径,该路径下,若指定文件不存在,会抛出FileNotFoundException
//读取字节数据 //读取字节: //read()方法每次可以读取一个字节的数据,提升为int类型,读到文件末尾时,返回-1. FileInputStream fis = new FileInputStream("read.txt"); int b; //定义变量b,保存数据 while((b = fis.read()) != -1){ //循环读取 sout((char)b); //虽然只读取了一个字节,但是会自动提升为int,所以再强转下去 } fis.close(); //使用字节数组读取: //read(byte[] b) 每次读取b.length个字节到数组中,返回读取到的有效字节个数,到末尾时,返回-1. int len; //定义变量,作为有效字节个数 byte[] b = new byte[1024]; //定义数组,作为字节数据容器 while((len = fis.read(b)) != -1){ //循环读取 sout(new String(b,0,len)); //将读取到的有效部分变成字符串打印 } fis.close();
复制原理
数据源(A.jpg)
1.创建流对象
- 指定数据源
- 指定目的地
2.读写数据
- 定义数组
- 定义有效长度
- 循环读取
- 写出数据
3.关闭资源
- 先开后关原则
目的地(A_copy.jpg)
FileInputStream fis = new FileInputStream("A.jpg"); FileOutputStream fos = new FileOutputStream("A_copy.jpg"); byte[] b = new byte[1024]; int len; while((len = fis.read(b)) != -1){ fos.write(b,0,len); } fos.close(); fis.close();
字符流
用于处理文本文件
Reader java.io.Reader 字符输入流
常用方法:
- close() 关闭流,释放资源
- int read() 读一个字符
- int read(char[ ] cbuf)读多个字符,存在数组中
构造方法:
- FileReader(File file)
- FileReader(String path)
构造时,使用系统默认的字符编码和默认字符缓冲区
Writer java.io.Writer 字符输出流
方法同字节输出流
FileWriter关闭资源时,与FileOutputStream不同
如果不关闭,数据只是保存到缓冲区,并未保存到文件
- flush() 刷新缓冲区,流对象可以继续使用
- close() 关闭流,释放系统资源,关闭前会刷新缓冲区
缓冲流
BufferInputStream BufferOutputStream
BufferReader BufferWriter
基本原理为:在创建流对象时,会创建一个内置的默认大小的缓冲区数组。通过缓冲区读写,减少系统IO次数,提高读写速率
字节缓冲流构造方法:
- BufferInputStream(InputStream in)
- BufferOuputStream(OuputStream out)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("bis.txt"));
字符缓冲流特有方法:
- BufferReader:readLine()读一行
- BufferWriter: newLine()行分隔符 新建时需要传入字符流
转换流--属于字符流
InputStreamReader
构造方法:
- InputStreamReader(InputStream in,String charsetName) 创建指定字符集的字符流,单参数则使用默认字符集
OutputStreamWriter
构造方法:
- OutputStreamWriter(OutputStream out,String charsetName)
序列化流
将对象以字节序列保存在文件中,称之为序列化
将字节序列读取出来,重构为对象,称之为反序列化
序列化操作:一个对象想要序列化,必须满足两个条件
- 该类必须实现java.io.Serializable接口,这是一个标记接口,不实现此类的接口不会使任何状态序列化或反序列化,会抛出NoSerializableException
- 该类的所有属性必须是可序列化的,如果有一个属性不需要可序列化,则改属性必须是瞬态的,使用transient关键字修饰
transient修饰的成员不会被序列化
ObjectOutputStream 序列化流
构造方法:
- ObjectOutputStream(OutputStream out)
FileOutputStream fos = new FileOutputStream("Person.txt"); ObjectOutputStream oos = new ObjectOutputStream(fos);
写出对象方法:
- public final void writeObject(Object obj) 将指定对象写出
ObjectInputStream 反序列化流
构造方法:
- ObjectInputStream (InputStream in)
读取一个对象方法:
- public final Object readObject() 读取一个对象
反序列化操作:
- 如果能找到一个对象的class文件,可以进行反序列化操作
对于jvm可以反序列化的对象,必须是能够找到class文件的类。如果找不到该类的class文件,会抛出ClassNotFoundException异常。若可以找到class文件,但class文件在序列化对象之后被修改,反序列化操作也会失败,抛出InvalidClassException。
InvalidClassException产生的一般原因:
- 该类的序列版本号与从流中读取的类描述符的版本号不匹配
- 该类包含未知的版本类型
- 该类没有可访问的无参数构造方法
Serializable接口给需要序列化的类提供了一个序列版本号SerialVersionUID,改版本号的目的在于验证序列化的对象和对应类是否版本匹配
打印流
在控制台打印输出,调用print/println方法完成,这两个方法都来自与java.io.PrintStream类。此类可以方便打印各种数据类型的值,是一种便捷的输出方式。
PrintStream 字节打印流
构造方法:
- PrintStream(String fileName) 使用指定文件名创建一个新的打印流
- PrintStream(File file)
- PrintStream(OutputStream out)
改变打印流向
System.out是PrintStream类型的,此流向由系统规定,打印在控制台。可通过System.setOut设置打印流流向。
System.out.print(97); //打印在控制台 PrintStream ps = new PrintStream("ps.txt"); System.setOut(ps); System.out.print(97); //在ps.txt中输出97