切换主题
十八、IO
一、IO流的体系

二、字节流
1、字节输入输出流

(1)FileOutStream
java
//创建对象
FileOutStream fos = new FileOutStream("myio\\a.txt");
//写出数据
fos.write(97);
//释放资源
fos.close();
写入方式
方法名称 | 说明 |
---|---|
void write(int b) | 一次写一个数据 |
void write(byte[] b) | 一次写一个字节数组数据 |
void write(byte[] b,int off,int len) | 一次写一个字节数组的部分数据 |
换行
java
FileOutStream fos = new FileOutStream("myio\\a.txt");
//第一段话输出.......
//换行
String wrap="\r\n";
fos.write(wrap.getBytes());
//第二段话输出.......
续写
java
FileOutStream fos = new FileOutStream("myio\\a.txt",true);
(2)FileInputStream
操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来
java
//创建对象
FileInputStream fos = new FileInputStream("myio\\a.txt");
//读数据
char ch=(int)fos.read();
//释放资源
fos.close();
一次读取多个字节
方法名称 | 说明 |
---|---|
public int read() | 一次读一个字节数据 |
public int read(byte[] buffer) | 一次读一个字节数组数据 |
java
int len;
byte[] bytes = new byte[2];
len = fis.read(bytes);
System.out.println(new String(bytes,0,len));
len = fis.read(bytes);
2、字节缓冲流

(1)BufferedInputStream
方法名称 | 说明 |
---|---|
public BufferedInputStream(InputStream is) | 把基本流包装成高级流,提高读取数据的性能 |
(2)BufferedOutputStream
构造方法
方法名称 | 说明 |
---|---|
public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
成员方法
方法名称 | 说明 |
---|---|
flush | 刷新此缓冲的输出流 |
write(int[] b,int off,int len) | 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此缓冲的输出流 |
write(int b) | 将指定的字节写入此缓冲的输出流 |
一次读取一个字节
java
BufferedInputStream bis =new BufferedInputStream(new FileInputStream("myio\\a.txt"));
BufferedOutputStream bos =new BufferedOutputStream(new FileOutputStream("myio\\copy.txt"));
int b;
while((b=bis.read())!=-1){
bos.write(b);
}
bos.close();
bis.close();
一次读取多个字节
java
BufferedInputStream bis =new BufferedInputStream(new FileInputStream("myio\\a.txt"));
BufferedOutputStream bos =new BufferedOutputStream(new FileOutputStream("myio\\copy.txt"));
byte[] bytes = new byte[1024];
int len;
while((len = bis.read(bytes))!=-1){
bos.write(b,0,len);
}
bos.close();
bis.close();
三、try...catch自动回收资源
java
//创建对象
FileInputStream fos1 = new FileInputStream("myio\\a.txt");
FileInputStream fos2 = new FileInputStream("myio\\a.txt");
try(fos1;fos2){
//操作
}catch(IOException e){
//操作
}
四、字符流
1、字符输入输出流
特点:
- 输入流:一次读一个字节,遇到中文时,一次读多个字节
- 输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中

(1)FileReader
操作本地文件的字符输入流
构造方法
方法名称 | 说明 |
---|---|
public FileReader(File file) | 创建字符输入流关联本地文件 |
public FileReader(String pathname) | 创建字符输入流关联本地文件 |
成员方法
方法名称 | 说明 |
---|---|
public int read() | 读取数据,读到末尾返回-1 |
public int read(char[] buffer) | 读取多个数据,读到末尾返回-1 |
空参
javaFileReader fr = new FileReader("路径"); int ch; while((ch=fr.read()) != -1){ System.out.println((int)ch); } fr.close();
有参
javaFileReader fr = new FileReader("路径"); char[] chars = new char[2]; int len; while((len=fr.read(chars)) != -1){ System.out.println(new String(chars,0,len)); }
(2)FileWriter
操作本地文件的字符输出流
构造方法
构造方法 | 说明 |
---|---|
public FileWriter(File file) | 创建字符输出流关联本地文件 |
public FileWriter(String pathname) | 创建字符输出流关联本地文件 |
public FileWriter(File file,boolean append) | 创建字符输出流关联本地文件,续写 |
public FileWriter(String pathname, boolean append) | 创建字符输出流关联本地文件,续写 |
成员方法
成员方法 | 说明 |
---|---|
void write() | 写出一个字符 |
void write(String str) | 写出一个字符串 |
void write(String str,int off ,int len) | 写出一个字符串的一部分 |
void write(char[] cbuf) | 写出一个字符数组 |
void write(char[ cbuf,int off ,int len) | 写出字符数组的一部分 |
(3)案例
拷贝文件夹
main
函数
java
public static void main(String[] args) throws IOException {
File src=new File("E:\\code\\java\\代码\\File2\\caogao");
File dest=new File("E:\\code\\java\\代码\\File2\\caogao2\\ccc");
copyDir(src,dest);
}
copyDir
函数
java
public static void copyDir(File src, File dest) throws IOException {
dest.mkdir();
//遍历文件夹所有元素
for (File file : src.listFiles()) {
//文件的处理
if (file.isFile()) {
//目标文件输入流
FileReader fr = new FileReader(file);
//copy文件输出流
FileWriter fw = new FileWriter(new File(dest, file.getName()));
char[] chars = new char[2];
int len;
while ((len = fr.read(chars)) != -1) {
fw.write(chars, 0, len);
}
fw.close();
fr.close();
} else {
copyDir(file, new File(dest, file.getName()));
}
}
}
2、字符缓冲流

(1)BufferedReader
特有方法
字符缓冲输入流特有方法 | 说明 |
---|---|
public String readLine() | 读取一行数据,如果没用数据可读了,会返回null |
java
BufferedReader br=new BufferedReader(new FileReader("myio\\a.txt"));
String line;
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
(2)BufferedWriter
特有方法
字符缓冲输出流特有方法 | 说明 |
---|---|
public void newLine() | 跨平台的换行 |
java
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
bw.write("123");
bw.newLine();
bw.write("456");
bw.newLine();
bw.close();
续写
java
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt",true));
五、转换输入输出流
1、InputStreamReader
指定编码格式为GBK
方式一(不推荐)
java
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");
int ch;
while ((ch=isr.read())!=-1){
System.out.println((char) ch);
}
isr.close();
方式二(推荐)
java
FileReader fr = new FileReader("myio\\file.txt", Charset.forName("GBK"));
int ch;
while ((ch=fr.read())!=-1){
System.out.println((char) ch);
}
fr.close();
2、OutputStreamWriter
方式一(不推荐)
java
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),"GBK");
osw.write("你好");
isr.close();
方式二(推荐)
java
FileWriter fw = new FileWriter("myio\\file.txt", Charset.forName("GBK"));
fw.write("你好");
fw.close();
六、序列化流和反序列化流
1、ObjectOutputStream
可以把java的对象写到本地文件中
(1)构造方法
构造方法 | 说明 |
---|---|
public ObjectOutputStream(OutputStream out) | 把基本流包装成高级流 |
(2)成员方法
成员方法 | 说明 |
---|---|
public final void writeObject(Object obj) | 把对象序列化(写出)到文件中去 |
(3)实操
使用对象输出流将对象保存到文件时会出现NotSerializableException
异常
解决方案:需要让Javabean类实现Serializable
接口
Student
类
java
public class Student implements Serializable{}
main
方法
java
Student stu = new Student("zhangsan,23");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("myio\\a.txt"));
oos.writeObject(stu);
oos.close();
2、ObjectInputStream
可以把序列化到本地文件中对象,读取到程序中来
(1)构造方法
构造方法 | 说明 |
---|---|
public ObjectInputStream(InputStream out) | 把基本流变成高级流 |
(2)成员方法
成员方法 | 说明 |
---|---|
public Object readObject() | 把序列化到本地文件中的对象,读取到程序中来 |
(3)实操
java
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("myio\\a.txt"));
Student o = (Student) ois.readObject();
ois.close();
3、序列化版本号
(1)方式一(手动加)
可在实体类Student
中加
java
private static final long serialVersionUID = 1L;
(2)方式二(idea配置)
1、配置

2、鼠标光标放到类名上面,alt
+回车
,自动生成serialVersionUID

4、自定义实体类序列化属性
想让实体类某一个属性不被序列化,使用transient
瞬态关键字
java
private transient String address;
七、打印流
分类:打印流一般是指:PrintStream
、PrintWriter
两个类
特点:
- 打印流只操作文件目的地,不操作数据源
- 特有的写出方法可以实现,数据原样写出
- 特有的写出方法,可以实现自动刷新,自动换行
1、PrintStream
(1)构造方法
构造方法 | 说明 |
---|---|
public PrintStream(OutputStream/File/String) | 关联字节输出流/文件/文件路径 |
public PrintStream(String filename,Charset charset) | 指定字符编码 |
public PrintStream(OutputStream out ,boolean autoFlush) | 自动刷新 |
public PrintStream(OutputStream out ,boolean autoFlush,String encoding) | 指定字符编码且自动刷新 |
(2)成员方法
成员方法 | 说明 |
---|---|
public void write(int b) | 常规方法:规则跟之前一样,将指定的字节写出 |
public void println(Xxx xx) | 特有方法:打印任意数据,自动刷新,自动换行 |
public void print(Xxx xx) | 特有方法:打印任意数据,不换行 |
public void printf(String format,Object ...args) | 特有方法:带有占位符的打印语句,不换行 |
2、PrintWriter
(1)构造方法
构造方法 | 说明 |
---|---|
public PrintWriter(Writer/File/String) | 关联字节输出流/文件/文件路径 |
public PrintWriter(String fileName ,Charset charset) | 指定字符编码 |
public PrintWriter(Write w , boolean autoFlush) | 自动刷新 |
public PrintWriter(OutputStream out , boolean autoFlush ,Charset charset) | 指定字符编码且自动刷新 |
(2)成员方法
成员方法 | 说明 |
---|---|
public void write(int b) | 常规方法:规则跟之前一样,写成字节或者字符串 |
public void println(Xxx xx) | 特有方法:打印任意类型的数据且换行 |
public void print(Xxx xx) | 特有方法:打印任意类型数据,不换行 |
public void printf(String format,Object ...args) | 特有方法:带有占位符的打印语句 |
八、解压缩流/压缩流
1、案例
(1)解压
main
方法
java
File src = new File("caogao.zip");
File dest = new File("caogao\\");
unZip(src,dest);
unzip
方法
java
public static void unZip(File src, File dest) throws IOException {
ZipInputStream zis=new ZipInputStream(new FileInputStream(src));
ZipEntry entry;
while ((entry=zis.getNextEntry())!=null){
//如果是文件夹
if(entry.isDirectory()){
File file =new File(dest,entry.getName());
file.mkdir();
}else {
File file =new File(dest,entry.getName());
FileOutputStream fos =new FileOutputStream(file);
int b;
while ((b=zis.read())!=-1){
fos.write(b);
}
fos.close();
zis.closeEntry();
}
}
zis.close();
}
(2)压缩
zos.putNextEntry(zipEntry);
这一步应该在压缩流开始写入数据之前调用。
在使用 ZipOutputStream
进行文件压缩时,每个压缩条目(文件或目录)之前都需要调用 putNextEntry()
方法来开始一个新的压缩条目。这样做会告诉 ZipOutputStream
开始为下一个文件或目录写入数据。因此,在你开始向 ZipOutputStream
中写入数据之前,应该先调用 putNextEntry()
方法。
压缩单个文件
main
方法javaFile src= new File("caogao\\b.txt"); File dest=new File("caogao\\"); toZip(src,dest);
tozip
方法javapublic static void toZip(File src, File dest) throws IOException { //压缩流关联压缩对象 ZipOutputStream zos=new ZipOutputStream(new FileOutputStream(new File(dest,"b.zip"))); ZipEntry zipEntry =new ZipEntry("b.txt"); zos.putNextEntry(zipEntry); FileInputStream fis=new FileInputStream(src); int b; while ((b=fis.read())!=-1){ zos.write(b); } fis.close(); zos.closeEntry(); zos.close(); }
压缩文件夹
main
方法javaFile src = new File("caogao\\caogao"); File destParent = src.getParentFile(); //压缩流关联压缩后的文件 File dest = new File(destParent, src.getName() + ".zip"); ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest)); toZip(src, zos, src.getName()); zos.close();
toZip
方法javapublic static void toZip(File src, ZipOutputStream zos, String name) for (File file : src.listFiles()) { //如果是文件 if (file.isFile()) { ZipEntry zipEntry = new ZipEntry(name + "\\" + file.getName()); zos.putNextEntry(zipEntry); FileInputStream fis = new FileInputStream(file); int b; while ((b = fis.read()) != -1) { zos.write(b); } fis.close(); zos.closeEntry(); } else { //如果是文件夹,就递归 toZip(file, zos, name + "\\" + file.getName()); } } }
九、commons-io
链接:https://www.123pan.com/s/QvTuVv-QlVw.html