【Java】文件I/O-文件内容操作-输入输出流-Reader/Writer/InputStream/OutputStream四种流

导读

在文件I/O这一节的知识里,对文件的操作主要分为两大类:

☑️针对文件系统进行的操作

☑️针对文件内容进行的操作

上文已经讲了针对文件系统即File类的操作,这篇文章里博主就来带了解针对文件内容的操作,即输入输出流(Reader,Writer,InputStream,OutputStream)四种流相关知识📖

前置知识

1、流的分类

文件I/O中的流分为字节流和字符流

字符流:以字符为单位 ,每次读写的最小单位是字符;对应文本文件。包括Reader,Writer两个类

字节流:以字节为单位 ,每次读写的最小单位是字节;对应二进制文件。包括InputStream,OutputStream两个类

流的关系分类如下图

注意,字符和字节的关系如下

一个字符可能是对应多个字节
GBK,一个中文字符 ->两个字节
UTF8,一个中文字符 ->三个字节

2、输入输出的定义

计算机中的输入输出发生在CPU和硬盘之间,而我们所说的输入输出是以CPU为视角,即

· 把数据从CPU保存到硬盘上,是输出/写(Input/Read)

· 把内容从硬盘取到CPU里,是输入/读(Output/Write)

下图可以形象地表示输入输出的定义

四种流的使用

1、Reader

(1)Reader类

先创建一个Reader

java 复制代码
Reader reader = new FileReader("/Users/liuwenwen/Desktop/test.txt");

(2)Reader类中的方法

Reader最常用的就是read方法,read方法分为下面几种

|-----------------------------------------|-----------------------------------------|
| 方法名 | 说明 |
| read(char\[\] cbuf) | 传入数组参数,读取数组长度的字符存放在数组中 |
| read () | 读一个字符 |
| read(CharBuffer target) | 传入CharBuffer对象 |
| read(char\[\] cbuf,int off, int length) | 传入数组参数,从字符串off位置开始读,读取length长度的字符存放在数组中 |

(3)代码实例

其中最常用的是read(char\[\] cbuf)方法,返回参数是读取字符的个数

java 复制代码
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class demo {
    public static void main(String[] args){
        char[] buf = new char[12];
        try(Reader reader = new FileReader("/Users/liuwenwen/Desktop/test.txt")) {
            while (true){
                int n = reader.read(buf);
                if(n == -1){
                    break;
                }
                System.out.println("n="+n);
                for (int i = 0; i < n; i++) {
                    System.out.print(buf[i]);
                }
                System.out.println();
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

注意:代码中将Reader reader = new FileReader("/Users/liuwenwen/Desktop/test.txt放在try()代码块中是隐藏了reader.close()操作,相当于

java 复制代码
try {
      Reader reader = new FileReader("/Users/liuwenwen/Desktop/test.txt")
      while (true){
                int n = reader.read(buf);
                if(n == -1){
                    break;
                }
                System.out.println("n="+n);
                for (int i = 0; i < n; i++) {
                    System.out.print(buf[i]);
                }
                System.out.println();
        }
} catch (FileNotFoundException e) {
            throw new RuntimeException(e);
} catch (IOException e) {
            throw new RuntimeException(e);
}finally{
       reader.close();
}

读取结果

2、Writer类

(1)Writer中的方法

Writer方法如下

|----------------------------------------|---------------------------------------|
| 方法名 | 说明 |
| write(String str) | 一次写一个字符串 |
| write(char\[\] cbuf) | 一次写多个字符(字符数组) |
| write(int c) | 一次写一个字符 |
| write(String str, int off, int len) | 带有 offset 和lenoffset指的是从字符串中的第几个字符开始写 |
| write(char\[\] cbuf, int off, int len) | 带有 offset 和lenoffset 指的是从数组中的第几个字符开始写 |

(2)代码实例

我们最常用的是第一个即write(String str)方法

java 复制代码
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class demo3 {
    public static void main(String[] args) {
        try(Writer writer = new FileWriter("/Users/liuwenwen/Desktop/test.txt")) {
            writer.write("驻跸怀千古,开襟望九州。太平词藻盛,长愿纪鸿休。");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

运行程序后,文本内容被修改了😦

可见我们原来的内容同时也被覆盖。如果不想覆盖原本的内容,怎么办呢?🤔

在创建Writer类时,加一个参数true,表示追加

java 复制代码
try(Writer writer = new FileWriter("/Users/liuwenwen/Desktop/test.txt",true)) 

为了防止由于程序运行太快,内容在缓冲区中没有来得及写到硬盘里,我们加一个flush()方法

java 复制代码
writer.flush();

现在整体代码就变成

java 复制代码
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class demo3 {
    public static void main(String[] args) {
        try(Writer writer = new FileWriter("/Users/liuwenwen/Desktop/test.txt",true)) {
            writer.write("驻跸怀千古,开襟望九州。太平词藻盛,长愿纪鸿休。");
            writer.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

用原来的文本再次运行程序

​​​​​​​

可以看到,这次是追加,不再是覆盖

3、InputStream类

(1)方法

InputStream类和Reader类里的方法类似,不过将char\[\]数组变为了byte\[\]数组,返回值是读取字节的个数

(2)代码实例

java 复制代码
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class demo5 {
    public static void main(String[] args) {
        try (InputStream inputStream = new FileInputStream("/Users/liuwenwen/Desktop/test.txt")){
            byte[] buf = new byte[1024];
            int n = inputStream.read(buf);
            for (int i = 0; i < n; i++) {
                System.out.printf("%x ",buf[i]);
                //采用十六进制打印,更加直观
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

读取结果

4、OutputStream类

(1)方法

OutputStream类和Writer类里的方法类似,不过将char\[\]数组变为了byte\[\]数组

(2)代码实例

java 复制代码
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class demo6 {
    public static void main(String[] args) {
        try(OutputStream outputStream = new FileOutputStream("/Users/liuwenwen/Desktop/test.txt",true)){
            String s = "驻跸怀千古,开襟望九州。太平词藻盛,长愿纪鸿休。";
            outputStream.write(s.getBytes());
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

由于OutputStream类write方法要传入的是byte\[\]参数,我们直接调用字符串的getBytes()方法,方便书写

最终追加结果

相关推荐
AntsData17 分钟前
用 12K+ 条亚马逊评论信号,定位机械键盘下一版该改什么
java·大数据·计算机外设
code2cat24 分钟前
【随笔】连续批处理:长短请求怎样在迭代之间补位
java·人工智能·后端·大语言模型·vllm
最强小杰27 分钟前
DeepSeek V4 Flash + Codex CLI 接入教程:原生 Responses API 适配,从配置到跑通收藏这篇就够了(2026)
java·前端·python·ai
Flynn Liang43 分钟前
Spring AI 2.0 深度解析:ChatClient、Advisor 链与 MCP——Java 工程师的 AI 落地最优解
java·人工智能·spring·大模型·架构设计·spring ai
灿飞1 小时前
Kotlin与Java虚拟机六:基础与类型系统:一切皆对象,但对象有代价
java·kotlin
计算机毕设定制辅导-无忧学长1 小时前
《基于微信小程序健康习惯激励系统设计与实现》
java·spring boot·mysql·微信小程序·uniapp·健康习惯激励系统
揽星河..1 小时前
【C语言】指针
c语言·开发语言
小小数媒成员1 小时前
UGUI原理(一)
开发语言·游戏·unity·游戏引擎
速易达网络2 小时前
Three.js 动画入门教学:从场景搭建到流畅动效
开发语言·javascript·ecmascript
福大大架构师每日一题2 小时前
excelize v2.11.1发布:Go 1.26.0起步,16项安全修复与嵌入对象能力全面升级
开发语言·安全·golang