在 Java 中逐行讀取 StringBuilder
1.概述
在 Java 中, StringBuilder
被廣泛用於高效地建構和操作字串,尤其是在需要頻繁修改的情況下。然而,一旦內容建構完成,我們經常面臨逐行處理文本的挑戰,尤其是在嵌入換行符的情況下StringBuilder
不提供直接遍歷行的方法,這使得提取單行或測量其長度等任務變得不那麼直觀。
在本教程中,我們將探討逐行讀取StringBuilder
多種實用技巧,並重點介紹每種方法的優點、缺點和理想場景。此外,我們將根據具體需求,嘗試確定最有效的方法。
2. 使用行分隔符號讀取StringBuilder
逐行處理StringBuilder
最簡單的方法之一是先將其轉換為String
,然後在換行符處將其拆分。
由於換行符約定在不同平台之間有所不同( \n
、 \r\n
或\r
),因此\\R
正規表示式簡寫可以方便地匹配任何類型的換行符。
讓我們來看一個這種方法的例子:
public class LineSeparatorApproach {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(
"StringBuilder\nLine Separator Approach\r\nLine by Line Reading\rAnother line"
);
// \R matches any line break (\n, \r\n, \r)
String[] lines = sb.toString().split("\\R");
for (String line : lines) {
System.out.println(line);
}
}
}
此方法簡單且可讀性強。
然而,在執行拆分操作之前,它需要將StringBuilder
的所有內容作為單一String
載入到記憶體中。這意味著該技術在處理大量文字時會導致效率低下並增加記憶體使用量。
3. 使用Scanner
讀取StringBuilder
處理每行StringBuilder
另一種實用方法是將其內容包裝在StringReader
中並使用Scanner
逐行讀取。
Scanner
類別提供了諸如hasNextLine()
和nextLine()
之類的內建方法,使基於行的迭代變得簡單直觀。
讓我們透過一個例子來探討一下這種方法:
public class ScannerApproach {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(
"StringBuilder\nScanner Approach\r\nLine by Line Reading\rAnother line"
);
Scanner scanner = new Scanner(new StringReader(sb.toString()));
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
}
}
具有StringReader
的Scanner
可以順利處理較小的文字。
然而,隨著內容大小的增加,此方法的效率會降低,因為Scanner
在解析和管理輸入時會引入額外的開銷。對於這種情況, BufferedReader
方法通常能提供更好的效能。
4.使用BufferedReader
讀取StringBuilder
為了有效地處理更大的StringBuilder
內容, Scanner
方法的更好替代方法是使用BufferedReader
。
透過將StringBuilder
內容包裝在StringReader
中,然後將其傳遞給BufferedReader
,我們可以逐行遍歷文本,同時降低開銷並提高效能。
那麼,讓我們來看看BufferedReader
方法的實際演示:
public class BufferedReaderApproach {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(
"StringBuilder\nBufferedReader Approach\r\nLine by Line Reading\rAnother line"
);
try (BufferedReader reader = new BufferedReader(new StringReader(sb.toString()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
這種方法利用了BufferedReader
的內建readLine()
方法,使過程更快、更方便。
不過,還有一種更現代的方法來處理這種情況。
5. 使用Stream API
讀取StringBuilder
建議逐行讀取StringBuilder
簡潔方法是使用 Java 8 Stream API
。
Java 8 提供了lines()
方法將字串轉換為順序流,識別換行符( \n
, \r\n
, \r
),並在處理時產生每一行。
讓我們看一下這種方法的示範:
public class StreamLinesApproach {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(
"StringBuilder\nStream Approach\r\nLine by Line Reading\rAnother line"
);
sb.toString()
.lines()
.forEach(System.out::println);
}
}
Stream API's lines()
方法簡潔,可以處理所有行分隔符號。
儘管如此,對於非常大的內容,它會使用更多的內存,並且提供的控制比Scanner
或BufferedReader
更少。
6. 使用手動迭代讀取StringBuilder
手動迭代使用charAt()
和substring()
讀取StringBuilder
,從而能夠精確處理換行符和逐行處理,使其成為大型或特殊格式的文字的理想選擇。
讓我們來看一個手動迭代方法的範例實作:
public class ManualIterationApproach {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(
"StringBuilder\nManual Iteration Approach\r\nLine by Line Reading\rAnother line"
);
int start = 0;
for (int i = 0; i < sb.length(); i++) {
char c = sb.charAt(i);
if (c == '\n' || c == '\r') {
System.out.println(sb.substring(start, i));
if (c == '\r' && i + 1 < sb.length() && sb.charAt(i + 1) == '\n') {
i++;
}
start = i + 1;
}
}
if (start < sb.length()) {
System.out.println(sb.substring(start));
}
}
}
這種方法具有高度的靈活性。
但是,它需要小心處理不同的換行符變化,這使得它與其他方法相比更容易出錯。
7. 結論
在本文中,我們探討了在 Java 中逐行讀取StringBuilder
五種有效方法,每種方法都根據用例提供自己的優勢。
讓我們回顧一下。按行分隔符號拆分簡單易讀,非常適合小型到中等大小的文字。 Scanner 提供便利的逐行Scanner
功能,但由於解析開銷,讀取較大內容BufferedReader
速度可能會略慢。 BufferedReader 透過高效率讀取行來提升大文本的效能。 Stream Stream API
提供了一種簡潔、現代、函數式風格的方法,可以處理所有行分隔符,但底層控制較少。手動迭代可以完全控制行檢測和記憶體使用,使其適用於非常大或自訂格式的文本,但需要謹慎處理換行符。
最合適的方法最終取決於多種關鍵因素,包括正在處理的文字的整體大小、應用程式的特定效能要求以及處理每一行時所需的控製程度。
本文討論的所有方法的程式碼範例都可以在 GitHub 上找到。