fileinputstream读中文乱码是因为它是字节流,不处理编码,直接用new string(buf)会使用系统默认编码(如gbk)解码utf-8文件,导致乱码;必须显式指定正确编码如"utf-8"。

FileInputStream 读取文件时为什么中文显示为乱码
因为 InputStream 是纯字节流,不处理字符编码。它把文件内容原样读成 byte[],如果你直接用 new String(buf) 构造字符串,默认用系统平台编码(比如 Windows 上是 GBK),而文件实际是 UTF-8 编码,就会乱码。
- 必须显式指定编码:用
new String(buf, 0, len, "UTF-8")或"GBK" - 不要依赖
available()当文件长度——它只保证“当前可无阻塞读取的字节数”,对网络流或压缩文件不可靠 - 如果不确定文件编码,先用工具(如 VS Code、Notepad++)查看并确认,再硬编码进代码
FileOutputStream 写入时为什么会覆盖原文件
FileOutputStream 默认构造行为就是**覆盖写入**。只要路径存在同名文件,打开流那一刻原内容就被清空了。
- 想追加内容,必须传
true作为第二个参数:new FileOutputStream("a.txt", true) - 传
File对象比传字符串路径更安全,能提前检查file.exists()或file.getParentFile().mkdirs() - 注意:即使目标目录不存在,
FileOutputStream也不会自动创建父级目录,会抛FileNotFoundException
为什么 read() 和 write() 要配合循环使用
InputStream.read(byte[]) 和 OutputStream.write(byte[], int, int) 都不能保证一次读/写完整个文件——操作系统每次允许传输的数据量受缓冲区、磁盘块、JVM 实现影响。
-
read(buf)返回的是**本次实际读到的字节数**,可能小于buf.length,尤其在结尾 - 必须用
while ((len = in.read(buf)) != -1)循环,而不是for固定次数 - 写入时一定要用
out.write(buf, 0, len),而不是out.write(buf),否则会把未读满的垃圾字节也写进去
不关流会出什么问题
不调用 close() 不仅浪费内存,更关键的是会泄漏**文件描述符(file descriptor)**。Linux/Windows 进程有上限(通常是 1024 或 4096),开太多不关的流会导致后续 new FileInputStream 直接失败,报 IOException: Too many open files。
- 务必在
finally块里关流,或用 try-with-resources(推荐):try (FileInputStream in = new FileInputStream("x.txt")) { ... } -
close()会隐式触发flush(),但OutputStream子类如BufferedOutputStream必须先flush()再close(),否则缓冲区数据可能丢失 - 流一旦
close(),再调用read()或write()会抛IOException: Stream closed











