十二、I/O流
12.1 I/O概述
-
I/O的概述
我们把这种数据的传输,可以看做是一种数据的流动,按照流动的方向,以内存为基准,分为 输入input 和 输出 output ,即流向内存是输入流,流出内存的输出流。
Java中I/O操作主要是指使用 java.io 包下的内容,进行输入、输出操作。输入也叫做读取数据,输出也叫做作写出数据。 -
I/O的分类
- 根据数据的流向分为:输入流和输出流。
输入流 :把数据从其他设备上读取到内存中的流。
输出流 :把数据从内存中写出到其他设备上的流。 - 格局数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。
字符流 :以字符为单位,读写数据的流。
- 根据数据的流向分为:输入流和输出流。
-
I/O流向图解
-
I/O顶级父类
分类 输入流 输出流 字节流 字节输入流(InputStream) 字节输出流(OutputStream) 字符流 字符输入流(Reader) 字符输出流(Writer)
12.2 字节流
-
字节输出流【OutputStream】
java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字 节输出流的基本共性功能方法。- public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
- public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
- public void write(byte[] b) :将 b.length字节从指定的字节数组写入此输出流。
- public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输 出到此输出流。
- public abstract void write(int b) :将指定的字节输出流。
-
FileOutputStream类
java.io.FileOutputStream 类是文件输出流,用于将数据写出到文件。
- 构造函数:
- public FileOutputStream(File file) :创建文件输出流以写入由指定的 File对象表示的文件。
- public FileOutputStream(String name) : 创建文件输出流以指定的名称写入文件。
public class FileOutputStreamConstructor throws IOException { public static void main(String[] args) { // 使用File对象创建流对象 File file = new File("a.txt"); FileOutputStream fos = new FileOutputStream(file); // 使用文件名称创建流对象 FileOutputStream fos = new FileOutputStream("b.txt"); } }
- 写出字节数据
/** * 一.1.利用字节输出流向文件中写出数据 */ public void byteOutput(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\bbb.txt"); try { //true表示追加内容,默认情况下后面内容覆盖前面内容 OutputStream os = new FileOutputStream(file,true); /** * 1. 写出字节(String->Byte .getBytes()) */ os.write(97); //换行 os.write("\r\n".getBytes()); String content = "Hello World!"; //默认全部写出 os.write(content.getBytes()); /** * 2. 写出字节数组 */ os.write("\r\n".getBytes()); byte[] b = "河南科技大学".getBytes(); os.write(b); /** * 3. 写出指定长度字节数组 */ //写出指定字符(注意:空格也算是一个字符!) os.write("\r\n".getBytes()); os.write(content.getBytes(),2,5); os.write("\r\n".getBytes()); os.write(b,1,5); os.close(); } catch (Exception e) { e.printStackTrace(); } }
- 数据追加续写
这两个构造方法,参数中都需要传入一个boolean类型的值, true 表示追加数据, false 表示清空原有数据。 这样创建的输出流对象,就可以指定是否追加续写了。public class byteOutputAppend { public static void main(String[] args) throws IOException { // 使用文件名称创建流对象 FileOutputStream fos = new FileOutputStream("fos.txt",true); // 字符串转换为字节数组 byte[] b = "abcde".getBytes(); // 写出从索引2开始,2个字节。索引2是c,两个字节,也就是cd。 fos.write(b); // 关闭资源 fos.close(); } }
- 写出换行
回车符 \r 和换行符 \n :
1. 回车符:回到一行的开头(return)。
2. 换行符:下一行(newline)。系统中的换行:
1. Windows系统里,每行结尾是 回车+换行 ,即 \r\n ;
2. Unix系统里,每行结尾只有 换行 ,即 \n ;
3. Mac系统里,每行结尾是 回车 ,即 \r 。从 Mac OS X开始与Linux统一。小贴士:
close方法,当完成流的操作时,必须调用此方法,释放系统资源。 - 构造函数:
-
ObjectOutputStream类:该流可以将一个对象写出,或者读取一个对象到程序中,也就是执行了序列化操作。
/** * 一.2.使用对象操作流将对象写出到文件里(序列化) */ public void objectOutputStream(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\fff.txt"); try { OutputStream os = new FileOutputStream(file); Book book1 = new Book("1","红楼梦","曹雪芹",52); Book book2 = new Book("2","西游记","吴承恩",23); List<Book> blist = Arrays.asList(book1,book2); //序列化:讲对象写入到磁盘的过程,就是序列化 ObjectOutputStream oos = new ObjectOutputStream(os); oos.writeObject(blist); oos.close(); os.close(); } catch (Exception e) { e.printStackTrace(); } }
-
字节输入流【InputStream】
java.io.InputStream 抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中。它定义了字节输入 流的基本共性功能方法。- public void close() :关闭此输入流并释放与此流相关联的任何系统资源。
- public abstract int read() : 从输入流读取数据的下一个字节。
- public int read(byte[] b) : 从输入流中读取一些字节数,并将它们存储到字节数组 b中 。
-
FileInputStream类
java.io.FileInputStream 类是文件输入流,从文件中读取字节。-
构造方法
- FileInputStream(File file) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的File对象file命名。
- FileInputStream(String name) : 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件 系统中的路径名name命名。
public class FileInputStreamConstructor throws IOException{ public static void main(String[] args) { // 使用File对象创建流对象 File file = new File("a.txt"); FileInputStream fos = new FileInputStream(file); // 使用文件名称创建流对象 FileInputStream fos = new FileInputStream("b.txt"); } }
- 读取字节数据
/** * 利用字节输入流读取文件中的内容 */ public void byteInput() { File file = new File("F:\\代码\\后端\\JavaSE\\abc\\ccc.txt"); try { InputStream is = new FileInputStream(file); /** * 1. 读取字节 */ //定义变量,保存数据 int b; //循环读取 while ((b = is.read()) != -1){ //b读取的是一堆数字码,强转后才能得到文件里的字符 System.out.print((char)b); } /** * 2. 使用字节数组读取(Byte->String new String()) */ //定义变量,作为有效个数 int len; //定义字节数组,作为装字节数据的容器 byte[] bb = new byte[2]; //循环读取 while ((len = is.read(bb)) != -1){ //每次读取后,把数组变成字符串打印 System.out.println(new String(bb,0,len));//每次读取有效的字节个数 } is.close(); } catch (Exception e) { e.printStackTrace(); } }
-
-
ObjectInputStream类:ObjectInputStream能够让你从输入流中读取Java对象,而不需要每次读取一个字节。你可以把InputStream包装到ObjectInputStream中,然后就可以从中读取对象了。
/** * 二.2.读取文件中的数据(反序列化) */ public void objectInputStream(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\fff.txt"); try { InputStream is = new FileInputStream(file); //反序列化:将磁盘代码读取到代码中 ObjectInputStream ois = new ObjectInputStream(is); Object object = ois.readObject(); if (object != null){ List<Book> blist = (List<Book>) object; for (Book b: blist){ System.out.println(b); } } } catch (Exception e) { e.printStackTrace(); } }
12.3 字符流
Java提供一些字符流类,以字符为单位读写数据,专门用于处理文本文 件。
-
字符输入流【Reader】
java.io.Reader 抽象类是表示用于读取字符流的所有类的超类,可以读取字符信息到内存中。它定义了字符输入 流的基本共性功能方法。- public void close() :关闭此流并释放与此流相关联的任何系统资源。
- public int read() : 从输入流读取一个字符。
- public int read(char[] cbuf) : 从输入流中读取一些字符,并将它们存储到字符数组 cbuf中 。
-
FileReader类
java.io.FileReader 类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。- 构造方法
- FileReader(File file) : 创建一个新的 FileReader ,给定要读取的File对象。
- FileReader(String fileName) : 创建一个新的 FileReader ,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。public class FileReaderConstructor throws IOException { public static void main(String[] args) { // 使用File对象创建流对象 File file = new File("a.txt"); FileReader fr = new FileReader(file); // 使用文件名称创建流对象 FileReader fr = new FileReader("b.txt"); } }
- 读取字符数据
/** * 二.1.利用字符流读取文件中的数据 */ public void fileReader(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\ddd.txt"); try { Reader reader = new FileReader(file); /** * 1. 读取字符 */ //定义变量,保存数据 int b; while ((b = reader.read()) != -1){ System.out.println((char)b); } /** * 2. 使用字符数组读取 */ //定义变量,保存有效字符个数 int len; //定义字符数组,作为装字符数据的容器 char[] cb = new char[2]; //循环读取 while ((len = reader.read(cb)) != -1){ System.out.println(new String(cb)); } reader.close(); } catch (Exception e) { e.printStackTrace(); } }
-
BufferedReader类:从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。 可以指定缓冲区的大小,或者可使用默认的大小。大多数情况下,默认值就足够大了。
/** * 二.2.使用字符缓冲流读取数据 */ public void bufferedReader(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\ddd.txt"); try { Reader reader = new FileReader(file); //创建缓冲流 BufferedReader bf = new BufferedReader(reader); String str = null; while ((str = bf.readLine()) != null){ System.out.print(str); } bf.close(); reader.close(); } catch (Exception e) { e.printStackTrace(); } }
-
字符输出流【Writer】
java.io.Writer 抽象类是表示用于写出字符流的所有类的超类,将指定的字符信息写出到目的地。它定义了字节 输出流的基本共性功能方法。- void write(int c) 写入单个字符。
- void write(char[] cbuf) 写入字符数组。
- abstract void write(char[] cbuf, int off, int len) 写入字符数组的某一部分,off数组的开始索引,len 写的字符个数。
- void write(String str) 写入字符串。
- void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个 数。
- void flush() 刷新该流的缓冲。
- void close() 关闭此流,但要先刷新它。
-
FileWriter类
java.io.FileWriter 类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。- 构造方法
- FileWriter(File file) : 创建一个新的 FileWriter,给定要读取的File对象。
- FileWriter(String fileName) : 创建一个新的 FileWriter,给定要读取的文件的名称。
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
public class FileWriterConstructor { public static void main(String[] args) throws IOException { // 使用File对象创建流对象 File file = new File("a.txt"); FileWriter fw = new FileWriter(file); // 使用文件名称创建流对象 FileWriter fw = new FileWriter("b.txt"); } }
- 写出数据
/** * 一.1利用字符流向文件中写出数据 */ public void fileWriter(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\eee.txt"); try { Writer writer = new FileWriter(file); /** * 1.写出字符 */ writer.write(97); writer.write('b'); writer.write(30000);//田 /** * 2. 写出字符数组 */ //字符串转换为字节数组 char[] chars = "河南科技大学".toCharArray(); //写出字符数组 writer.write(chars); /** * 3. 写出字符串 */ String msg = "王老板"; writer.write(msg); /** * 4. 续写和换行 */ //append设为true,表示可以续写 Writer writer1 = new FileWriter(file,true); //写出字符串 writer1.write("乔"); //写出换行 writer1.write("\r\n"); writer1.write("老师"); writer.close(); } catch (IOException e) { e.printStackTrace(); } }
小贴士:
1.字符流,只能操作文本文件,不能操作图片,视频等非文本文件;
2.当我们单纯读或者写文本文件时使用字符流其他情况使用字节流。
-
BufferedWriter类:将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。
/** * 一.2.使用字符缓冲流写出数据 */ public void bufferedWriter(){ File file = new File("F:\\代码\\后端\\JavaSE\\abc\\fff.txt"); try { Writer writer = new FileWriter(file); //创建缓冲流 BufferedWriter bw = new BufferedWriter(writer); bw.write("中国人民站起来了!"); bw.close(); writer.close(); } catch (IOException e) { e.printStackTrace(); } }