将CSV文件导入到二维字符串数组中。

4

我需要将一个文本文件读入到一个二维数组中。

唯一的问题是,数组的宽度会变化,最大为9列。我不知道有多少行。

例如,有些行有6列,而有些行有9列。

以下是我的CSV文件的一小部分:

1908,Souths,Easts,Souths,Cumberland,Y,14,12,4000
1909,Souths,Balmain,Souths,Wests,N
1910,Newtown,Souths,Newtown,Wests,Y,4,4,14000
1911,Easts,Glebe,Glebe,Balmain,Y,11,8,20000
1912,Easts,Glebe,Easts,Wests,N
1913,Easts,Newtown,Easts,Wests,N

以下是我目前的代码:

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

public class ass2 {

    public static void main(String[] args) throws IOException {
        readData();

    }

    public static void readData() throws IOException{
        BufferedReader dataBR = new BufferedReader(new FileReader(new File("nrldata.txt")));
        String line = "";

        ArrayList<String[]> dataArr = new ArrayList<String[]>(); //An ArrayList is used because I don't know how many records are in the file.

        while ((line = dataBR.readLine()) != null) { // Read a single line from the file until there are no more lines to read

            String[] club = new String[9]; // Each club has 3 fields, so we need room for the 3 tokens.

            for (int i = 0; i < 9; i++) { // For each token in the line that we've read:
                String[] value = line.split(",", 9);                
                club[i] = value[i]; // Place the token into the 'i'th "column"
            }

            dataArr.add(club); // Add the "club" info to the list of clubs.
        }

        for (int i = 0; i < dataArr.size(); i++) {
            for (int x = 0; x < dataArr.get(i).length; x++) {
                System.out.printf("dataArr[%d][%d]: ", i, x);
                System.out.println(dataArr.get(i)[x]);
            }
        }
    }

The error I get is:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
at ass2.readData(ass2.java:23)
at ass2.main(ass2.java:7)

有人能帮个忙吗?:'(

谢谢!


1
你的代码中第49行是哪一行?另外,你应该将String[] value = line.split(",", 9);这一行移到循环之前。 - Ted Hopp
4个回答

10
你可以使用 OpenCSV 来读取CSV文件。
// Read all
CSVReader csvReader = new CSVReader(new FileReader(new File("nrldata.txt")));
List<String[]> list = csvReader.readAll();

// Convert to 2D array
String[][] dataArr = new String[list.size()][];
dataArr = list.toArray(dataArr);

1
这使事情变得非常容易,我喜欢这比被接受的答案更好。 - qed
我们应该导入什么? - user4410354

3

问题出在你的内循环上。无论一行有多少个值,你都试图访问value的9个元素。首先,你应该将对value的赋值移动到内循环之前。然后,你需要将循环迭代次数限制为9和value长度的最小值:

String[] value = line.split(",", 9);                
int n = Math.min(value.length, data.length);
for (int i = 0; i < n; i++) { // For each token in the line that we've read:
    data[i] = value[i]; // Place the token into the 'i'th "column"
}

请注意,data的末尾元素将是null

实际上,您并不需要“minimum”部分,因为您将“9”作为第二个参数传递给split()函数。 - gkalpak
@ExpertSystem - 这是真的。这有点像腰带和吊带,以防代码发展并且data某种方式可能比9短(可能是无意中)。在这里使用符号常量比将文字“9”散布在整个代码中更好。 - Ted Hopp

1
您会遇到错误,因为您试图在只包含6个标记的行上访问第7个标记(索引为6)。请进行以下替换:
for (int i = 0; i < 9; i++) { // For each token in the line that we've read:
    String[] value = line.split(",", 9);                
    data[i] = value[i]; // Place the token into the 'i'th "column"
}

使用这个:
String[] value = line.spkit(",", 9);   // Split the line into max. 9 tokens
for (int i = 0; i < value.length; i++) {
    data[i] = value[i];   // Add each token to data[]
}

实际上,您可以用这个一行代码替换整个while循环体:
dataArr.add(Arrays.copyOf(line.split(",", 9), 9));

请看这个简短演示

这应该被标记为答案!很棒 @gkalpak - Martins

0

你可以使用ArrayListList代替数组。由于List是动态可增长的,因此您无需考虑其大小。

List<List<String>> dataArr = new ArrayList<List<String>>();

while ((line = dataBR.readLine()) != null){ 
        for (int i = 0; i < 9; i++) 
            dataArr.add(Arrays.asList(line.split(",", 9)));                
}

1
这不是ArrayIndexOutofBound的解决方案,如果他使用错误的索引,仍然可能会遇到相同的异常。 - sanbhat
1
我提出了一个更好的解决方案,我想你误解了我的意思 :) - Subhrajyoti Majumder

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