繁体   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