簡體   English   中英

通過標記分割字符串?

[英]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方法的含義可能更不明確。

您嘗試的操作並不困難,但並不像按關鍵字進行拆分那樣簡單。 在真實的書中,您可以輕松地在文本中找到單詞“章節”。 因此,如果按“章”的出現進行拆分,則會導致虛假的划分和錯誤構建的數據結構。

因此,您必須注意要考慮的標准,即文本“章節”(或“卷”)實際上是章節標題。 您已經說了一個:

  • 一章以“ CHAPTER”一詞為首,加上求和間距再加上羅馬數字。

我將添加下一個:

  • 該標題占據一整行文本。

還有一個類似的體積規則,使用單詞“ 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM