Java IO笔记

0 阅读6分钟

什么是流

  • 概念:内存与存储设备之间传输数据的通道。 流的分类

  • 按方向【重点】:

    • 输入流:将<存储设备>中的内容读入到<内存>中。
    • 输出流:将<内存>中的内容写入到<存储设备>中。

(文件 →[输入流]→ 程序 →[输出流]→ 文件)

  • 按单位:

    • 字节流:以字节为单位,可以读写所有数据 。
    • 字符流:以字符为单位,只能读写文本数据 。
  • 按功能:

    • 节点流:具有实际传输数据的读写功能。
    • 过滤流:在节点流的基础之上增强功能。

字节流

  • 字节流的父类(抽象类):

    • InputStream:字节输入流

      • public int read() {}
      • public int read(byte[] b) {}
      • public int read(byte[] b, int off, int len) {}
    • OutputStream:字节输出流

      • public void write(int n) {}
      • public void write(byte[] b) {}
      • public void write(byte[] b, int off, int len) {}
package com.zhang.IO流;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fileInputStream = new FileInputStream("d:\aaa.txt");
        int data=0;
//        while ((data=fileInputStream.read())!=-1){
//            System.out.println((char) data);
//        }
        //一次读取多个字节
        byte[] bytes = new byte[3];
        int i=0;
        while((i=fileInputStream.read(bytes))!=-1){
            System.out.println(new String(bytes,0,i));
        }
        fileInputStream.close();


    }
}

D:\develop-tools\JDK\jdk-17.0.2\bin\java.exe "-javaagent:D:\develop-tools\IDEA\IntelliJ IDEA 2025.1.1.1\lib\idea_rt.jar=65093" -Dfile.encoding=UTF-8 -classpath D:\code\JAVA\IDEA\study1\out\production\study1;D:\code\JAVA\IDEA\study1\src\com\lib\commons-io-2.21.0.jar com.zhang.IO流.TestFileInputStream
abc
def
g

Process finished with exit code 0

public class TestFileOutputStream {
    public static void main(String[] args) throws IOException {
        //创建一个文件输出流,true表示激活追加写,就不会一个进程覆盖掉上一个进程写的了
        FileOutputStream fileOutputStream = new FileOutputStream("d:\bbb.txt",true);
//        fileOutputStream.write(97);
//        fileOutputStream.write('b');
//        fileOutputStream.write('c');
        String str = " Hello World";
        fileOutputStream.write(str.getBytes());
        fileOutputStream.close();
    }
}

image.png

IO流复制文件

public class TestFileOutputStream02 {
    public static void main(String[] args) throws Exception {
        FileInputStream fileInputStream = new FileInputStream("D:\图片\Screenshots\屏幕截图(50).png");
        FileOutputStream fileOutputStream = new FileOutputStream("D:\图片\Screenshots\copy.png");
        /*
         * buffer 是一个缓冲区,因为不知道要读的文件多大,所以
         * 一次次填满缓冲区来循环读。以免发生内存溢出的问题
         * len用来记录实际读取了多长的数据,以免最后不满缓冲区时读到上次循环未覆盖的数据
         * 输入流读完会返回-1,以此判断是不是读完了
         */
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fileInputStream.read(buffer)) != -1) {
            fileOutputStream.write(buffer, 0, len);
        }
        fileInputStream.close();
        fileOutputStream.close();
    }
}

image.png

字节缓冲流

  • 缓冲流:BufferedInputStream/BufferedOutputStream

    • 提高IO效率,减少访问磁盘的次数;
    • 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。 字节缓冲流内部就有一个缓冲区(buffer),和你自己定义的 byte[]本质上作用一样,但有优化。
  • 小文件、简单场景:自己定义 byte[1024]就够用。

  • 大文件、性能要求高:用缓冲流,省心又高效。

try (BufferedInputStream bis = new BufferedInputStream(
         new FileInputStream("file.txt"));
     BufferedOutputStream bos = new BufferedOutputStream(
         new FileOutputStream("copy.txt"))) {
    
    int data;
    while ((data = bis.read()) != -1) {  // 内部用8KB缓冲区自动优化
        bos.write(data);
    }
}
```
public class TestBufferStream {
    public static void main(String[] args) throws Exception {
        FileInputStream inputStream = new FileInputStream("d:\aaa.txt");
        FileOutputStream outputStream = new FileOutputStream("d:\bbb.txt");

        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
        int count = 0;
       while ((count=bufferedInputStream.read())!=-1){
           System.out.println((char) count);
       }
       bufferedInputStream.close();
        for (int i = 0; i < 10; i++) {
            bufferedOutputStream.write("hello world\r\n".getBytes());//\r是回车,\r\n在连在一块写主要是因为 Windows 系统中的换行符由这两个字符组成。
            bufferedOutputStream.flush();//由于你一次写入的文件没有8k,故而只是写入了缓冲区,
            // 达到8k前不会写入文件,使用flush就可以直接写入
        }
        bufferedOutputStream.close();
    }
}
```

对象流

  • 对象流:ObjectOutputStream/ObjectInputStream

    • 增强了缓冲区功能

    • 增强了读写8种基本数据类型和字符串功能

    • 增强了读写对象的功能:

      • readObject()从流中读取一个对象
      • writeObject(Object obj)向流中写入一个对象

使用流传输对象的过程称为序列化、反序列化。

package com.zhang.IO流;

import java.io.*;

public class TestObjectStream {
    public static void main(String[] args) throws Exception {
//        ObjectOutputStream objectOutputStream =//.bin是二进制文件的意思
//                new ObjectOutputStream(new FileOutputStream("d:\abject.bin") );
        ObjectInputStream objectInputStream =
                new ObjectInputStream(new FileInputStream("d:\abject.bin"));

//        TestObject a=new TestObject("zhnag");
//        objectOutputStream.writeObject(a);//序列化文件
//        objectOutputStream.close();//close自带flush功能
//        System.out.println("序列化完毕");

        TestObject b=(TestObject)objectInputStream.readObject();//反序列化文件
        System.out.println("反序列化完毕");
        System.out.println(b);
        objectInputStream.close();

    }
}
class TestObject implements Serializable {
    //Serializable表示可序列化,必须实现这个接口
    /*
    如果有Student a;这种对象属性,那么这个属性的类也要实现Serializable
    用transit修饰的属性不能被序列化,只会是默认值
    静态属性不能被序列化
    序列化多个类可以依靠集合实现
     */
    private String name;
    public TestObject(String name) {
        this.name = name;
    }

    public TestObject() {
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "TestObject{name = " + name + "}";
    }
}

字符编码

  • ISO-8859-1 收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。
  • UTF-8 针对Unicode码表的可变长度字符编码
  • GB2312 简体中文
  • GBK 简体中文、扩充
  • BIG5 台湾,繁体中文

文件字符流

  • FileReader:

    • public int read(char[] c)//从流中读取多个字符,将读到内容存入c数组,返回实际读到的字符数;如果达到文件的尾部,则返回-1。
  • FileWriter:

    • public void write(String str)//一次写多个字符,将b数组中所有字符,写入输出流。

      只能处理字符文件,不能实现上面的复制图片操作

public class TestFileReader {
    public static void main(String[] args) throws Exception {
        FileReader fileReader = new FileReader("d:\hello.txt");
        FileInputStream fileInputStream = new FileInputStream("d:\hello.txt");
        int count = 0;
        int count2=0;
        while ((count = fileReader.read()) != -1) {
            System.out.print((char) count);
        }
        System.out.println();
        /*
        reader和writer可以依据默认的字符码读取写入文件,避免了出现乱码
         */
        while ((count2=fileInputStream.read() )!= -1) {
            System.out.print((char) count2);
        }
        fileReader.close();
        fileInputStream.close();
    }
}

D:\develop-tools\JDK\jdk-17.0.2\bin\java.exe "-javaagent:D:\develop-tools\IDEA\IntelliJ IDEA 2025.1.1.1\lib\idea_rt.jar=56141" -Dfile.encoding=UTF-8 -classpath D:\code\JAVA\IDEA\study1\out\production\study1;D:\code\JAVA\IDEA\study1\src\com\lib\commons-io-2.21.0.jar com.zhang.IO流.TestFileReader
好好学习
好好学习
Process finished with exit code 0

字符缓冲流

  • 缓冲流:BufferedReader/BufferedWriter
  • 高效读写
  • 支持输入换行符。
  • 可一次写一行、读一行。 image.png

image.png

打印流

  • PrintWriter:

    • 封装了print() / println()方法,支持写入后换行。
    • 支持数据原样打印
public class TestPrintWriter {
    public static void main(String[] args) throws FileNotFoundException {
        PrintWriter pw = new PrintWriter("d:\print.txt");
        pw.println(97);
        pw.println(true);
        pw.println(3.14);
        pw.print('a');
        pw.print('b');
        pw.close();
    }
}

image.png

转换流

  • 桥转换流:InputStreamReader/OutputStreamWriter

    • 可将字节流转换为字符流。
    • 可设置字符的编码方式。

image.png

image.png

File类

  • 概念:代表物理盘符中的一个文件或者文件夹。

  • 方法:

    • createNewFile()//创建一个新文件
    • mkdir()//创建一个新目录
    • delete()//删除文件或空目录
    • exists()//判断File对象所代表的对象是否存在
    • getAbsolutePath()//获取文件的绝对路径
    • getName()//取得名字
    • getParent()//获取文件/目录所在的目录
    • isDirectory()//是否是目录
    • isFile()//是否是文件
    • length()//获得文件的长度
    • listFiles()//列出目录中的所有内容
    • renameTo()//修改文件名为

image.png

image.png image.png

image.png

FileFilter接口

  • public interface FileFilter

    • boolean accept(File pathname)
  • 当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件的才可出现在listFiles()的返回值中。

image.png

image.png

image.png

补充:Properties

  • Properties:属性集合

  • 特点

    • 1 存储属性名和属性值
    • 2 属性名和属性值都是字符串类型
    • 3 没有泛型
    • 4 和流有关