一、java IO流概述 Java IO(输入/输出)流是 Java 提供的用于数据输入和输出的机制,主要用于文件操作、网络通信、数据流处理等。Java IO 以 流(Stream) 的方式处理数据,即数据像水流一样从一个地方流向另一个地方。
File :表示系统中的文件或者文件夹的路径。利用File可以获取文件信息(大小、文件名、修改时间),判断文件的类型,创建文件/文件夹,删除文件/文件夹等操作。
注意:File类只能对文件本身进行操作,不能读写文件里面存储的数据。
IO流 :用于读写文件中的数据(可以读写文件,或网络中的数据)。
IO流的分类 Java IO 流按照不同的标准可以进行不同的分类。
1 按数据流向分类(以程序为参照物)
输入流(Input Stream) :数据从外部流入程序(如从文件读取数据)。
输出流(Output Stream) :数据从程序流出到外部(如将数据写入文件)。
2 按数据类型分类
字节流(Byte Stream) :以 字节(8-bit) 为单位进行数据读写,适用于任何类型的文件(文本、图片、视频等)。
字符流(Character Stream) :以 字符(16-bit Unicode) 为单位进行数据读写,专门用于处理纯文本数据(指能用Windows自带的记事本打开并且能读懂的文件)。
二、IO流的体系 示例图
三、字节流 字节流示例图
1. FileOutputStream FileOutputStream :操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。
书写步骤
创建字节输出流对象
细节1:参数是字符串表示的路径(底层也是将字符串路径变为File对象)或者是File对象都是可以的。如FileOutputStream fos = new FileOutputStream("D:\\a.txt");或者FileOutputStream fos = new FileOutputStream(new File("D:\\a.txt"));
细节2:如果文件不存在会创建一个新的文件,但是要保证父路径是存在的。
细节3:如果文件已经存在,则会清空文件。
写数据
细节:write()方法的参数是整数,但是实际上写到本地文件中的是整数再ASCII上对应的字符。如 97 —> a。
释放资源
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.ryan.iostream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo1 { public static void main (String[] args) throws IOException { FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\a.txt" ); fos.write(97 ); fos.close(); } }
FileOutputStream写数据的3种方式
方法名
说明
void write(ing b)
一次写一个字节数据
void write(byte[] b)
一次写一个字节数组数据
void write(byte[] b, int off, int len)
一次写一个字节数组的部分数据
void write(byte[] b, int off, int len)参数说明
参数1:字节数组
参数2:要写出的数据的起始索引
参数3:要写出的数据的长度
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.ryan.iostream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo2 { public static void main (String[] args) throws IOException { FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\a.txt" ); fos.write(97 ); fos.write(98 ); byte [] bytes = {97 , 98 , 99 , 100 , 101 }; fos.write(bytes); byte [] bytes1 = {97 , 98 , 99 , 100 , 101 }; fos.write(bytes1, 1 , 2 ); fos.close(); } }
FileOutputStream写数据的两个小问题
1. 换行写数据
再次写出一个换行符即可
Windows: \r\n
Linux: \n
Mac:\r
细节:在Windows中,Java对回车换行进行了优化,虽然完整的是\r\n,但是我们写其中一个\r或者\n,Java都可以实现换行,因为Java在底层会补全。但是建议不要省略,补全写。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.ryan.iostream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo3 { public static void main (String[] args) throws IOException { FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\b.txt" ); String str = "ryanlearnjava" ; byte [] bytes1 = str.getBytes(); fos.write(bytes1); String wrap = "\r\n" ; byte [] bytes2 = wrap.getBytes(); fos.write(bytes2); String str2 = "666" ; byte [] bytes3 = str2.getBytes(); fos.write(bytes3); fos.close(); } }
2. 不清空文件,续写数据
在创建FileOutputStream对象的时候,在构造方法中加入第二个参数true即可 ,表示打开续写。
1 FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\b.txt" , true );
FileInputStream:操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中。
书写步骤:
创建字节输入流对象
读数据
细节1:一次读一个字节的数据,读出来的是数据在ASCII上对应的数字。
细节2:read()每执行一次,就会把指向数据的指针向后移动一次。
细节2:读到文件末尾了,read方法返回-1。
释放资源
FileInputStream循环读取
代码演示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package com.ryan.inputstream;import java.io.FileInputStream;import java.io.IOException;public class ByteStreamDemo2 { public static void main (String[] args) throws IOException { FileInputStream fis = new FileInputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\src\\a.txt" ); int b; while ((b = fis.read()) != -1 ) { System.out.println((char ) b); } fis.close(); } }
3. 练习:文件拷贝 核心思想:边读边写
代码演示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.ryan.inputstream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo3 { public static void main (String[] args) throws IOException { FileInputStream fis = new FileInputStream ("D:\\ryan.jpg" ); FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\copy.jpg" ); int b; while ((b = fis.read()) != -1 ) { fos.write(b); } fos.close(); fis.close(); } }
FileInputStream读取问题
IO流:如果拷贝的文件过大,速度会非常慢。因为一次读写一个字节
方法名称
说明
public int read()
一次读一个字节数据
public int read(byte[] buffer)
一次读一个字节数组数据
注意:一次读一个字节数组的数据,每次读取会尽可能把数组填满。
创建字节数组一般是1024的整数倍。
代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.ryan.inputstream;import java.io.FileInputStream;import java.io.IOException;public class ByteStreamDemo4 { public static void main (String[] args) throws IOException { FileInputStream fis = new FileInputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\src\\a.txt" ); byte [] bytes = new byte [2 ]; int len1 = fis.read(bytes); System.out.println(len1); String str1 = new String (bytes, 0 , len1); System.out.println(str1); int len2 = fis.read(bytes); System.out.println(len1); String str2 = new String (bytes, 0 , len2); System.out.println(str2); int len3 = fis.read(bytes); System.out.println(len3); String str3 = new String (bytes, 0 , len3); System.out.println(str3); } } 输出结果(a.txt中的数据是:abcde): 2 ab 2 cd 1 e
拷贝(大文件)改进代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package com.ryan.inputstream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class ByteStreamDemo5 { public static void main (String[] args) throws IOException { long start = System.currentTimeMillis(); FileInputStream fis = new FileInputStream ("D:\\movie.mp4" ); FileOutputStream fos = new FileOutputStream ("D:\\Code\\teacher_han\\Homework\\IOStream\\src\\copy.mp4" ); int b; byte [] bytes = new byte [1024 *1024 *5 ]; while ((b = fis.read(bytes)) != -1 ) { fos.write(bytes, 0 , b); } fos.close(); fis.close(); long end = System.currentTimeMillis(); System.out.println(end - start); } }
四、字符集 字符集(Charset)是用于 字符编码和解码 的规则集合,它定义了字符如何在计算机内部表示。字符集决定了字符的 编码方式 (存储为二进制数据)和 解码方式 (将二进制数据转换回字符)。
编码
特点
适用范围
ASCII
7 位,128 个字符
仅适用于英文
ISO-8859-1
8 位,支持西欧字符
英语和西欧语言
GB2312 / GBK / GB18030
适用于中文
中文文档、应用
Unicode
统一全球字符
适用于所有语言
UTF-8
变长(1~4 字节),兼容 ASCII
网络、Web 开发
UTF-16
2/4 字节,适合存储
Java 内部字符处理
UTF-32
4 字节,存储浪费
很少使用
在 Java 开发中,推荐使用 UTF-8 ,避免乱码问题!
编码:就是将要存储的数据变成真正的能存储在硬盘当中的字节数据。
为什么会有乱码?
读取数据时未读完整个汉字
编码和解码时的方式不统一
如何不产生乱码?
不要用字节流 读取文本文件
编码解码时使用同一个码表,同一个编码方式。
Java中编码的方法
String类中的方法
说明
public byte[] getBytes()
使用默认方式进行编码
public byte[] getBytes(String charsetName)
使用指定方式进行编码
java中解码的方法
String类中的方法
说明
String(byte[] bytes)
使用默认方式进行解码
String(byte[] bytes, String charsetName)
使用指定方式进行解码
代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 package com.ryan.chatset;import java.io.UnsupportedEncodingException;import java.util.Arrays;public class CharsetDemo1 { public static void main (String[] args) throws UnsupportedEncodingException { String str = "ai你哟" ; byte [] bytes1 = str.getBytes(); System.out.println(Arrays.toString(bytes1)); byte [] bytes2 = str.getBytes("GBK" ); System.out.println(Arrays.toString(bytes2)); String str2 = new String (bytes1); System.out.println(str2); String str3 = new String (bytes1, "GBK" ); System.out.println(str3); } }
五、字符流 字符流:底层其实还是字节流。
字符流 = 字节流 + 字符集
特点
输入流:一次读一个字节,遇到中文时,一次读多个字节。
输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中。
使用场景
对于纯文本文件进行读写操作。
字符流示例图
1. FileRreader 步骤
创建字符输入流对象
构造方法
说明
public FileReader(File file)
创建字符输入流关联本地文件
public FileReader(String pathname)
创建字符输入流关联本地文件
细节1:如果文件不存在,就直接报错
读取数据
成员方法
说明
public int read()
读取数据,读到末尾返回-1
public int read(char[] buffer)
读取多个数据,读到末尾返回-1
细节1:按字节进行读取,遇到中文,一次读多个字节 ,读取后解码,返回一个十进制整数。
细节2:读到文件末尾了,read方法返回-1
释放资源
空参read()方法代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ryan.chatset;import java.io.FileReader;import java.io.IOException;public class CharsetDemo2 { public static void main (String[] args) throws IOException { FileReader fr = new FileReader ("src\\a.txt" ); int ch; while ((ch = fr.read()) != -1 ) { System.out.println(ch); System.out.print((char )ch); } } }
空参的read方法:读取数据+解码。
所以如果想看到中文的打印结果,还需要我们进行强制转换。
有参read(char[] chars)方法代码实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.ryan.chatset;import java.io.FileReader;import java.io.IOException;public class CharsetDemo3 { public static void main (String[] args) throws IOException { FileReader fr = new FileReader ("src\\a.txt" ); char [] chars = new char [2 ]; int len; while ((len = fr.read(chars)) != -1 ) { System.out.print(new String (chars, 0 , len)); } fr.close(); } }
有参的read方法:读取数据,解码,强制转换三步合并了,把强制转换后的字符放到数组当中。
2. FileWriter 构造方法 、
构造方法
说明
public FileWriter(File file)
创建字符输出流关联本地文件
public FileWriter(String pathname)
创建字符输出流关联本地文件
public FileWriter(File file, boolean append)
创建字符输出流关联本地文件,续写
public FileWriter(String pathname, boolean append)
创建字符输出流关联本地文件,续写
FileWriter书写细节
创建字符输出流对象
细节1:参数是字符串表示的路径或者File对象都是可以的
细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关。
写数据
细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数再字符集上对应的字符。
释放资源
3. 字符流原理解析 字符输入流原理解析
创建字符输入流对象
底层:关联文件,并创建缓冲区(长度为8192的字节数组)
读取数据
字符输出流原理解析
成员方法
说明
public void flush()
将缓冲区中的数据,刷新到本地文件中
public void close()
释放资源/关流
flush刷新: 刷新之后,还可以继续往文件中写出数据。
close关流: 断开通道,无法再往文件中写出数据。
创建字符输出流对象
底层:关联文件,并创建缓冲区(长度为8192的字节数组)
写出数据
数据什么时候真正的保存到本地文件中?
缓冲区装满了,自动保存到本地文件。
手动刷新,使用flush()方法。
释放资源/关流 close()方法。
六、字节流和字符流的使用场景 字节流
拷贝任意类型 的文件
字符流
读取纯文本文件 中的数据
往纯文本文件 中写出数据
习题1 - 拷贝文件夹
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package com.ryan.chatset;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;public class Test01 { public static void main (String[] args) throws IOException { File src = new File ("D:\\src" ); File dest = new File ("D:\\dest" ); copydir(src, dest); } private static void copydir (File src, File dest) throws IOException { dest.mkdir(); File[] files = src.listFiles(); for (File file : files) { if (file.isFile()) { FileInputStream fis = new FileInputStream (src); FileOutputStream fos = new FileOutputStream (new File (dest, file.getName())); byte [] bytes = new byte [1024 ]; int len; while ((len = fis.read(bytes)) != -1 ) { fos.write(bytes, 0 , len); } fos.close(); fis.close(); } else { copydir(src, new File (dest, file.getName())); } } } }
七、高级流 体系图
八、缓冲流 体系图
1. 字节缓冲流 原理:底层自带了长度为8192的缓冲区提高性能
字节缓冲流的构造方法
方法名称
说明
public BufferedInputStream(InputStream is)
把基本流包装成高级流,提高读取数据的性能
pubic BufferedOutputStream(OutputStream os)
把基本流包装成高级流,提高写出数据的性能
练习:利用字节缓冲流拷贝文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ryan.bufferedstream;import java.io.*;public class BufferedStreamDemo1 { public static void main (String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream (new FileInputStream ("src\\a.txt" )); BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream ("src\\b.txt" )); int b; while ((b = bis.read()) != -1 ) { bos.write(b); } bos.close(); bis.close(); } }
一次拷贝多个字节
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package com.ryan.bufferedstream;import java.io.*;public class BufferedStreamDemo2 { public static void main (String[] args) throws IOException { BufferedInputStream bis = new BufferedInputStream (new FileInputStream ("src\\a.txt" )); BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream ("src\\b.txt" )); byte [] bytes = new byte [1024 ]; int len; while ((len = bis.read(bytes)) != -1 ) { bos.write(bytes, 0 , len); } bos.close(); bis.close(); } }
字节缓冲流提高效率的原理
示例图
创建的缓冲区是在内存中执行的,内存执行是非常快的,所以字节缓冲流节省的是内存和硬盘之间打交道的时间。没必要没读取一个字节就从硬盘的文件中读取一次,而是从已经被尽可能填满的缓冲区中进行读取。
2. 字符缓冲流 原理:底层自带了长度为8192的缓冲区提高性能 (但是实际上字符流底层自带了缓冲区,所以字符缓冲流提高的性能不是很明显)。
字符缓冲流的构造方法
方法名称
说明
public BufferedReader(Reader r)
把基本流变成高级流
public BufferedWriter(Writer w)
把基本流变成高级流
字符缓冲流特有方法
字符缓冲输入流特有方法
说明
public String readLine()
读取一行 数据,如果没有数据可读了,会返回null
字符缓冲输出流特有方法
说明
public void newLine()
跨平台的换行
字符缓冲输入流代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package com.ryan.bufferedstream;import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException;public class BufferedStreamDemo3 { public static void main (String[] args) throws IOException { BufferedReader br = new BufferedReader (new FileReader ("src\\a.txt" )); String line; while ((line = br.readLine()) != null ) { System.out.println(line); } br.close(); } }
字符缓冲输出流代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.ryan.bufferedstream;import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException;public class BufferedStreamDemo4 { public static void main (String[] args) throws IOException { BufferedWriter bw = new BufferedWriter (new FileWriter ("src\\b.txt" )); bw.write("123" ); bw.newLine(); bw.write("456" ); bw.newLine(); bw.close(); } }
打开续写:BufferedWriter bw = new BufferedWriter(new FileWriter(“src\b.txt”, true));
BufferedWriter没有打开续写的功能,所以要在FileWriter中打开。
九、转换流 转换流属于字符流,用于 字节流 和 字符流 之间的转换,主要用于处理 不同编码格式的文本数据 ,防止乱码问题。
InputStreamReader:将 字节输入流 转换为 字符输入流 (解码 )。
OutputStreamWriter:将 字符输出流 转换为 字节输出流 (编码 )。
作用 :
让 InputStream(字节流) 能够以 字符 方式读取数据。
让 OutputStream(字节流) 能够以 字符 方式写入数据。
处理 不同字符编码 ,如 UTF-8、GBK。
字节流想要使用字符流中的方法
InputStreamReader(字节流 → 字符流)
构造方法
1 2 public InputStreamReader (InputStream in) public InputStreamReader (InputStream in, String charsetName)
OutputStreamWriter(字符流 → 字节流)
构造方法
1 2 public OutputStreamWriter (OutputStream out) public OutputStreamWriter (OutputStream out, String charsetName)
练习一 转换文件编码
需求1:手动创建一个GBK文件,把文件中的中文读取到内存中,不能出现乱码。
需求2:把一段中文按照GBK的方式写到本地文件
需求3:将本地文件中的GBK文件,转成UTF-8
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package com.ryan.convertstream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.nio.charset.Charset;public class ConvertStreamDemo3 { public static void main (String[] args) throws IOException { FileReader fr = new FileReader ("src\\a.txt" , Charset.forName("GBK" )); FileWriter fw = new FileWriter ("src\\b.txt" , Charset.forName("UTF-8" )); int b; while ((b = fr.read()) != -1 ) { fw.write(b); } fw.close(); fr.close(); } }
练习二 读取文件中的数据
利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.ryan.convertstream;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;public class ConvertStreamDemo4 { public static void main (String[] args) throws IOException { BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream ("src\\a.txt" ))); String line; while ((line = br.readLine()) != null ) { System.out.println(line); } br.close(); } }
十、序列化流和反序列化流 序列化流也是高级流,也是用来包装基本流的,属于字节流的一种。
序列化(Serialization) 是指 将 Java 对象转换为字节流 以便存储到文件或通过网络传输。反序列化(Deserialization) 是指 从字节流恢复 Java 对象 。
2. 序列化的核心类
类
作用
ObjectOutputStream
对象序列化 (写入文件/网络)
ObjectInputStream
对象反序列化 (读取对象)
1. 序列化流/对象造作输出流 可以把Java中的对象写到本地文件中 ,而且写到文件中的内容我们是看不懂的
构造方法
说明
public ObjectOutputStream(OutputStream out)
把基本流包装成高级流
成员方法
说明
public final writeObject(Object obj)
把对象序列化(写出)到文件中去
序列化流的小细节
使用对象输出流将对象保存到文件时会出现NotSerializableException异常
解决方案:需要让Javabean类实现Serializable接口
JavaBean 是一种 符合特定规范的 Java 类 ,主要用于封装数据,并可在 Web 开发、GUI 开发(如 JSP、Spring、JavaFX) 中使用。
JavaBean 特点:
必须有一个无参构造方法 (方便反射创建实例)。
所有属性都是私有(private) ,不能直接访问。
提供 getter 和 setter 方法 访问属性。
可序列化(通常实现 Serializable 接口) ,便于存储和传输。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package com.ryan.objectstream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;import java.io.Serializable;public class ObjectStreamDemo1 { public static void main (String[] args) throws IOException { Student stu = new Student ("zhangsan" , 23 ); ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("src\\a.txt" )); oos.writeObject(stu); oos.close(); } } class Student implements Serializable { private String name; private int age; public Student () { } public Student (String name, int age) { this .name = name; this .age = age; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } }
2. 反序列化流/对象操作输入流 可以把序列化到本地文件中的对象,读取到程序中来
构造方法
说明
public ObjectInputStream(InputStream in)
把基本流变成高级流
成员方法
说明
public Object readObject()
把序列化到本地文件中的对象,读取到程序中
3. 序列化流/反序列化流的细节汇总
使用序列化流将对象写到文件时,需要让javabean类实现Serializable接口,否则会出现NotSerializableException异常
序列化流写到文件中的数据是不能修改的,一旦修改就无法再次读回来了。
序列化对象后,修改了Javabean类,再次反序列化,会不会有问题?
会出问题,会抛出InvalidClassException异常
解决方法:给Javabean类添加serialVersionUID(序列号、版本号)
如果一个对象中的某个成员变量的值不想被序列化,又该如何实现?
解决方法:给该成员变量添加transient关键字(瞬态关键字)修饰,该关键字标记的成员变量不参与序列化过程。
练习 - 用对象流读写多个对象
需求:将多个自定义对象序列化到文件中,但是由于对象的个数不确定,反序列化流该如何读取?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 1. 序列化代码package com.ryan.objectstream;import java.io.*;import java.util.ArrayList;public class Test { public static void main (String[] args) throws IOException { Teacher t1 = new Teacher ("zhangsan" , 23 , "南京" ); Teacher t2 = new Teacher ("lisi" , 24 , "重庆" ); Teacher t3 = new Teacher ("zhangsan" , 25 , "北京" ); ArrayList<Teacher> list = new ArrayList <>(); list.add(t1); list.add(t2); list.add(t3); ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("src\\a.txt" )); oos.writeObject(list); oos.close(); } } 2. 反序列化代码package com.ryan.objectstream;import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.util.ArrayList;public class Test01 { public static void main (String[] args) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("src\\a.txt" )); ArrayList<Teacher> list = (ArrayList<Teacher>) ois.readObject(); for (Teacher teacher : list) { System.out.println(teacher); } ois.close(); } } 3. Javabean类package com.ryan.objectstream;import java.io.Serializable;public class Teacher implements Serializable { private static final long serialVersionUID = -8095654425841779262L ; private String name; private int age; private String address; public Teacher () { } public Teacher (String name, int age, String address) { this .name = name; this .age = age; this .address = address; } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } public String getAddress () { return address; } public void setAddress (String address) { this .address = address; } @Override public String toString () { return "Teacher{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}' ; } }
十一、打印流 打印流也是高级流,用来包装基本流,打印流不能读,只能写 ,所以打印流只有输出流。
分类: 打印流一般是指:PrintStream(字节打印流), PrintWriter(字符打印流)两个类
特点
打印流只操作文件目的地,不操作数据源。
特有的写出方法 可以实现数据原样写出
特有的写出方法 ,可以实现自动刷新,自动换行。
打印一次数据 = 写出 + 换行 + 刷新
1. 字节打印流
构造方法
说明
public PrintStream(OutputStream/File/String)
关联字节输出流/文件/文件路径
public PrintStream(String fileName, Charset harset)
指定字符编码
public PrintStream(OutputStream out, boolean autoFlush)
自动刷新
public PrintStream(OutputStream out, boolean autoFlush, String enconding)
指定字符编码且自动刷新
字节流底层没有缓冲区,所以开不开自动刷新都一样。
成员方法
说明
public void write(int b)
常规方法:将指定的字节写出
public void println(Xxx xx)
特有方法:打印任意数据,自动刷新,自动换行
public void print(Xxx xx)
特有方法:打印任意数据,不换行
public void printf(String fomat, Object… args)
特有方法:带占位符的打印语句,不换行
2. 字符打印流
构造方法
说明
public PrintWriter(Write/File/String)
关联字节输出流/文件/文件路径
public PrintWriter(String fileName, Charset charset)
指定字符编码
public PrintWriter(Write w, boolean, autoFlush)
自动刷新
public PrintWriter(OutputStream out, boolean autoFlush, Charset charset)
指定字符编码且自动刷新
字符打印流底层有缓冲区,想要自动刷新需要开启。
成员方法
说明
public void write(int b)
常规方法:将指定的字节写出
public void println(Xxx xx)
特有方法:打印任意数据,自动刷新,自动换行
public void print(Xxx xx)
特有方法:打印任意数据,不换行
public void printf(String fomat, Object… args)
特有方法:带占位符的打印语句,不换行
十二、解压缩流/压缩流 1. 解压缩流 解压本质:把每个ZipEntry按照层级拷贝到本地另一个文件夹中。
2. 压缩流 压缩本质:把每一个(文件/文件夹)看成ZipEntry对象,放到压缩包中。
十三、常用工具包 Commons-io Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包。
作用:提高IO流的开发效率
使用步骤
在项目中创建一个文件夹:lib
将jar包复制粘贴到lib文件夹
右键点击jar包,选择Add as Library -> 点击OK
在类中导包使用
Commons-io常见方法