Java Csv-data字符串空间拆分错误

时间:2016-12-28 17:45:45

标签: java csv arraylist split space

我在使用命令时遇到了一些麻烦。

我有一个csv类型的文件,如下所示:

Merkmals-Nr .; Interne Teile-Nr .; Bereich; Fertigungsschritt; ...

阅读文件后,想要读取一行,然后在“;”之后拆分行使用此代码行。

List<String> datenListe = Arrays.asList(data.split(";"));

然后我做了一个system.println

印刷品的外观如何:
    Merkmals-NR。
    Interne Teile-Nr。
    Bereich
    Fertigungsschritt
    ......

印刷品的实际外观:
    Merkmals-NR。
    上网。

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
    at java.util.Arrays$ArrayList.get(Arrays.java:2866)
    at CsvEinlesen.main(CsvEinlesen.java:23)

我发现问题是由“Interne Teile-Nr”中的空间引起的。但我不知道如何解决空间问题。

这是完整的代码:

import java.io.*;

import java.util.*;


public class CsvEinlesen {
  public static void main(String[] args) {
    String fileName = "0-201-08-4473.csv";
    File file = new File(fileName);

    try {
      Scanner csvInputStream = new Scanner(file);

      while (csvInputStream.hasNext()) {
        String data = csvInputStream.next();

        List<String> datenListe = Arrays.asList(data.split(";"));

        for (int i = 0; i < 32; i++) {
          System.out.println(datenListe.get(i));
        }
      }

      csvInputStream.close();
    } catch (FileNotFoundException e) {
      e.printStackTrace();
      System.out.println("CSV-Datei nicht gefunden");
    }
  }
}

2 个答案:

答案 0 :(得分:0)

如果仍然像普通数组一样迭代数组,是否真的有必要将数组转换为List<String>?另外你为什么把32作为限制?这不安全 - 完全是因为您最终会收到ArrayIndexOutOfBoundsException等错误。

对于这个例子,我的建议就是像这样使用数组:

    //the rest of your code...
    while (csvInputStream.hasNext()) {
            String data = csvInputStream.next();

            String[] wordsInLine = data.split(";");

            for (int i = 0; i < wordsInLine.length; i++) {
              System.out.println(wordsInLine[i]);
            }
          }
   //the rest of your code ...

尝试一下,看看错误是否消失。

答案 1 :(得分:0)

我今天正在开展一项类似的任务(从CSV读取数据,但使用“,”分隔符)。 如果您有兴趣保持字段的顺序,并且知道您将拥有多少“列”,那么您可能想尝试使用正则表达式的解决方案。

这样做的原因:

  • 使用方法.split()拆分行value1 ;;; value2 ;; 你会得到一个数组:arr [0]:value1,arr [1]:value2。这有可能 不是很好,因为你可能想知道那个价值 代表你可能有一个提示,如果你知道它的顺序 CSV,但是你会以这种方式丢失这些信息。
  • 使用正如我将在示例中显示的正则表达式,你将能够 要尊重CSV值的顺序,您可以添加结果 你喜欢什么,一个字符串,ArrayList,List等数组 (因为你要求使用ArrayList我将使用它做出示例)
  • 您可能会学会在regexp中使用group来获取更具体的信息,以及 也可以根据您的需求建立更具体的注册表

<强>缺点:

  • 也许这不是一种有效的方式,在时间的意义上
  • 您可以选择自己拆分 “.nextIndexOf(separationChar)”以保持值的跟踪
  • 也许是其他人,我不知道

但是,这是我的解决方案:

public class RegExpSeparator {
    // if you have a convention for your CSV or file, that the first row
    // will contain the header you might count the header items and update the
    // column count so this method will be more generic
    // also to be more generic you can make a final var to store the separator
    // and append it to the stringbuilder in the method splitRow
    public static int columnCount = 7;

    public static void main(String args[]) {
        String testRow1 = "NaMe_wE132;-123.46;CEE Tue 23 Apr 1976 22:23:34;Value;Another_value;bla;blaa";
        String testRow2 = ";;Value1;;;;Value2";

        ArrayList<String> letsTestFirstCase = new ArrayList<String>(splitRow(testRow1));
        for (String item : letsTestFirstCase) {
            System.out.print(item + ";"); // we'll add and ; also at the end
        }
        System.out.println("");
        ArrayList<String> letsTestSecondCase = new ArrayList<String>(splitRow(testRow2));
        for (String item : letsTestSecondCase) {
            System.out.print(item + ";"); // we'll add and ; also at the end
        }
    }       

    private static ArrayList<String> splitRow (String toSplit) {
        StringBuilder buildPattern = new StringBuilder();
        //use this if you know how many columns you'll have, from the start
        for (int i = 0; i<columnCount-1; i++) {
            buildPattern.append("([^;]*);"); // to keep it simple I've assumed the fact that
            // you might have values like "Name_233, 23:45 PM, -123.45" and so on
            // * means 0 or more occurences of any char except for ;
        }
        buildPattern.append("([^;]*)"); //the last column will not be followed by a separator
        // the final regexp will be something like
        // (group1);(group2);...;(groupN)
        // and you might get the values by calling matcher.group(i)
        // where i will have values in the interval [1,N]
        // group(0) will return the WHOLE STRING!!
        String patternToString = buildPattern.toString();
        Pattern pattern = Pattern.compile(patternToString);
        Matcher matcher = pattern.matcher(toSplit);   // get a matcher object

        ArrayList<String> result = new ArrayList<String>();
        if (matcher.find()) {
            for (int i=1; i<=columnCount; i++){
                result.add(matcher.group(i)); // for the columns like ;; it will add the string ""
            }
        } else {
            System.out.println("Could not parse the given row");
        }
        return result;
    }
}

您可以使用TutorialsPoint.

中的示例详细了解regexp

注意:你应该将它作为一个单独的类,就像一个util / handler一样,只是为了这个例子,这样就可以在这里同时使用main和方法。祝你好运!