用FileInputStream读本地文件的关键是合理配置缓冲区、正确处理read()返回值、用try-with-resources自动关流;路径用正斜杠或双反斜杠;缓冲区宜用1KB/8KB/64KB等固定大小;必须用new String(buf,0,len)避免乱码。

核心要点一句话
用 FileInputStream 读本地文件,关键不是“能不能读”,而是“怎么配缓冲区+怎么处理返回值+怎么关流”——这三步错一个,就容易乱码、丢数据或资源泄漏。
路径写法与流创建要稳
传入文件路径时,避免 Windows 下单反斜杠引发转义错误。推荐两种写法:
- 用正斜杠:
"C:/data/test.txt"或"./config.bin" - 用双反斜杠:
"C:\data\test.txt"
创建流对象会立即校验文件是否存在、是否有读权限。如果文件不存在,抛 FileNotFoundException(属于 IOException 子类),所以建议统一捕获 IOException 即可。
缓冲区大小不是越大越好
常见误区是“把缓冲区设成文件大小”,比如先调 fis.available() 再 new byte[fis.available()]。这在小文本上看似方便,但遇到大文件(如 2GB 视频)会直接 OOM。
更稳妥的做法是固定使用 1024 的整数倍,例如:
- 普通文本/配置文件:
new byte[1024](1KB) - 中等二进制数据(图片、日志包):
new byte[8192](8KB) - 高吞吐场景(如文件拷贝):
new byte[65536](64KB)
缓冲区只是临时容器,真正有效字节数由 read(byte[]) 返回值决定,绝不能直接用 new String(buf) 全量转换。
读取逻辑必须依赖返回值
read(byte[] b) 返回的是本次实际读到的字节数,可能小于数组长度(尤其在文件末尾)。正确写法示例:
byte[] buf = new byte[8192];
int len;
while ((len = fis.read(buf)) != -1) {
// ✅ 安全:只处理 buf[0] 到 buf[len-1]
System.out.print(new String(buf, 0, len, StandardCharsets.UTF_8));
}
错误写法(会导致末尾垃圾数据被打印):
-
System.out.print(new String(buf));—— 整个数组转字符串,含未读取的脏字节 -
while (fis.read(buf) != -1)—— 忽略返回值,无法知道真实长度
自动关闭比手动更可靠
务必使用 try-with-resources,它在语句块结束时自动调用 close(),即使发生异常也不遗漏:
try (FileInputStream fis = new FileInputStream("data.bin")) {
byte[] buf = new byte[4096];
int len;
while ((len = fis.read(buf)) != -1) {
// 处理 buf[0...len-1]
}
} catch (IOException e) {
// 统一处理所有 IO 异常
e.printStackTrace();
}
不用再写 finally 块手动 close,也不用声明流变量在 try 外——简洁且安全。











