FileInputStream & FileOutputStream

一、字节流

1. FileInputStream 读取全部字节

字节流可处理所有类型文件(文本、图片、视频等),核心是通过字节数组提升读取效率。

方式 1:自定义字节数组读取(推荐)

原理:创建与文件大小一致的字节数组,一次性读取全部数据,避免乱码问题。

public class FileInputStreamTest1 {
    public static void main(String[] args) throws Exception {
        // 1. 创建字节输入流,绑定目标文件
        FileInputStream is = new FileInputStream("day10/src/yy02.txt");
        // 2. 获取文件大小
        File f = new File("day10/src/yy02.txt");
        long size = f.length();
        // 3. 创建和文件大小一致的字节数组
        byte[] buffer = new byte[(int) size];
        // 4. 读取全部字节
        int len = is.read(buffer);
        // 5. 转字符串输出
        System.out.println(new String(buffer));
        // 6. 关闭流
        is.close();
    }
}

2. FileOutputStream 写入字节

作用:以内存为基准,将内存中的数据以字节形式写入文件,支持覆盖 / 追加两种模式。

核心方法与代码示例
public class FileOutputStreamTest {
    public static void main(String[] args) throws Exception {
        // 1. 创建字节输出流,第二个参数true表示追加写入,默认false为覆盖
        FileOutputStream os = new FileOutputStream("day10/src/yy03.txt", true);

        // 2. 写入单个字节
        os.write('a');
        os.write(97); // 写入ASCII码对应的字符

        // 3. 写入整个字节数组
        byte[] bytes = "我爱Javaabc".getBytes();
        os.write(bytes);

        // 4. 写入字节数组的一部分(从下标0开始,写入5个字节)
        os.write(bytes, 0, 5);

        // 5. 关闭流
        os.close();
    }
}

3. 字节流复制文件(通用方案)

原理:边读边写,通过字节数组作为缓冲区,实现所有文件的高效复制。

public class CopyDemo {
    public static void main(String[] args) throws Exception {
        // 1. 源文件输入流(读取)
        InputStream is = new FileInputStream("D:/resource/meinv.png");
        // 2. 目标文件输出流(写入)
        OutputStream os = new FileOutputStream("E:/data/meinv.png");

        // 3. 创建缓冲区(1024的整数倍,提升效率)
        byte[] buffer = new byte[1024];
        int len;

        // 4. 循环读写:读多少写多少
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }

        // 5. 关闭流(先关输出流,再关输入流)
        os.close();
        is.close();
        System.out.println("复制完成!");
    }
}

二、IO 流资源释放(核心避坑)

1. 问题根源

流是操作系统资源,程序异常终止时,close() 无法执行,会导致资源泄漏,后续操作会报 Stream Closed 异常。

2. JDK7 之前:try-catch-finally 方案

finally 块保证代码一定会执行,确保流被关闭。

public class CopyDemo1 {
    public static void main(String[] args) {
        InputStream is = null;
        OutputStream os = null;

        try {
            // 初始化流
            is = new FileInputStream("D:/resource/meinv.png");
            os = new FileOutputStream("E:/data/meinv.png");

            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // finally中判空关闭流,避免空指针
            try {
                if (os != null) os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (is != null) is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3. JDK7+:try-with-resources 方案(推荐)

流对象实现 AutoCloseable 接口,代码块执行完毕后自动关闭流,无需手动写 finally

public class CopyDemo2 {
    public static void main(String[] args) {
        // try()中声明流对象,自动管理关闭
        try (
                InputStream is = new FileInputStream("D:/resource/meinv.png");
                OutputStream os = new FileOutputStream("E:/data/meinv.png")
        ) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) != -1) {
                os.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

三、字符流(FileReader & FileWriter)

1. 字符流体系与适用场景

  • 顶层父类:Reader(输入)、Writer(输出)
  • 常用子类:FileReader(读取文本)、FileWriter(写入文本)
  • 适用场景:仅处理纯文本文件,自动适配字符编码,避免中文乱码。

2. FileReader 读取文本文件

核心构造方法
构造方法说明
FileReader(File file)通过 File 对象创建字符输入流
FileReader(String pathname)通过文件路径创建字符输入流
常用读取方式
public class FileReaderTest {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("day10/src/yy02.txt");

        // 方式1:单个字符读取
        /*
        int ch;
        while ((ch = fr.read()) != -1) {
            System.out.print((char) ch);
        }
        */

        // 方式2:字符数组读取(推荐,效率高)
        char[] buffer = new char[1024];
        int len;
        while ((len = fr.read(buffer)) != -1) {
            System.out.print(new String(buffer, 0, len));
        }

        fr.close();
    }
}

3. FileWriter 写入文本文件

核心构造方法
构造方法说明
FileWriter(File file)创建覆盖模式的字符输出流
FileWriter(String pathname, boolean append)append=true 开启追加模式
常用写入方法与示例
public class FileWriterTest {
    public static void main(String[] args) throws Exception {
        // 追加模式写入
        FileWriter fw = new FileWriter("day10/src/yy03.txt", true);

        // 1. 写入单个字符
        fw.write('中');
        fw.write(97);

        // 2. 写入字符串(字符流特有便捷方法)
        fw.write("Java 字符流学习");

        // 3. 写入字符数组
        char[] chars = {'a', 'b', 'c', '我', '爱', '编', '程'};
        fw.write(chars);

        // 4. 写入字符串的一部分
        fw.write("abcdef", 1, 3);

        // 手动刷新缓冲区(数据落地到文件)
        fw.flush();
        // 关闭流(会自动刷新缓冲区)
        fw.close();
    }
}

注意:字符流自带缓冲区,数据不会直接写入磁盘,必须调用 flush()close() 才能让数据落地。


4. 字符流复制纯文本文件

public class CharCopyDemo {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("day10/src/yy03.txt");
        FileWriter fw = new FileWriter("day10/src/copy_yy03.txt");

        char[] buffer = new char[1024];
        int len;
        while ((len = fr.read(buffer)) != -1) {
            fw.write(buffer, 0, len);
        }

        fw.close();
        fr.close();
        System.out.println("文本复制完成!");
    }
}

四、字节流 vs 字符流 核心对比

对比维度字节流字符流
顶层父类InputStream / OutputStreamReader / Writer
处理单位字节(byte)字符(char)
适用场景所有文件(文本、图片、视频、压缩包)仅纯文本文件
乱码问题可能出现,需手动处理编码自动适配编码,中文不乱码
缓冲区无,读写直接生效有,需 flush()/close() 数据才落地
开发首选场景文件复制、非文本文件读写纯文本文件读写
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值