使用 Java 替換檔案中的特定單字
1. 簡介
在本教程中,我們將了解如何使用各種標準 Java 套件和 Apache Commons IO 庫替換檔案中的特定單字。
2. 樣本數據
在本教學的所有範例中,我們將使用下面定義的範例資料和參數。
首先,讓我們建立一個名為data.txt
的簡單文件,將其用作輸入文件:
This is a sample file.
This is a sample file.
This is a sample file.
此外,我們將使用以下範例值(如檔案路徑、輸出檔案路徑和輸出)進行驗證:
private static final String FILE_PATH = "src/test/resources/data.txt";
private static final String FILE_OUTPUT_PATH = "src/test/resources/data_output.txt";
private static final String OUTPUT_TO_VERIFY
= "This is a test file."+System.lineSeparator()+"This is a test file."+System.lineSeparator()+"This is a test file.";
3.使用BufferedReader
讓我們來探索一下BufferedReader
類,它允許我們逐行讀取文件。
首先,我們將逐行遍歷檔案並使用StringBuilder
附加整行。我們也會在附加資料的同時附加換行符。這樣,我們就可以儲存文件內容了。然後,我們將使用String replace()
方法替換整個文件內容中所需的單字,然後將資料寫回檔案:
@Test
void givenFile_whenUsingBufferedReader_thenReplacedWordCorrect() throws IOException {
StringBuilder fileContent = new StringBuilder();
try (BufferedReader br = Files.newBufferedReader(Paths.get(FILE_PATH))) {
String line;
while ((line = br.readLine()) != null) {
fileContent.append(line).append(System.lineSeparator());
}
String replacedContent = fileContent.toString().replace("sample", "test").trim();
try (FileWriter fw = new FileWriter(FILE_OUTPUT_PATH)) {
fw.write(replacedContent);
}
assertEquals(OUTPUT_TO_VERIFY, replacedContent);
}
}
透過這種方法,我們替換了整個檔案中的單詞,並使用FileWriter
將更新的內容寫回檔案。
4. 使用Scanner
我們可以使用Scanner
類別以類似的方法實現相同的結果:
@Test
void givenFile_whenUsingScanner_thenReplacedWordCorrect() throws IOException {
StringBuilder fileContent = new StringBuilder();
try (Scanner scanner = new Scanner(new File(FILE_PATH))) {
while (scanner.hasNextLine()) {
fileContent.append(scanner.nextLine()).append(System.lineSeparator());
}
String replacedContent = fileContent.toString().replace("sample", "test").trim();
try (FileWriter fw = new FileWriter(FILE_OUTPUT_PATH)) {
fw.write(replacedContent);
}
assertEquals(OUTPUT_TO_VERIFY, replacedContent);
}
}
5.使用NIO2 Files
讓我們來探索一下 NIO2 Files
API .
它的lines()
方法提供了一個流來逐行讀取檔案。使用 lambda 函數,我們將在每一行中用所需的單字取代該單字:
@Test
void givenFile_whenUsingFilesAPI_thenReplacedWordCorrect() throws IOException{
try (Stream<String> lines = Files.lines(Paths.get(FILE_PATH))) {
List<String> list = lines.map(line -> line.replace("sample", "test"))
.collect(Collectors.toList());
Files.write(Paths.get(FILE_OUTPUT_PATH), list, StandardCharsets.UTF_8);
assertEquals(OUTPUT_TO_VERIFY, String.join(System.lineSeparator(), list));
}
}
首先,我們建立包含更新的檔案資料的列表,然後使用Files.write()
方法寫入更新的資料。
6.使用 Apache Commons IO
我們可以使用 Apache Commons IO 函式庫。我們將使用FileUtils
類別。此類別提供了readLines()
方法,使用該方法我們可以將整個檔案讀入清單。
類似地,我們將使用StringBuilder
的方法以及String replace()
方法:
@Test
void givenFile_whenUsingFileUtils_thenReplacedWordCorrect() throws IOException{
StringBuilder fileContent = new StringBuilder();
List<String> lines = FileUtils.readLines(new File(FILE_PATH), "UTF-8");
lines.forEach(line -> fileContent.append(line).append(System.lineSeparator()));
String replacedContent = fileContent.toString().replace("sample", "test").trim();
try (FileWriter fw = new FileWriter(FILE_OUTPUT_PATH)) {
fw.write(replacedContent);
}
assertEquals(OUTPUT_TO_VERIFY, replacedContent);
}
再次,我們將使用FileWriter
寫入更新的資料。請注意,這種方法會導致文件在記憶體中儲存兩次,一次作為原始文件,一次儲存更新後的資料。**雖然這對於小檔案來說是可以接受的,但對於大檔案來說可能會導致記憶體問題或效能下降。**
7. 使用記憶體高效方法
上述每種方法都將更新的檔案內容儲存在記憶體中,這會增加記憶體使用量。
讓我們看一下記憶體高效的方法。在逐行讀取檔案時,我們將使用Files.writeString()
方法將該行連續寫入檔案:
@Test
void givenLargeFile_whenUsingFilesAPI_thenReplacedWordCorrect() throws IOException {
try (Stream<String> lines = Files.lines(Paths.get(FILE_PATH))) {
Files.writeString(Paths.get(FILE_OUTPUT_PATH), "",
StandardCharsets.UTF_8, StandardOpenOption.CREATE,StandardOpenOption.TRUNCATE_EXISTING);
lines.forEach(line -> {
line = line.replace("sample", "test") + System.lineSeparator();
try {
Files.writeString(Paths.get(FILE_OUTPUT_PATH),line,StandardCharsets.UTF_8,
StandardOpenOption.APPEND);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
assertEquals(OUTPUT_TO_VERIFY, Files.readString(Paths.get(FILE_OUTPUT_PATH)).trim());
}
}
因此,我們將替換該單字並不斷將更新的資料寫入檔案中。請注意,這會在文件末尾存儲一個額外的新行。從檔案讀取資料時,我們可以使用trim()
方法。
這種方法使我們不必將整個檔案儲存在記憶體中,但也會導致高 IO 操作,從而增加 CPU 使用率。
8. 結論
在本文中,我們研究了使用 Java IO 和 NIO 套件以及 Apache Commons 替換檔案中特定單字的不同方法。我們應該考慮應用程式是否能夠承受更多的 CPU 使用率或更多的記憶體使用率來選擇方法。
本文中的所有程式碼都可以在 GitHub 上找到。