通過 Scanner 讀取文件時處理 NoSuchElementException
一、概述
在這個簡短的教程中,我們將了解如何在使用Scanner
類讀取文件時處理“ NoSuchElementException: No line found”
。
首先,我們將了解異常的根本原因。然後,我們將學習如何在實踐中重現它,最後學習如何修復它。
2. 理解異常
顧名思義, Scanner
是一個 Java 類,它提供了掃描和解析原始類型和字符串的方法。
在這些方法中,我們發現nextLine()
返回當前行,不包括末尾的任何行分隔符。
在進入細節之前,讓我們研究一下“ NoSuchElementException: No line found”
的真正含義。
NoSuchElementException
表示我們嘗試訪問的元素不存在。因此,堆棧跟踪“ No line found
”表示Scanner
未能檢索到請求的行。
此異常的最常見原因是在沒有要讀取的行時調用nextLine()
方法。
3.重現異常
既然我們知道Scanner
因NoSuchElementException
失敗的原因,讓我們看看如何重現它。
因此,為了舉例說明異常,我們將創建一個使用Scanner.nexLine()
讀取文件的方法:
static String readFileV1(String pathname) throws IOException {
Path pathFile = Paths.get(pathname);
if (Files.notExists(pathFile)) {
return "";
}
try (Scanner scanner = new Scanner(pathFile)) {
return scanner.nextLine();
}
}
如我們所見,我們使用Path類來表示我們要讀取的文件。
現在,讓我們將一個空文件作為參數傳遞給我們的方法,看看會發生什麼:
@Test
void givenEmptyFile_whenUsingReadFileV1_thenThrowException() throws IOException {
Exception exception = assertThrows(NoSuchElementException.class, () -> {
ScannerNoSuchElementException.readFileV1("src/test/resources/emptyFile.txt");
});
assertEquals("No line found", exception.getMessage());
}
因此,嘗試讀取空文件會導致NoSuchElementException: No line found
。
這裡的主要原因是nextLine()
期望該行存在。否則,它會拋出異常。
4. 使用防禦性編程的解決方案
避免異常的最簡單方法是在調用nexLine().
為此,我們可以使用hasNextLine()
方法,如果輸入有另一行,該方法返回true
。
因此,讓我們創建另一個方法readFileV2()
作為readFileV1()
的增強:
static String readFileV2(String pathname) throws IOException {
Path pathFile = Paths.get(pathname);
if (Files.notExists(pathFile)) {
return "";
}
try (Scanner scanner = new Scanner(pathFile)) {
return scanner.hasNextLine() ? scanner.nextLine() : "";
}
}
正如我們在上面看到的,如果有一個或一個空字符串,我們返回下一行。
現在,讓我們使用測試用例驗證一切正常:
@Test
void givenEmptyFile_whenUsingReadFileV2_thenSuccess() throws IOException {
String emptyLine = ScannerNoSuchElementException.readFileV2("src/test/resources/emptyFile.txt");
assertEquals("", emptyLine);
}
如測試用例所示,該解決方案工作正常。 hasNextLine()
防止nexLine()
拋出異常。
另一種解決方案是在使用Scanner
讀取給定文件之前檢查它是否為空:
static String readFileV3(String pathname) throws IOException {
Path pathFile = Paths.get(pathname);
if (Files.notExists(pathFile) || Files.size(pathFile) == 0) {
return "";
}
try (Scanner scanner = new Scanner(pathFile)) {
return scanner.nextLine();
}
}
這樣,我們確保至少有一行將被nextLine()
使用。因此,我們省略了hasNextLine()
。
現在,讓我們測試一下這種新方法:
@Test
void givenEmptyFile_whenUsingReadFileV3_thenSuccess() throws IOException {
String emptyLine = ScannerNoSuchElementException.readFileV3("src/test/resources/emptyFile.txt");
assertEquals("", emptyLine);
}
5. 使用異常處理的解決方案
或者,我們可以使用try
– catch
塊以傳統方式簡單地處理NoSuchElementException
:
static String readFileV4(String pathname) throws IOException {
Path pathFile = Paths.get(pathname);
if (Files.notExists(pathFile)) {
return "";
}
try (Scanner scanner = new Scanner(pathFile)) {
return scanner.nextLine();
} catch (NoSuchElementException exception) {
return "";
}
}
如上所示,我們捕獲了異常並返回了一個空字符串。
最後,讓我們使用測試用例來確認這一點:
@Test
void givenEmptyFile_whenUsingReadFileV4_thenSuccess() throws IOException {
String emptyLine = ScannerNoSuchElementException.readFileV4("src/test/resources/emptyFile.txt");
assertEquals("", emptyLine);
}
六,結論
在本文中,我們了解了導致Scanner
在讀取文件時拋出“ NoSuchElementException: No line found”
的原因。
然後,我們通過實際例子了解瞭如何產生異常以及如何修復它。
與往常一樣,示例的完整源代碼可在 GitHub 上獲得。