Java:使用额外引号解析字符串

时间:2016-01-18 22:28:30

标签: java string split

备用问题标题:拆分以制表符分隔的列表中的逗号分隔列表。

我正在寻找一种不涉及其他包装的解决方案 比标准的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
    
  4. 读取并拆分行如下:

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

    当我将输入行拆分为&#34; \ t&#34;在上述每种情况下,我的第三个字段(temp [2])设置如下:

    1. []
    2. [Fred Flintstone]
    3. [弗雷德,巴尼,威尔玛]
    4. 然后我再次通过&#34;,&#34;分割field3。

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

      在上面的每个案例

      中给出了ArrayList名称中的以下值
      1. [empty]
      2. Fred Flintstone
      3. 佛瑞德
         巴尼
         威尔玛
      4. 当我使用文本编辑器创建文件或SQL语句将数据从我无法访问的外部远程系统中拉出时,所有这些都得到了正确处理。问题在于用户坚持使用MS EXCEL来创建文件。在这种情况下,该行看起来像这样:

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

        当我解析该行时,我的变量得到值

        "Fred, Barney, Wilma"
        

        将其拆分为&#34;,&#34;结果:
           &#34;佛瑞德
           巴尼
           威尔玛&#34;

        显然我想摆脱额外的&#34;分数。我在寻找解决方案来消除&#34;我分裂之前的标记?或者更有意义(更少的代码)等待字段分割后,然后只看第一个和最后一个项目。我问,因为这条线可能是:

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

        在这种情况下,我希望temp [2]成为:

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

        并导致temp [2]的分割应该导致:
        &#34; Fred Flintstone&#34;
        &#34; Barney Rubble&#34;
        &#34; Wilma Flintstone&#34;

        这没关系。

        修改 已咨询设计团队并确认对于所有字段,字段中不能嵌入选项卡。

        此外,他们已经确认在字段3中,字段内没有嵌入逗号。

        因此,输入如:

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

        应该为field3产生三个条目:

        • &#34; Fred Flintstone&#34;
        • &#34;巴尼
        • Wilam&#34;

        我正在向他们提出另一个可能使整个问题无法解决的问题......

3 个答案:

答案 0 :(得分:1)

你想要

  • 以逗号分割
  • If((第一个元素以双引号开头,但不以double-_quote结尾)和(最后一个元素以双引号结尾但不以双引号开头))然后删除那些doble-quotes

不过,我想知道是否有不良数据,比如

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

导致各种脏数据。您可能需要严格定义语法而不是使用示例,此时解析应该变得微不足道。

答案 1 :(得分:1)

我建议您在两个级别编写特定解析器

  • 每次出现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();

来自有效的公寓,由于其特殊性,此解决方案也高效,因为它只解析每个

答案 2 :(得分:0)

只需删除&#34;首先,然后拆分。

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