有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

备选问题标题:拆分位于制表符分隔列表内的逗号分隔列表

我正在寻找一个不涉及其他包的解决方案 而不是标准的java例程。这一定是一个 以前已经解决了,我只是不知道该在哪些关键字上使用 我要找到它

我正在解析一个以制表符分隔的文件。我在分割行后对字段执行错误检查,以防止坏数据进入我的程序。除了一个领域,我几乎解决了所有问题。输入行的基本布局为:

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

字段3,按设计可包含:

  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. [弗雷德·弗林斯通]
  3. [弗雷德、巴尼、威尔玛]

然后我将字段3再次拆分为“,”

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"

温度[2]的拆分结果应为:
“弗雷德·弗林斯通”
“巴尼碎石”
“威尔玛·弗林斯通”

那就好了

编辑 已咨询设计团队并确认,对于所有字段,字段内不能有嵌入式选项卡

此外,他们还确认,在字段3中,字段内不能有带有项目的嵌入逗号

因此,输入如下:

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

应为字段3生成三个条目:

  • “弗雷德·弗林斯通”
  • “巴尼
  • 威廉“

我在另一个问题上向他们施压,这可能使整个问题变得毫无意义


共 (3) 个答案

  1. # 1 楼答案

    我想你想

    • 逗号分隔
    • 如果((第一个元素以双引号开始,但不以双引号结束)和(最后一个元素以双引号结束,但不以双引号开始))则删除这些双引号

    尽管如此,我还是想知道是否会有坏数据,比如

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

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

  2. # 2 楼答案

    只需删除“先”字,然后拆分

    temp = entry.replaceAll("\"", '').split("\t", 4);
    
  3. # 3 楼答案

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

    • 外部级别应在每次出现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();
    

    有效来看,由于其特殊性,该解决方案也有效,因为它只解析每个字符一次