# Java的FileInputStream流如何使用
## 目錄
1. [FileInputStream概述](#一fileinputstream概述)
- 1.1 [什么是FileInputStream](#11-什么是fileinputstream)
- 1.2 [FileInputStream在IO體系中的位置](#12-fileinputstream在io體系中的位置)
2. [FileInputStream核心方法詳解](#二fileinputstream核心方法詳解)
- 2.1 [構造方法](#21-構造方法)
- 2.2 [read()方法](#22-read方法)
- 2.3 [available()方法](#23-available方法)
- 2.4 [skip()方法](#24-skip方法)
- 2.5 [close()方法](#25-close方法)
3. [基礎使用示例](#三基礎使用示例)
- 3.1 [讀取單個字節](#31-讀取單個字節)
- 3.2 [讀取字節數組](#32-讀取字節數組)
- 3.3 [完整文件讀取](#33-完整文件讀取)
4. [高級應用場景](#四高級應用場景)
- 4.1 [大文件分塊讀取](#41-大文件分塊讀取)
- 4.2 [與其他流配合使用](#42-與其他流配合使用)
- 4.3 [文件復制實現](#43-文件復制實現)
5. [異常處理機制](#五異常處理機制)
- 5.1 [FileNotFoundException處理](#51-filenotfoundexception處理)
- 5.2 [IOException處理](#52-ioexception處理)
- 5.3 [使用try-with-resources](#53-使用try-with-resources)
6. [性能優化建議](#六性能優化建議)
- 6.1 [緩沖區大小選擇](#61-緩沖區大小選擇)
- 6.2 [NIO替代方案](#62-nio替代方案)
- 6.3 [內存映射文件](#63-內存映射文件)
7. [常見問題解答](#七常見問題解答)
- 7.1 [中文亂碼問題](#71-中文亂碼問題)
- 7.2 [文件鎖定問題](#72-文件鎖定問題)
- 7.3 [資源釋放問題](#73-資源釋放問題)
8. [總結與最佳實踐](#八總結與最佳實踐)
## 一、FileInputStream概述
### 1.1 什么是FileInputStream
FileInputStream是Java I/O庫中用于從文件系統中讀取原始字節流的核心類。作為InputStream抽象類的直接子類,它專門用于處理文件輸入操作,提供了多種從文件讀取數據的方法。
關鍵特性:
- 字節導向:以字節為單位進行讀取
- 順序訪問:支持順序讀取文件內容
- 不可逆:讀取后無法回退(除非配合BufferedInputStream)
- 線程不安全:需自行處理多線程同步
### 1.2 FileInputStream在IO體系中的位置
Java I/O類層次結構:
java.lang.Object └─ java.io.InputStream └─ java.io.FileInputStream
相關接口實現:
- Closeable:標識可關閉的資源
- AutoCloseable(Java 7+):支持try-with-resources
## 二、FileInputStream核心方法詳解
### 2.1 構造方法
```java
// 通過文件路徑創建
FileInputStream fis1 = new FileInputStream("test.txt");
// 通過File對象創建
File file = new File("test.txt");
FileInputStream fis2 = new FileInputStream(file);
// 通過FileDescriptor創建(高級用法)
FileDescriptor fd = fis2.getFD();
FileInputStream fis3 = new FileInputStream(fd);
構造注意事項: 1. 文件不存在時拋出FileNotFoundException 2. 路徑可以是相對路徑或絕對路徑 3. 創建后即保持文件打開狀態
三種重載形式:
int read() // 讀取單個字節(0-255),EOF返回-1
int read(byte[] b) // 讀取到字節數組,返回實際讀取數
int read(byte[] b, int off, int len) // 帶偏移量的讀取
int available = fis.available();
long skipped = fis.skip(1024); // 跳過1KB數據
fis.close();
try (FileInputStream fis = new FileInputStream("test.txt")) {
int content;
while ((content = fis.read()) != -1) {
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
}
byte[] buffer = new byte[1024];
try (FileInputStream fis = new FileInputStream("largefile.bin")) {
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
processBytes(buffer, bytesRead);
}
} catch (IOException e) {
handleError(e);
}
public static byte[] readFullFile(String path) throws IOException {
try (FileInputStream fis = new FileInputStream(path);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
return bos.toByteArray();
}
}
public void processLargeFile(String filePath, int chunkSize) {
try (FileInputStream fis = new FileInputStream(filePath)) {
byte[] buffer = new byte[chunkSize];
int chunkNumber = 0;
while (fis.available() > 0) {
int read = fis.read(buffer);
processChunk(buffer, read, chunkNumber++);
}
} catch (IOException e) {
// 錯誤處理
}
}
// 轉換為BufferedInputStream提高性能
try (InputStream bis = new BufferedInputStream(
new FileInputStream("data.dat"), 8192)) {
// 讀取操作
}
// 轉換為DataInputStream讀取基本類型
try (DataInputStream dis = new DataInputStream(
new FileInputStream("numbers.bin"))) {
double d = dis.readDouble();
int i = dis.readInt();
}
public static void copyFile(String src, String dest) throws IOException {
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest)) {
byte[] buffer = new byte[8192];
int length;
while ((length = fis.read(buffer)) > 0) {
fos.write(buffer, 0, length);
}
}
}
try {
FileInputStream fis = new FileInputStream("missing.txt");
} catch (FileNotFoundException e) {
System.err.println("文件未找到: " + e.getMessage());
// 可選:創建新文件或提示用戶
}
try (FileInputStream fis = new FileInputStream("data.bin")) {
// 讀取操作
} catch (IOException e) {
logger.error("IO操作失敗", e);
throw new CustomRuntimeException("處理文件失敗", e);
}
// Java 7+ 自動關閉資源
try (FileInputStream fis = new FileInputStream("auto_close.txt")) {
// 使用流
} // 自動調用close()
緩沖區大小 | 適用場景 |
---|---|
512B-1KB | 小文件處理 |
4KB-8KB | 通用場景 |
16KB-64KB | 大文件處理 |
1MB+ | 視頻等超大文件 |
// 使用Files類(Java 7+)
byte[] data = Files.readAllBytes(Paths.get("file.txt"));
// 使用FileChannel
try (FileChannel channel = FileChannel.open(Paths.get("large.bin"))) {
ByteBuffer buffer = ByteBuffer.allocate(8192);
while (channel.read(buffer) > 0) {
buffer.flip();
processBuffer(buffer);
buffer.clear();
}
}
try (FileChannel channel = new RandomAccessFile("huge.dat", "r").getChannel()) {
MappedByteBuffer buffer = channel.map(
FileChannel.MapMode.READ_ONLY, 0, channel.size());
// 直接操作內存緩沖區
}
解決方案:
try (InputStreamReader isr = new InputStreamReader(
new FileInputStream("text.txt"), "UTF-8")) {
// 使用字符流讀取
}
File file = new File("locked.txt");
if (!file.canRead()) {
throw new IOException("文件被鎖定或無權限");
}
錯誤示范:
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
// ...
} finally {
if (fis != null) {
try {
fis.close(); // 可能拋出異常
} catch (IOException e) {
// 被忽略的異常
}
}
}
正確做法(Java 7+):
try (FileInputStream fis = new FileInputStream("file.txt")) {
// ...
} // 自動安全關閉
方法 | 10MB文件 | 1GB文件 |
---|---|---|
單字節讀取 | 1200ms | 超時 |
8KB緩沖 | 45ms | 4200ms |
NIO FileChannel | 32ms | 3800ms |
內存映射 | 28ms | 3500ms |
測試環境:JDK 17/Windows 10/SSD
”`
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。