钩子:你的程序是个"金鱼"
到现在为止(第 29 篇了),我们写的所有程序有个共同点:没有记性。
变量存在内存里,程序一关——全没了。你做的单词计数器、通讯录,下次打开又是白纸。
因为内存是"临时工",硬盘才是"档案馆"。想记住东西,就得把数据从内存搬到硬盘——中间那根搬运管道,就叫 IO 流。
核心:管道思维
记住一个画面就够了:
- 文件住在硬盘上;
- 程序住在内存里;
- 中间隔着一条河,流就是河上的管道。
写文件 = 内存 → 管道 → 硬盘;读文件 = 硬盘 → 管道 → 内存。所谓 IO(Input/Output),输入输出全是相对程序自己说的。

正题:5 行写一个文件
FileWriter writer = new FileWriter("橙码酱.txt"); // 1. 架管道
writer.write("IO 流:硬盘和内存之间的搬运工\n"); // 2. 塞内容
writer.write("第 29 篇,打卡\n"); // 3. 再塞一行
writer.close(); // 4. 拆管道(必须!)
严格说 3 行就能写完一个文件。FileWriter 是"字符流",专管文本;将来处理图片、视频要用"字节流",但管道思维完全一样。
读文件,推荐按行读:
BufferedReader br = new BufferedReader(new FileReader("橙码酱.txt"));
String line;
while ((line = br.readLine()) != null) { // 读到 null 就是文件末尾
System.out.println(line);
}
br.close();
BufferedReader 套在 FileReader 外面,像给管道加了个加速环——一次搬一车而不是搬一件,还白送一个 readLine() 按行读。这种"套娃"写法是 IO 流的标配姿势,以后还会见到很多。
顺便说:new FileReader(不存在的文件) 编译器会直接飘红——还记得上篇吗?这就是受检异常,编译器逼你表态。本文为了聚焦先 throws 了,第 30 篇给你终极解法。
坑点:不 close,文件是空的
新手第一大坑,我 demo 里现场表演了一遍:
FileWriter lazy = new FileWriter("没关管道.txt");
lazy.write("这行字大概率写不进去");
// 没有 close —— 打开文件一看:空的!
原因:write 的数据先堵在缓冲区,close 时才统一冲进硬盘。不 close,数据就烂在缓冲区里了。
所以"用完必须 close"不是礼貌问题,是数据完整性问题。但手写 close 又啰嗦又容易漏——别急,这正是第 30 篇 try-with-resources 要解决的。
速查表
| 操作 | 代码 | 说明 |
|---|---|---|
| 写文件 | new FileWriter("文件名") |
默认覆盖写 |
| 追加写 | new FileWriter("文件名", true) |
第二参数 true |
| 按行读 | new BufferedReader(new FileReader(...)) |
套娃加速 + readLine |
| 文件末尾 | read() 返回 -1 / readLine 返回 null | 两种判空别记混 |
| 铁律 | 用完必须 close | 不关=数据可能没落盘 |
本文示例代码均已本地实测通过,可直接运行。
对应文件:FileIODemo.java
橙码酱,分享更有用的技术知识,助你成为更优秀的开发者。