傳統 IO 實作(適用 Java 7 前環境)
public class FileUtil {
private static final String BASE_PATH = "D:\\file\\";
/** 建立檔案並寫入內容 */
public static boolean createFile(String fileName, String content) {
File file = new File(BASE_PATH + fileName + ".txt");
try {
if (!file.exists()) {
file.createNewFile();
return writeFileContent(file.getAbsolutePath(), content);
}
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/** 追加寫入檔案內容 */
public static boolean writeFileContent(String filePath, String newContent) {
File file = new File(filePath);
try (FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);
FileOutputStream fos = new FileOutputStream(file);
PrintWriter pw = new PrintWriter(fos)) {
StringBuilder buffer = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
buffer.append(line).append(System.lineSeparator());
}
buffer.append(newContent).append(System.lineSeparator());
pw.write(buffer.toString().toCharArray());
pw.flush();
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/** 刪除檔案 */
public static boolean deleteFile(String fileName) {
File file = new File(BASE_PATH + fileName + ".txt");
return file.exists() && file.delete();
}
}
現代 NIO.2 寫法(Java 7+ 推薦)
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.io.IOException;
public class ModernFileUtil {
private static final Path BASE_DIR = Paths.get("D:/file");
/** 原子性建立檔案並寫入(覆蓋模式) */
public static void writeFile(String fileName, String content) throws IOException {
Files.createDirectories(BASE_DIR);
Path path = BASE_DIR.resolve(fileName + ".txt");
Files.write(path, content.getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}
/** 追加模式寫入 */
public static void appendFile(String fileName, String content) throws IOException {
Files.createDirectories(BASE_DIR);
Path path = BASE_DIR.resolve(fileName + ".txt");
Files.write(path, (content + System.lineSeparator()).getBytes(StandardCharsets.UTF_8),
StandardOpenOption.CREATE, StandardOpenOption.APPEND);
}
/** 讀取全部內容 */
public static String readFile(String fileName) throws IOException {
Path path = BASE_DIR.resolve(fileName + ".txt");
return Files.readString(path, StandardCharsets.UTF_8);
}
/** 刪除檔案(不存在不拋異常) */
public static void deleteFile(String fileName) throws IOException {
Path path = BASE_DIR.resolve(fileName + ".txt");
Files.deleteIfExists(path);
}
/** 列出目錄下所有 .txt 檔案 */
public static Stream listTxtFiles() throws IOException {
return Files.list(BASE_DIR).filter(p -> p.toString().endsWith(".txt"));
}
}
大檔案處理最佳實踐
- 分塊讀寫:使用
Files.newBufferedReader() / newBufferedWriter() 避免載入整個檔案到記憶體
- 緩衝區大小調優:預設 8KB,大檔案可調大至 64KB-256KB
- 非同步 IO:Java 7
AsynchronousFileChannel 配合 CompletionHandler 實現非阻塞操作
- 記憶體映射:
FileChannel.map() 適合頻繁隨機存取的大檔案
編碼與跨平台注意事項
| 議題 | 建議做法 |
| 字元編碼 | 明確指定 StandardCharsets.UTF_8,避免預設編碼差異 |
| 路徑分隔符 | 使用 Paths.get() 或 File.separator,勿硬編碼 |
| 換行符 | 使用 System.lineSeparator() 或 \\n(NIO 會自動轉換) |
| 檔案鎖定 | Windows 下檔案被佔用無法刪除,需確認關閉所有串流 |
完整測試範例
public class FileDemo {
public static void main(String[] args) {
String uuid = UUID.randomUUID().toString();
String content = "我的夢想不停留期待,就讓光線折射淚濕的瞳孔...";
// 傳統 IO
FileUtil.createFile(uuid + "_legacy", content);
System.out.println("傳統 IO 讀取:" + FileUtil.readFile(uuid + "_legacy"));
// NIO.2
try {
ModernFileUtil.writeFile(uuid + "_nio", content);
System.out.println("NIO.2 讀取:" + ModernFileUtil.readFile(uuid + "_nio"));
ModernFileUtil.appendFile(uuid + "_nio", "追加測試行");
ModernFileUtil.listTxtFiles().forEach(System.out::println);
ModernFileUtil.deleteFile(uuid + "_nio");
} catch (IOException e) {
e.printStackTrace();
}
}
}