Skip to content

十八、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
  • 空参
    java
    FileReader fr = new FileReader("路径");
    
    int ch;
    while((ch=fr.read()) != -1){
        System.out.println((int)ch);
    }
    
    fr.close();
  • 有参
    java
    FileReader 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;

七、打印流

分类:打印流一般是指:PrintStreamPrintWriter两个类

特点:

  • 打印流只操作文件目的地,不操作数据源
  • 特有的写出方法可以实现,数据原样写出
  • 特有的写出方法,可以实现自动刷新,自动换行

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方法

    java
    File src= new File("caogao\\b.txt");
    File dest=new File("caogao\\");
    toZip(src,dest);

    tozip方法

    java
    public 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方法

    java
    File 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方法

    java
    public 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

十、hutool

官网:https://apidoc.gitee.com/dromara/hutool/

资源链接:https://www.123pan.com/s/QvTuVv-ElVw.html