[英]Splitting a string up via markers?
我有一個txt文件,該文件摘自一本書。 我已通過以下方法將文件轉換為字符串
File book = new File("WarAndPeace.txt");
chapters = new ArrayList<String>();
FileReader fileReader;
fileReader = new FileReader(book);
BufferedReader bufferedReader = new BufferedReader(fileReader);
StringBuffer stringBuffer = new StringBuffer();
String nextLine;
while ((nextLine = bufferedReader.readLine()) != null) {
stringBuffer.append(nextLine);
stringBuffer.append("\n");
}
fileReader.close();
myBook = stringBuffer.toString();
在文本文件中,每章都包含一個卷。 用“章”表示,然后用羅馬數字表示。 例如,第五章以“第V章”開頭
我需要將字符串分解為多個字符串,然后將它們全部添加到ArrayList中,這樣我才能編寫諸如“ nextChapter()”,“ previousChapter”,“ getChapter(int volumeNumber,int ChapterNumber”)之類的函數,這些函數將返回適用的字符串。例如,我在想這個;章節是一個ArrayList
public String nextChapter(){
currentChapter++;
return chapters(currentChapter);
}
如何將本書分為幾章和幾卷(一卷包含許多章)
我需要使用與ArrayList不同的數據結構嗎?如果可以,怎么辦? 我聽說HashMap可以使用鍵(也許類型String擁有章和卷這兩個鍵?),如果可以,我該怎么做?
謝謝
關於文件解析: String.split()
是一個非常有用的工具。 它支持正則表達式 ,這意味着您可以為其提供"CHAPTER [IVXLCDM]+"
,並且它將匹配出現的任何“ CHAPTER”后跟羅馬數字。 但是,請記住,正則表達式區分大小寫 。 同樣,使用此方法將不遵守各章的實際編號。 不論第一章是哪一章,都將放在結果數組中。 這可能不會成為問題,因為大多數書籍按順序包含其章節。
如果使用上面的示例匹配,則可能必須從章節文本的開頭和/或結尾處刪除換行符。 String.trim()
將為您完成此操作。
關於數據結構:在這種情況下,面向對象的編程可以使您受益匪淺。 而不是使用ArrayList<String>
來保存書的章節,而應該為書的不同部分創建類。 例如, Book
類的一個實例可以具有一個Volume
實例數組,每個Volume
實例都有一個Chapter
實例數組。 Chapter
可能包含帶有該章節內容的單個String
,也可能包含標題的另一個String
。
現在看來似乎還有更多工作要做,但從長遠來看會有所收獲。 類為用戶提供了一致的界面,還使您作為程序員可以保護您的數據。 通過定義諸如Volume getVolume(int)
或Chapter getChapter(int)
,可以為用戶提供一種更清潔,更有意義的方式來與數據進行交互。 相反,調用List
方法的含義可能更不明確。
您嘗試的操作並不困難,但並不像按關鍵字進行拆分那樣簡單。 在真實的書中,您可以輕松地在文本中找到單詞“章節”。 因此,如果按“章”的出現進行拆分,則會導致虛假的划分和錯誤構建的數據結構。
因此,您必須注意要考慮的標准,即文本“章節”(或“卷”)實際上是章節標題。 您已經說了一個:
我將添加下一個:
還有一個類似的體積規則,使用單詞“ VOLUME”(如果未指定其他條件)。
因此,如果您已經在逐行讀取文件 , 則最好在讀取文件時執行analisys文本,從而獲得更好的機會來區分行的開始和結束位置,並避免在文件中存儲大量數據。字符串(通常會導致性能下降)。 因此,應在分析文本的過程中建立數據結構。
數據結構應如下所示:
class Book
{
private List<Volume> volumes=...
public void addVolume(Volume volume) {...}
public Volume getVolume(int volume) {...}
public Chapter getChapter(int volume, int chapter) {...}
}
class Volume
{
private List<Chapter> chapters=...
public void addChapter(Chapter chapter) {...}
public Chapter getChapter(int chapter) {...}
}
class Chapter
{
private StringBuilder text=...
public void addText(String text) {...}
public String getText() {...}
}
解析算法如下:
Pattern chapterPattern=Pattern.compile("CHAPTER\s+[IVXLDC]+");
Pattern volumePattern=Pattern.compile("VOLUME\s+[IVXLDC]+");
Book book=new Book(...);
Volume currentVolume=null;
Chapter currentChapter=null;
while ((nextLine = bufferedReader.readLine()) != null) {
if (volumePattern.matcher(nextLine)).matches())
{
// It is a volume heading:
currentVolume=new Volume(...);
currentChapter=null;
book.addVolume(currentVolume);
}
else if (chapterPattern.matcher(nextLine)).matches())
{
// It is a chapter heading:
currentChapter=new Chapter(...);
currentVolume.addChapter(currentChapter);
}
else
{
currentChapter.addText((nextLine).append("\n"));
}
}
這種解析算法始終希望本書格式正確:它必須始終以卷標題開頭。 卷標題之后,必須有章節標題。 並且所有卷和章節都必須按順序出現(因此,羅馬數字可以忽略)。 如果沒有,將出現一個丑陋的例外。 因此,如果您想控制可能的錯誤格式,則必須考慮currentVolume或currentChapter中的null
值。
此外,沒有任何關於空行的規定。 在標題和章節標題之間留空行是否合法? 如果是這樣,則必須考慮到它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.