IO流知识点

IO流概述

1.什么是IO流

存储和读取数据的解决方案

I:input O:output

流:像水一样传输数据

2.IO流的作用

用于读写数据(本地文件,网络)

3.IO按照流向可以分为哪两种流

输出流:程序 ——> 文件

输入流:文件 ——> 程序

4.IO流按照操作文件的类型可以分类成哪两种流

字节流:可以操作所有类型的文件

字符流:只能操作纯文本文件

5.什么是纯文本文件

用windows系统自带的记事本打开并且能读懂的文件

txt文件,md文件,xml文件,lrc文件等。

FileOutputStream

FileOutputStream原理

操作本地文件的字节输出流,可以把程序种的数据写到本地文件中。

书写步骤:

  • 创建字节输出流对象

    • 细节1:参数是字符串表示的路径或是File对象都是可以的

    • 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的

    • 细节3:如果文件已经存在,则会清空文件

  • 写数据

    • 细节:write方法的参数是整数,但是实际上写到本地文件中的整数是在ASCII上对应的字符

  • 释放数据

    • 细节:每次使用完流之后都到释放资源

FileOutputStream写数据的3种方式

方法名称说明
void write(int b)一次写一个字节数据
void write(byte[] b)一次写一个字节数组数据
void write(byte[] b, int off, int len)一次写一个字节数组的部分数据

FileOutputStream换行写和续写

换行写:
  • 再次写出一个换行符就可以了

    • windows: \r\n

    • Linux: \n

    • Mac: \r

细节:

在windows操作系统当中,java对回车换行进行了优化。 ​ 虽然完整的是\r\n,但是我们写其中一个\r或者\n ​ java也可以实现换行,因为java在底层会补全

建议:

不要省略,还是写全了。

续写:

如果想要续写,打开续写开关即可。 ​ 开关位置:创建对象的第二个参数 ​ 默认false:表示关闭续写,此时创建对象会清空文件 ​ 手动传递true:表示打开续写,此时创建对象不会清空文件

总结

  • FileOutputStream的作用

    • 可以把程序中的数据写到本地文件上,是字节流的基本流。

  • 书写步骤

    • 创建对象,写出数据,释放资源

  • 三步操作的细节

    • 创建对象:文件存在、文件不存在、追加写入

    • 写出数据:写出整数、写出字节数据、换行写

    • 释放资源:关闭通道

FileInputStream

FileInputStream原理

操作本地文件的字节输入流,可以把本地文件中的数据读取到程序中来。

书写步骤:

  • 创建字节输入流对象

    • 细节1:如果文件不存在,就直接报错。

      • java为什么会这么设计呢?

      • 输出流:不存在文件,创建一个

        • 把数据写到文件当中

      • 输入流:不存在文件,而是报错呢?

        • 因为创建出来的文件是没有数据的,没有任何意义。

        • 所以java就没有设计这种无意义的逻辑,文件不存在直接报错。

      • 程序中最重要的是:数据。

  • 读取数据

    • 细节1:一次读取一个字节,读取出来的是数据在ASCII上对应的数字

    • 细节2:读到文件末尾了,read方法返回-1

  • 释放资源

    • 细节:每次使用完之后都要释放资源。

FileInputStream循环读取

案例:

//创建对象
FileInputStream fis = new FileInputStream("D:\\Code\\myio\\myIo\\a.txt");
//循环读取
int b ;
while ((b = fis.read()) != -1 ){
    System.out.println((char) b);
}
//释放资源
fis.close();

错误案例:

//read:表示读取数据,而且是读取一次数据就移动一次指针
//创建对象
FileInputStream fis = new FileInputStream("D:\\Code\\myio\\myIo\\a.txt");
//循环读取
while ((fis.read()) != -1 ){
    System.out.println(fis.read());//只返回部分的数据
}
//释放资源
fis.close();

FileInputStream读取的问题

IO流:如果拷贝的文件过大,那么速度会不会又影响?

方法名称说明
public int read()一次读一个字节数据
public int read(byte[] buffer)一个读一个字节数组数据

注意:一次读一个字节数组的数据,每次读取会尽可能把数组装满

一般都用:1024的整数倍 1024 * 1024 * 5

		byte[] bytes = new byte[2];
//一次读取多个字节数据,具体读多少,跟数组的长度有关
        //返回值:本次读取到了多少个字节数据
        int len1 = fis.read();
        System.out.println(len1);
//这里表示的是读取个数,并且他是从0位置进行读取,且读取很len1长。
        String str1 = new String(bytes,0,len1);
        System.out.println(str1);

字符集

字符集详解: (ASCII,GBK)

1、在计算机中,任意数据都是以二进制的形式来存储的。

2、计算机中最小的存储单元是一个字节

3、ASCII字符集中,一个英文在一个字节

4、简体中文版Windows,默认是使用GBK字符集

5、GBK字符集完全兼容ASCII字符集

一个英文占一个字节,二进制第一位是0.

一个中文占两个字节,二进制高位字节的第一位是1.

字符集详解: (Unicode)

1、Unicode字符集的UTF-8编码格式

一个英文占一个字节,二进制第一位是0,转成十进制是正数

一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数

2、UTF不是字符集,只是一种编码格式

乱码

为什么会有乱码?

1、读取数据时未读完整个汉字。字节流:一个读取一个字节

2、编码和解码时的方式不统一

如何不产生乱码?

1、不要用字节流读取文本文件

2、编码解码时使用一个码表,同一个编码方式

扩展

字节流读取中文会乱码,但是为什么拷贝不会乱码呢?

因为他是整个文本中的字节读取并写出的。

Java中编码和解码的实现

Java中编码的方法

public byte[] getBytes()								使用默认方式进行编码
public byte[] getBytes(String charsetName)				使用指定方式进行编码

Java中解码的方法

String (byte[] bytes)							使用默认方式进行解码
String (byte[] bytes, String charsetName)    	使用指定方式进行解码

案例:

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class study1 {
    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);
        
    }
}

字符流

字符流概述

字节流的底层其实就是字节流

字符流 = 字节流 + 字符集

特点

输入流:一次读一个字节,遇到中文时,一个读多个字节

输出流:底层会把数据按照指定的编码方式进行编码,变成字节再写到文件中。

使用场景

对于纯文本文件进行读写操作

FileReader

第一步:创建对象
public  FileReader(File file)                            创建字符输入流关联本地文件
public  FileReader(String pathname)                      创建字符输入流关联本地文件
第二步:读取数据
public  int  read()                               读取数据,读到末尾返回-1
public  int  read(char[] buffer)                  读取多个数据,读到末尾返回-1

字符流的底层也是字节流,默认也是一个字节一个字节的读取的。

如果遇到中文就会一次读取多个,GBK一次读取两个字节,UTF—8一次读三个字节

read()细节:

1、read():默认也是一个字节一个字节的读取的,如果遇到中文就会一次读取多个

2、在读取之后,方法的底层还会进行解码并转成十进制。

最终把这个十进制作为返回值

这个十进制的数据也表示在字符集上的数字

英文:文件里面二进制数据 0110 0001

read方法进行读取,解码并转成十进制97

中文:文件里面的二进制数据 11100110 10110001 10001001

read方法进行读取,解码并转成十进制27721

如果想看见中文就把这些十进制,进行强转就可以了。

第三步:释放资源
public void close()                                       释放资源/关流

案例:
FileReader file = new FileReader("D:\\Code\\myio\\myIo\\a.txt");
char[] chars = new char[2];
int len;
//read(chars):读取数据,解码,强转三步合并了,把强转之后的字符放到数组当中
//空参的read + 强转类型转换
while ((len = file.read(chars)) != -1){
    //把数组中的数据变成字符串在进行打印
    System.out.print(new String(chars,0,len));
}
file.close();

FileWriter

第一步:创建对象
方法名称说明
public FileWriter(File file)创建字符输出流关联本地文件
public FIleWriter(String pathname)创建字符输出流关联本地文件
public FIleWriter(File file, boolean append)创建字符输出流关联本地文件,续写
public FIleWriter(String pathname, boolean append)创建字符输出流关联本地文件,续写

细节1:参数是字符串表示的路径或者File对象都是可以的

细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的

细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关

第二步:读取数据
方法名称说明
void write(int c)写出一个字符
void write(String str)写出一个字符串
void write(String str, int off, int len)写出一个字符串的一部分
void write(char[] cbuf)写出一个字符数组
void write(char[] cbuf, int off, int len)写出字符数组的一部分

细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集对应的字符

第三步:释放资源
方法名称说明
public void close()释放资源/关流

细节:每次使用完之后都要进行释放。

字符流原理解析

  • 创建字符输入流对象

    • 底层:关联文件,并创建缓冲区(长度为8192的字节数组)

  • 读取数据

    • 底层:

      • 判断缓冲区中是否有数据可以读取

      • 缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲区

        如果文件中也没有数据了,返回-1

      • 缓冲区有数据:就从缓冲区中读取。

空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解码并转成十进制返回

有参的read方法:把读取字节,解码,强转三步合并了,强转之后的字符放到数组中

如果把缓存区的8192个字节用完之后,还有读取的就进行覆盖形式的读取。

flush和close方法
成员方法说明
public void flush()将缓冲区中的数据,刷新到本地文件中
public void close()释放资源/关流

flush刷新:刷新之后,还可以继续往文件中写数据(刷新之后是直接出现再文本当中)

close关流:断开通道,无法再往文件中写出数据

缓冲流

字节缓冲流

方法名称说明
public BufferedInputStream(InputStream is)把基本流包装成高级流,提高读取数据的性能
public BufferedOutputStream(OutputStream os)把基本流包装成高级流,提高写出数据的性能

原理:底层自带了长度为8192的缓冲区提高性能。

字节缓冲流提高速率的原理是它是在内存中进行运行的。

字符缓冲流

方法名称说明
public BufferedReader(Reader r)把基本流变成高级流
public BufferedWriter(Writer r)把基本流变成高级流

原理:底层自带了长度为8192的缓冲区提高性能。

特有方法
字符缓冲输入流特有方法说明
public String readLine()读取一行数据,如果没有数据可读了,会返回null

细节:readLine方法在读取的时候,一次读一整行,遇到回车换行结束,但是他不会把回车换行读到内存当中。

字符缓冲输出流特有方法说明
public void newLine()跨平台的换行

总结

  • 缓冲流有几种?

    • 字节缓冲输入流:BufferedInputStream

    • 字节缓冲输出流:BufferedOutputStream

    • 字符缓冲输入流:BufferedReader

    • 字符缓冲输出流:BufferedWriter

  • 缓冲流为什么能提高性能

    • 缓冲流自带长度为8192的缓冲区

    • 可以显著提高字节流的读写性能

    • 对于字符流提到不明显,对于字符缓冲而言关键点是两个特有的方法

  • 字符缓冲流两个特有的方法是什么?

    • 字符缓冲输入流BufferedReader:readLine()

    • 字节缓冲输出流BufferedWriter:newLine()

转换流

转换流是字符流和字节流之间的桥梁。可以根据字符集一次读取多个字节,读取数据不会乱码了。

作用1:指定字符集读写

作用2:字节流想要使用字符流中的方法

转换流读取

jdk11之前的:

//1、创建对象并指定字符编码
InputStreamReader  isr = new  InputStreamReader(new FileInputStream("D:\Code\myio\myIo\a.txt"),"GBK");
//2、读取数据
int ch;
while((ch = isr.read()) != -1){
    System.out.print((char)ch);
}
//3、释放资源
isr.close();

jdk11之后(包含jdk11)

//1、创建对象并指定字符编码
FileReader  fr = new  FileReader("D:\Code\myio\myIo\c.txt",Charset.forName("GBK"));
//2、读取数据
int ch;
while((ch = isr.read()) != -1){
    System.out.print((char)ch);
}
//3、释放资源
isr.close();

转换流写出

jdk11之前的:

//1、创建转换流的对象
OutputStreamWriter  osw = new  OutputStreamWriter(new  FileOutputStream("D:\Code\myio\myIo\b.txt"),"GBK");
//2、写出数据
osw.write("你好你好");
//3、释放资源
osw.close();

jdk11之后(包含jdk11)

FileWriter fw = new FileWriter("D:\Code\myio\myIo\b.txt",Charset.forName("GBK"));
fw.writer("你好你好");
fw.close();

转换流读取+写出

jdk11之前的:

InputStreamReader  isr = new  InputStreamReader(new FileInputStream("D:\Code\myio\myIo\a.txt"),"GBK");
OutputStreamWriter  osw = new  OutputStreamWriter(new  FileOutputStream("D:\Code\myio\myIo\b.txt"),"UTF-8");
int ch;
while((ch = isr.read()) != -1){
    osw.write(ch);
}
osw.close();
isr.close();

jdk11之后(包含jdk11)

FileReader  fr = new  FileReader("D:\Code\myio\myIo\c.txt",Charset.forName("GBK"));
FileWriter fw = new FileWriter("D:\Code\myio\myIo\b.txt",Charset.forName("UTF-8"));
int b;
while((b = fr.read()) != -1){
    fw.write(b);
}
fw.close();
fr.close();

转换流练习题

利用字节流读取文件中的数据,每次读一整行,而且不能出现乱码

  • 字节流在读取中文的时候,是会出现乱码的,但是字符流可以搞定

  • 字节流里面是没有读一整行的方法的,只有字符缓冲才能搞定

//复杂
FileInputStream  fis = new FileInputStream("D:\Code\myio\myIo\a.txt");
InputStreamReader  isr = new  InputStreamReader(fis);
BufferedReader  br = new  BufferedReader(isr);
String  str = br.readLine();
System.out.println(str);
br.close();
​
//简化(并加上查询文件所有内容)
BufferedReader  br = new  BufferedReader(new  InputStreamReader(new FileInputStream("D:\Code\myio\myIo\a.txt")));
String line;
while((line = br.readLine() != null)){
    System.out.println(line);
}
br.close();

总结

  • 转换流的名字是什么?

    • 字符转换输入流:InputStreamReader

    • 字符转换输出流:OutputStreamWriter

  • 转换流的作用是什么?

    • 指定字符集读写数据(JDK11之后已淘汰)

    • 字节流想要使用字符流中的方法了

序列化

序列化流

序列化流可以把Java中的对象写道本地文件中

构造方法说明
public ObjectOutputStream(OutputStream out)把基本流包装成高级流

成员方法说明
public final void writeObject(Object obj)把对象序列化(写出)到文件中区

细节:

使用对象输出流将对象保存到文件时会出现NotSerializableException异常

解决方案:需要让Javabean类实现Serializable接口

Serializable接口里面是没有抽象方法,标记型接口

一旦实现了这个接口,那么就表示当前的Student类可以被序列化

理解:一个物品的合格证

案例:
//1、创建对象(创建一个对象的类)
Student  stu = new  Student("zhangsan",23)
//2、创建序列化流的对象/对象操作输出流
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\Code\myio\myIo\a.txt"))
//3、写出数据
oos.writeObject(stu);
//4、释放数据
oos.close();

反序列化流

反序列化流/对象操作输入流可以把序列化到本地文件中的对象,读取到程序中来

构造方法说明
public ObjectInputStream(InputStream out)基本流变成高级流

成员方法说明
public Object readObject()把序列化到本地文件中的对象,读取到程序中来

案例:
//1、创建反序列化流的对象
ObjectInputStream  ois = new  ObjectInputStream(new  FileInputStream("D:\Code\myio\myIo\a.txt"))
//2、读取数据
Object o = ois.readObject();
//如果非要用student : Student o = (Student) ois.readObject();
//3、打印对象
System.out.println(o);
//4、释放资源
ois.close();

细节汇总:

  • 使用序列化流将对象写到文件时,需要让javabean类实现Serializable接口。

    否则,会出现NotSerializableException异常

  • 序列化流写到文件中的数据是不能修改的,一旦修改就无法再次都回来。

  • 序列化对象后,修改了Javabean类,再次反序列化,会不会有问题?

    会出现问题,会抛出InvalidClassException异常

    解决方案:给Javabean类添加serialVersionUID(序列号、版本号)

    //代码编写(也可以直接在idea中的设置查找serialVersionUID进行定义,用快捷方式编写出来)
    private static final long serialVersionUID = 1L;
    //private:当前类的私有 , static:表示这个类都共享同一个版本号 , final:表示最终,表示版本号的值永远不会发生变化 , Long版本号比较长所以用long
        版本号:serialVersionUID单词是固定的;

  • 如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?

    解决方案:给该成员变量加trasient关键字修饰,该关键字标记的成员变量不参与序列化过程

//trasient:瞬态关键字
//作用:不会把当前属性序列化到本地文件当中
private transient String address;

打印流

字节打印流

分类:打印流一般是指:PrintStream,PrintWriter两个类。

  • 特点1:打印流只操作文件目的地,不操作数据源

  • 特点2:特有的写出方法可以实现,数据原样写出

    • 例如:打印:97 文件中:97

打印:true 文件中:true

  • 特点3:特有的写出方法,可以实现自动刷新,自动换行

    • 打印一次数据 = 写出 + 换行 + 刷新

构造方法说明
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)指定字符编码且自动刷新
  • 字节流底层没有缓冲区,开不开自动刷新都一样。

成员方法说明
public void write(int b)常规方法:规则跟之前一样,指定的字节写出
public void println(Xxx xx)特有方法:打印任意数据,自动刷新,自动换行
public void print(Xxx xx)特有方法:打印任意数据,不换行
public void printf(String format , Object... args)特有方法:带有占位符的打印语句,不换行

案例:
//1、创建字节打印流的对象
PrintStream  ps = new  PrintStream(new  FileOutputStream("D:\Code\myio\myIo\a.txt"),true,Charset.forName("UTF-8"))
//2、写出数据
ps.println(97);//写出 + 自动刷新 + 自动换行
ps.print(true);
//3、释放数据
ps.close();

字符打印流

构造方法说明
public PrintWriter(Writer/File/String)关联字节输出流/文件/文件路径
public PrintWriter(String fileName, Charset charset)指定字符编码
public PrintWriter(Writer w, boolean autoFlush)自动刷新
public PrintWriter(OutputStream out, boolean autoFlush, Charset charset)指定字符编码且自动刷新
  • 字符流底层有缓冲区,想要自动刷新需要开启

成员方法说明
public void write( . . . )常规方法:规则跟之前一样,写出字节或者字符串
public void println(Xxx xx)特有方法:打印任意类型的数据并且换行
public void print(Xxx xx)特有方法:打印任意类型的数据,不换行
public void printf(String format , Object... args)特有方法:带有占位符的打印语句

案例:
//1、创建字符打印流的对象
PrintWriter  pw = new  PrintWriter(new  FileWriter("D:\Code\myio\myIo\a.txt"),true);
//2、写出数据
pw.println("大会警告和高山大海公司");
pw.print("和嘎哈地方");
pw.printf("%s爱上了%s","阿珍","阿强")
//3、释放数据
pw.close();

打印流应用场景

//获取打印流的对象,此打印流在虚拟机启动的时候,由虚拟机创建,默认指向控制台
//特殊的打印流,系统中的标准输出流,是不能关闭,在系统中是唯一的。
PrintStream  ps = System.out;
​
//调用打印流中的方法println
//写出数据,自动换行,自动刷新
ps.println("123");
​
//ps.close();
​
ps.println("就爱看的风格就爱看");
​
System.out.println("456");

总结:

  • 打印流有几种?各有什么特点?

    • 有字节打印流和字符打印流两种

    • 打印流不操作数据源,只有操作目的地

    • 字节打印流:默认自动刷新,特有的println自动换行

    • 字符打印流:自动刷新需要开启,特有的println自动换行

压缩流

解压缩流

解压本质:把每一个ZipEntry按照层级拷贝到本地另一个文件夹中

案例:
public class ZipStreamDemo1{
    public static void main(String[] args){
        //1、创建一个File表示要解压的压缩包
        File src = new File("D:\\aaa.zip");
        //2、创建一个File表示解压的目的地
        File dest = new File("D:\\");
        
        unzip(src,dest);
    }
    
    //定义一个方法用来解压
    public static void unzip(File src , File dest) throws IOException{
        //解压的本质:把压缩包里面的每一个文件夹读取出来,按照层级拷贝到目的地当中
        
        //创建一个解压缩流用来读取压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //要先获取到压缩包里面的每一个zipentry对象
        
        //表示当前在压缩包中获取到的文件或者文件夹
        ZipEntry entry; 
        While((entry = zip.getNextEntry()) != null){
            System.out.println(entry);
            if(entry.isDirectory()){
                //文件夹:需要在目的地dest处创建一个同样的文件夹
                File file = new File(dest,entry.toString());
                file.mkdirs();
            }else{
                //文件:需要读取到压缩包中的文件,并把它存放到目的地dest文件夹中(按照层级目录进行存放)
                FileOutputStream fos = new FileOutputStream(new File(dest,entry.toString()));
                int b;
                while((b = zip.read()) != -1){
                    //写到目的地
                    fos.write(b);
                }
                fos.close();
                //表示在压缩包中的一个文件处理完毕了。
                zip.closeEntry();
            }
        }
        zip.close();
    }
}
​

压缩流

压缩本质:把每一个(文件/文件夹)看成ZipEntry对象放到压缩包中

压缩文件
public class ZipStreamDemo2{
    public static void main(String[] args){
        //1.创建File对象表示要压缩的文件
        File src = new File("D:\\a.txt");
        //2.创建File对象表示压缩包的位置
        File dest = new File("D:\\");
        //3.调用方法用来压缩
        toZip(src,dest);
    }
    //作用:压缩
    //参数一:表示要压缩的文件
    //参数二:表示压缩包的位置
    public static void toZip(File src , File dest) throws IOException{
        //1、创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
        //2、创建ZipEntry对象,表示压缩包里面的每一个文件和文件夹
        //参数:压缩包里面的路径
        ZipEntry entry = new ZipEntry("aa\\dd\\a.txt");
        //3、把ZipEntry对象放到压缩包当中
        zos.putNextEntry(entry);
        //4、把src文件中的数据写到压缩包当中
        FileInputStream fis = new FileInputStream(src);
        int b;
        while((b = fis.read()) != -1){
            zos.write(b);
        }
        //关闭entry
        zos.closeEntry();
        //关闭压缩流
        zos.close();
    }
}

压缩文件夹
public class ZipStreamDemo2{
    public static void main(String[] args){
        //1、创建File对象表示要压缩的文件夹
        File src = new File("D:\\aaa");
        //2、创建File对象表示压缩包放在哪里(压缩包的父级路径)
        File destParent = src.getParentFile();
        //3、创建File对象表示压缩包的路径
        File dest = new File(destParent,src.getName() + ".zip");
        //4、创建压缩流关联的压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
        //5、获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
        toZip(src,zos,src.getName());
        //6、释放资源
        zos.close();
    }
    
    //作用:获取src里面的每一个文件,变成ZipEntry对象,放入到压缩包当中
    //参数一:数据源
    //参数二:压缩流
    //参数三:压缩包内部的路径
    
    public static void toZip(File src,ZipOutputStream zos,String name) throws IOException{
        //1、进入src文件夹
        File[] files = src.listFiles();
        //2、遍历数组
        for(File file : files){
            if(file.isFile()){
                //3、判断-文件,变成ZipEntry对象,放入到压缩包当中
                ZipEntry entry = new ZipEntry(name + "\\" + file.getName());
                zos.putNextEntry(entry);
                //读取文件中的数据,写到压缩包
                FileInputStream fis = new FileInputStream(file);
                int b;
                while((b = fis.read()) != -1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            }else{
                //4、判断-文件夹,递归
                toZip(file,zos,name + "\\" + file.getName());
            }
        }
    }
}

常用工具包

Commons-io

Commons-io是apache开源基金组织提供的一组有关IO操作的开源工具包。

作用:提高IO流的开发效率

使用步骤:
  • 在项目中创建一个文件夹:lib

  • 将jar包复制粘贴到lib文件夹

  • 右键点击jar包,选择Add as Library -> 点击OK

  • 在类中导包使用

FileUtils类(文件/文件夹相关)说明
static void copyFile(File srcFile , File destFile)复制文件
static void copyDirectory(File srcDir , File destDir)复制文件夹
static void copyDirectoryToDirectory(File srcDir , File destDir)复制文件夹
static void deleteDirectory(File directory)删除文件夹
static void cleanDirectory(File directory)清空文件夹
static String readFileToString(File file , Charset encoding)读取文件中的数据变成成字符串
static void write(File file , CharSepuence data , String encoding)写出数据

IOUtils类(流相关相关)说明
public static int copy(InputStream input , OutputStream output)复制文件
public static int copyLarge(Reader input , Writer output)复制大文件
public static String readLines(Reader input)读取数据
public static void write(String data , OutputStream output)写出数据
部分方法案例
public class ZipStreamDemo{
    public static void main(String[] args){
        //复制文件
        File src = new File("D:\\aaa.txt");
        File dest = new File("D:\\bbb.txt");
        FileUtils.copyFile(src,dest);
        
        //复制文件夹(这个复制是包含了aaa文件夹的复制)
        File src = new File("D:\\aaa");
        File dest = new File("D:\\bbb");
        FileUtils.copyDirectoryToDirectory(src,dest);
        
        //复制文件夹(这个复制是不包含了aaa文件夹的复制)
        File src = new File("D:\\aaa");
        File dest = new File("D:\\bbb");
        FileUtils.copyDirectory(src,dest);
        
        //删除文件夹(包含bbb文件夹的删除)
        File dest = new File("D:\\bbb");
        FileUtils.deleteDirectory(dest);
        
        //清空文件夹(不包含bbb文件夹的清空)
        File dest = new File("D:\\bbb");
        FileUtils.cleanDirectory(dest);
    }
}

Hutool

相关类说明
IoUtil流操作工具类
FileUtil文件读写和操作的工具类
FileTypeUtil文件类型判断工具类
WatchMonitor目录、文件监听
ClassPathResource针对ClassPath中资源的访问封装
FileReader封装文件读取
FileWriter封装文件写入

//file:根据参数创建一个file对象
//touch:根据参数创建文件
//writeLines:把集合中的数据写出到文件中,覆盖模式。
//appendLines:把集合中的数据写出到文件中,续写模式。
//readLines:指定字符编码,把文件中的数据,读到集合中。
//readUtf8Lines:按照UTF-8的形式,把文件中的数据,读到集合中
//copy:拷贝文件或是文件夹
​
​
//根据参数创建一个file对象
File touch = FileUtil.file("D:\\" , "aaa" , "bbb" , "a.txt");
System.out.println(files1);
​
//根据参数创建文件(即使没有根文件也能把根文件创建出来)
File touch = FileUtil.touch(file1);
System.out.println(touch);
​
//把集合中的数据写出到文件中,覆盖模式。
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
File file2 = FileUtil.writeLines(list,"D:\\a.txt","UTF-8");
System.out.println(file2);
​
//把集合中的数据写出到文件中,续写模式。
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("aaa");
list.add("aaa");
list.add("aaa");
File file3 = FileUtil.appendLines(list,"D:\\a.txt","UTF-8");
System.out.println(file3);
​
//指定字符编码,把文件中的数据,读到集合中。
List<String> list = FileUtil.readLines("D:\\a.txt","UTF-8");
System.out.println(list)
  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值