簡體   English   中英

Java:解析帶有額外引號的字符串

[英]Java: Parsing Strings with extra quotes

備用問題標題:分割制表符分隔列表內的逗號分隔列表。

我正在尋找不涉及標准Java例程以外的其他程序包的解決方案。 這必須是之前已經解決的問題,我只是不知道在Stackoverflow上使用哪個關鍵字來找到它!

我正在解析一個制表符分隔的文件。 分割行后,我在字段上執行錯誤檢查,以防止不良數據進入程序。 除了一個領域,我幾乎解決了所有問題。 輸入線的基本布局是:

field1<tab>field2<tab>field3<tab>field4

根據設計,field3可以包含:

  1. 空字符串:

     field1<tab>field2<tab><tab>field4 
  2. 一串,帶或不帶空格:

     field1<tab>field2<tab>Fred Flintstone<tab>field4 
  3. 用逗號分隔的多個字符串:

     field1<tab>field2<tab>Fred, Barney, Wilma<tab>field4 

該行的讀取和拆分如下:

    String entry = pq2File.readline();
    String[] temp;
    temp = entry.split("\t", 4);

當我將輸入行除以“ \\ t”時,在上述每種情況下,我的第三個字段(temp [2])的設置如下:

  1. []
  2. [Fred Flintstone]
  3. [弗雷德,巴尼,威爾瑪]

然后,我再次用“,”分割field3

ArrayList<String> names = 
     new ArrayList<String>(Arrays.asList(temp[2].split(",")));

在上述每種情況下,在ArrayList名稱中給我以下值

  1. [空]
  2. 弗雷德·弗林特斯通
  3. 弗雷德
    巴尼
    威爾瑪

當我使用文本編輯器創建文件或使用SQL語句將數據從我無法訪問的外部遠程系統中拉出時,所有這些操作都可以正確處理。 用戶堅持使用MS EXCEL創建文件會帶來問題。 在這種情況下,該行如下所示:

field1<tab>field2<tab>"Fred, Barney, Wilma"<tab>field4

當我解析行時,我的變量獲取值

"Fred, Barney, Wilma"

並以“,”將其分割為:
“弗雷德
巴尼
威爾瑪”

顯然,我想擺脫多余的“”標記。我是否正在尋找解決方案,以便在拆分字段之前刪除“”標記? 還是等到字段拆分之后才有意義(更少的代碼),然后再看第一和最后一項。 我問,因為這行可能是:

field1<tab>field2<tab>"Fred Flintstone", "Barney Rubble", "Wilma Flintstone"<tab>field4 

在這種情況下,我希望temp [2]變為:

"Fred Flintstone", "Barney Rubble", "Wilma Flintstone"

並且temp [2]的結果拆分應導致:
“弗雷德摩登原始人”
“巴尼·魯伯”
“威爾瑪打火石”

很好。

編輯已咨詢設計團隊,並確認對於所有字段,這些字段中都沒有嵌入的選項卡。

此外,他們已經確認,在字段3中,該字段內沒有帶逗號的項目。

因此,輸入如下內容:

field1<tab>field2<tab>"Fred Flintstone", "Barney, Wilma"<tab>field4 

應為field3產生三個條目:

  • “弗雷德摩登原始人”
  • “巴尼
  • Wilam”

我正向他們施加壓力,要求他們解決可能使整個問題困擾的另一個問題。

你想

  • 以逗號分隔
  • 如果((第一個元素以雙引號開頭但不以double__quote結束)和(最后一個元素以雙引號結尾但不以雙引號開頭)),則刪除那些雙引號

不過,我想知道是否會有壞數據,例如

field1<tab>field2<tab>"Fred Flintstone", "Barney, Wilma"<tab>field4 

導致各種臟數據。 您可能需要嚴格定義語法,而不是使用示例,此時解析應該變得很簡單。

我建議您分兩個級別對特定的解析器進行編碼:

  • 外層應在每次出現TAB時停止。
  • 內部級別應在每次出現逗號時停止,並丟棄第一個字符引號和最后一個字符引號。

從理論上講,我並沒有在這里發表我的建議:

public class CombinedStringParser
{
    private final String src;

    private final char delimitter;

    private int currentPos=0;

    public CombinedStringParser(String src, char delimitter)
    {
        super();
        this.src=src;
        this.delimitter=delimitter;
    }

    public String nextToken()
    {
        int initialPos=this.currentPos;
        int x=0;
        while (this.currentPos < this.src.length())
        {
            char c=this.src.charAt(this.currentPos++);
            if (c == this.delimitter)
            {
                x=-1;
                break;
            }
        }
        return this.src.substring(initialPos, this.currentPos + x);
    }

    public List<String> nextListOfTokens(char listDelimitter)
    {
        int initialPos=this.currentPos;
        List<String> list=new ArrayList<String>();
        while (this.currentPos < this.src.length())
        {
            char c=this.src.charAt(this.currentPos++);
            if (c == this.delimitter)
            {
                break;
            }
            else
            {
                if (c == listDelimitter)
                {
                    int p1=initialPos;
                    int p2=this.currentPos - 1;
                    if (this.src.charAt(p1) == '\"')
                    {
                        p1++;
                    }
                    if (this.src.charAt(p2 - 1) == '\"')
                    {
                        p2--;
                    }
                    list.add(this.src.substring(p1, p2));
                    initialPos=this.currentPos;
                }
            }
        }
        if (initialPos < this.currentPos)
        {
            int p1=initialPos;
            int p2=this.src.length();
            if (this.src.charAt(p1) == '\"')
            {
                p1++;
            }
            if (this.src.charAt(p2 - 1) == '\"')
            {
                p2--;
            }
            list.add(this.src.substring(p1, p2));
        }
        return list;
    }
}

如何使用它:

CombinedStringParser parser=new CombinedStringParser(src, '\t');
String firstToken=parser.nextToken();
String secondToken=parser.nextToken();
List<String> thirdToken=parser.nextListOfTokens(',');
String fourthToken=parser.nextToken();

Appart從有效開始 ,由於其特殊性,該解決方案也是有效的 ,因為它只解析每個字符一次

只需先刪除“,然后拆分。

temp = entry.replaceAll("\"", '').split("\t", 4);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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