【问题标题】:Need help parsing strings in Java需要帮助在 Java 中解析字符串
【发布时间】:2011-04-06 13:41:32
【问题描述】:

我正在读取 Java 中的 csv 文件,并且根据给定行上字符串的格式,我必须对它做一些不同的事情。 csv 文件中包含的三种不同格式是(使用随机数):

833 “79、869” "56-57, 568"

如果它只是一个数字(833),我想将它添加到我的 ArrayList 中。如果它是用逗号分隔并用引号括起来的两个数字 ("79, 869)",我想解析出两个数字中的第一个 (79) 并将其添加到 ArrayList。如果是用引号括起来的三个数字(前两个数字用破折号隔开,第三个用逗号分隔 ["56-57, 568"],那么我想解析出第三个数字 (568) 并添加它到 ArrayList。

我无法使用 str.contains() 来确定给定行上的字符串是否包含破折号。谁能给我一些帮助?这是我目前所拥有的:

private static void getFile(String filePath) throws java.io.IOException {
    BufferedReader reader = new BufferedReader(new FileReader(filePath));
    String str;

    while ((str = reader.readLine()) != null) {

        if(str.endsWith("\"")){
            if (str.contains(charDash)){
                System.out.println(str);
            }
        }

    }

}

谢谢!

【问题讨论】:

  • 你是如何定义 charDash 的?并且每一行上是否只有一个逗号分隔值(即,如果该行上还有其他值,则可能不会发现该行以引号结尾)。
  • 这是您的 CSV 文件中的一行吗? 833 "79, 869" "56-57, 568"
  • 为什么没有人推荐正则表达式?

标签: java string parsing


【解决方案1】:

尽管这些天它受到了很多人的讨厌,但我仍然非常喜欢 StringTokenizer 这类东西。您可以将其设置为返回令牌,至少对我而言,它使处理变得微不足道,而无需与正则表达式交互

您必须使用 ",- 作为标记来创建它,然后在循环中启动它。

st=new StringTokenizer(line, "\",-", true);

然后你设置一个循环:

while(st.hasNextToken()) {
    String token=st.nextToken();

每个案例都成为循环的一小部分:

// Use punctuation to set flags that tell you how to interpret the numbers.
if(token == "\"") {
    isQuoted = !isQuoted;
} else if(token == ",") {
    ...        
} else  if(...) {
    ...
} else { // The punctuation has been dealt with, must be a number group
    // Apply flags to determine how to parse this number.
}

我意识到 StringTokenizer 现在已经过时了,但我不确定为什么。解析正则表达式再快不过了,而且语法是——好吧,我必须承认,拆分是一种非常好的语法。

我猜如果您和您一起工作的每个人都对正则表达式感到满意,您可以将其替换为 split 并迭代结果数组,但我不确定如何拆分以返回标点符号——可能是“ +" 来自其他答案,但我从不相信我传递给正则表达式的某些字符不会做完全出乎意料的事情。

【讨论】:

    【解决方案2】:

    以下代码适用于我(注意:我编写它时没有考虑优化 - 仅用于测试目的):

    public static void main(String args[]) {
        ArrayList<String> numbers = GetNumbers();
    }
    
    private static ArrayList<String> GetNumbers() {
        String str1 = "833";
        String str2 = "79, 869";
        String str3 = "56-57, 568";
    
        ArrayList<String> lines = new ArrayList<String>();
    
        lines.add(str1);
        lines.add(str2);
        lines.add(str3);
    
        ArrayList<String> numbers = new ArrayList<String>();
    
        for (Iterator<String> s = lines.iterator(); s.hasNext();) {
            String thisString = s.next();
    
            if (thisString.contains("-")) {
                numbers.add(thisString.substring(thisString.indexOf(",") + 2));
            } else if (thisString.contains(",")) {
                numbers.add(thisString.substring(0, thisString.indexOf(",")));
            } else {
                numbers.add(thisString);
            }
        }
    
        return numbers;
    }
    

    输出:

    833
     79
    568
    

    【讨论】:

      【解决方案3】:

      我认为三个正则表达式是你最好的选择 - 因为通过匹配,你也会得到你感兴趣的部分。我很讨厌正则表达式,但类似于:

      .*\-.*, (.+)
      
      .*, (.+)
      

      (.+)
      

      应该做到这一点(按顺序,因为最终模式匹配包括前两个在内的任何内容)。

      【讨论】:

        【解决方案4】:

        我建议使用实际采用字符而不是字符串的 indexOf 版本,因为这种方法要快得多。 (这是一个简单的循环,没有嵌套循环。)

          if (str.indexOf('-')!=-1) {
              System.out.println(str);
           }
        

        (注意单引号,所以这是一个字符,而不是字符串。)

        但是您必须拆分行并解析各个值。目前,您正在测试整行是否以引号结尾,这可能不是您想要的。

        【讨论】:

          【解决方案5】:

          这行得通吗?

          if(str.contains("-")) {
              System.out.println(str);
          } 
          

          我想知道 charDash 变量是否不是您所期望的。

          【讨论】:

            【解决方案6】:

                if (str.indexOf(charDash.toString()) > -1){
                    System.out.println(str);
                }
            

            做这个伎俩?

            顺便说一下,它比 contains... 最快,因为它实现了 indexOf

            【讨论】:

              最近更新 更多