在Java中将CSV数据解析为数组

6

我正在尝试将一个CSV文件导入到数组中,以便在Java程序中使用。CSV文件已经成功导入并在终端上显示输出,但是它会抛出以下错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1 
at CompareCSV.main(CompareCSV.java:19)

最后,当我尝试调用数组中的元素时,也会显示相同的错误。我的代码如下:

import java.io.*;
import java.util.*;

public class CompareCSV {

    public static void main(String[] args) {

        String fileName = "sampledata1.csv";
        try {
            BufferedReader br = new BufferedReader( new FileReader(fileName));
            String strLine = null;
            StringTokenizer st = null;
            int lineNumber = 0, tokenNumber = 0;

            while((fileName = br.readLine()) != null) {
                lineNumber++;
                String[] result = fileName.split(",");
                for (int x=0; x<result.length; x++) {
                    System.out.println(result[x]);
                }
            }
        }

        catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }   
}

2
你为什么在for循环中使用硬编码常量,而不是结果大小? - Perception
你可以使用现有的Java CSV API来满足你的需求: http://sourceforge.net/projects/csv4j/或者http://sourceforge.net/projects/javacsv/。 - Benoit Courtine
@Perception是正确的,你确定读取一行后有3个值吗? - Marcelo
@Perception:我那样做只是为了暂时测试我是否会继续触发异常,实际上应该是result.length。 - Roger Chen
4个回答

6

使用专业的CSV解析器要比自己搞一个有缺陷的解析器更好: http://opencsv.sourceforge.net/

CSV并不是一个像人们想象的那样简单的格式(是的,一行可以包含不分隔两个数据片段的,)。


一个人应该能够解析一个简单的 CSV 文件,而不使用一些“csv4j”库... - Andreas Dolk
互联网上的其他阅读材料表明,拉取CSV库可能更容易。但是,如果您知道如何将简单的CSV文件轻松解析为可以被Java程序的其余部分访问的数组,我将非常感激! - Roger Chen
@Andreas_D:但是为什么要浪费时间呢?CSV解析不能使用String.split,因为逗号只有在没有被引号包围时才是分隔符。 - Mathias Schwarz
@Roger:没有什么比下载库并让它完成工作更容易的了。你代码中的具体问题是,尽管长度比3短,但你还是迭代到了3,但你离CSV解析器还很远。 - Mathias Schwarz
但是OpenCSV非常简单。它将为您提供您正在寻找的确切数组,并且您可以按照您尝试的方式精确迭代行。请参见此处的示例:http://opencsv.sourceforge.net/#how-to-read - Mathias Schwarz
显示剩余2条评论

2

当有很多优秀的库存在时,我建议您不要重新发明轮子。尝试使用uniVocity-parsers,以下代码片段可供参考:

public static void main(String[] args) throws FileNotFoundException {

    /**
     * ---------------------------------------
     * Read CSV rows into 2-dimensional array
     * ---------------------------------------
     */

    // 1st, creates a CSV parser with the configs
    CsvParser parser = new CsvParser(new CsvParserSettings());

    // 2nd, parses all rows from the CSV file into a 2-dimensional array
    List<String[]> resolvedData = parser.parseAll(new FileReader("/examples/example.csv"));

    // 3rd, process the 2-dimensional array with business logic
    // ......
}

如您所见,只需两行代码即可完成将CSV数据解析为数组的任务。此外,该库提供了完整的功能列表,具有出色的性能。


2

这是上述问题的答案

 public class Readline {

/**
 * @param args
 */
public static void main(String[] args) {
    String fileName = "C:/Users/karthikrao/Desktop/cvsFile.csv";
    ArrayList<Integer> margins = new ArrayList<Integer>();
    BufferedReader br;
    String line, token;
    int i;
    try {
        br = new BufferedReader(new FileReader(fileName));
        try {
            while ((line = br.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(line, ",\"");
                i = 0;
                while (st.hasMoreTokens()) {
                    token = st.nextToken();
                    if (margins.size() <= i) {
                        margins.add((Integer) token.length());
                    } else {
                        margins.set(
                                i,
                                Math.max(margins.get(i),
                                        (Integer) token.length()));
                    }
                    i++;
                }
            }

            br = new BufferedReader(new FileReader(fileName));
            while ((line = br.readLine()) != null) {
                StringTokenizer st = new StringTokenizer(line, ",\"");
                i = 0;
                while (st.hasMoreTokens()) {
                    token = st.nextToken();
                    System.out.print(token);
                    for (int j = 0; j < margins.get(i) - token.length(); j++) {
                        System.out.print(" ");
                    }
                    System.out.print("|");
                    i++;
                }
                System.out.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }

}

}


0

看起来你的假设,即文件中的每行总是有三列并非所有行都成立。将for循环语句替换为以下行以消除异常并查看其原因:

for (int x=0; x<result.length; x++)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接