CSV读取器危险 - Java

时间:2016-09-11 15:25:26

标签: java arrays csv

我尝试读取CSV文件并通过java中的二维数组将每一行拆分为4个不同的整数值。

我正在使用openCSV 3.8。

为简单起见,请说这是CSV文件的内容(完整文件包含306行,就像这些一样):

76,67,0,1
77,65,3,1
78,65,1,2
83,58,2,2

我可以正常阅读该文件,我可以使用System.out.println将每个单独的值输出到控制台,如下所示:

76
67
0
1
77
65
3
1
78
65
1
2
85
58
2
2

不幸的是,我的代码设计为将每个值输入到一个单独的数组元素中,只将4个值保存在文件的最后一行。

这是我的java代码(不要介意iaData数组的大小,它的大小适合完整的CSV文件):

public static void main(String[] args) {

        //String outputStr = "";
        int[][] iaData = new int[306][4];
        int i = 0;
        int x = 0;

        try
        {
            //Get the CSVReader instance with specifying the delimiter to be used
             CSVReader reader = new CSVReader(new FileReader("haberman.data"),',');
            String [] nextLine = new String[1250];

            //Read one line at a time
            while ((nextLine = reader.readNext()) != null)
            {           
                for (i = 0; i <= 305; i++)
                {
                    for (x = 0; x <= 3; x++)
                    {
                        iaData[i][x] = Integer.parseInt(nextLine[x]);
                    }
                }
            }

            for (int z = 0; z <= 3; z++)
            {
            System.out.println(iaData[0][z] + "\n");
            }
            reader.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

使用此代码,我希望我的System.out.println(iaData[0][z] + "\n");将以下内容输出到控制台(文件第一行中的值):

76

67

0

1

不幸的是,事实并非如此,它实际输出以下内容(文件最后一行中的4个值):

83

58

2

2

我的代码有什么问题,iaData[0][0/1/2/3]实际输出了我期望在iaData[**3**][0/1/2/3]中保留的内容?

5 个答案:

答案 0 :(得分:6)

对于每一行,你开始用第一个索引i = 0写。 因此,对于每一行,您都会覆盖以前行中的所有信息:

       while ((nextLine = reader.readNext()) != null)
        {           
            for (i = 0; i <= 305; i++)
            {
                for (x = 0; x <= 3; x++)
                {
                    iaData[i][x] = Integer.parseInt(nextLine[x]);
                }
            }
        }

这可以解决您的问题:

int i = 0;
while ((nextLine = reader.readNext()) != null) {
    for (x = 0; x <= 3; x++) {
        iaData[i][x] = Integer.parseInt(nextLine[x]);
    }
    i++;
}

答案 1 :(得分:3)

您当前的问题是,对于每条线,您在整个2D阵列上进行迭代,无论是行方向还是列方向。这样做的结果是只有最后一行会反映当前读取的行。

相反,行计数器init-hook只应在从CSV文件中读取另一行后递增。目前,您一遍又一遍地为同一行增加i

i

答案 2 :(得分:1)

你的代码中有各种各样的东西是没有意义的。

首先,你正在尝试使用nextLine来容纳1250行。

String [] nextLine = new String[1250];

但是,你正在推动单一一行:

        while ((nextLine = reader.readNext()) != null)

要么你不需要第一个陈述;或者第二个问题出了什么问题。

对于你正在观察的实际错误:你也一直在写相同的行395次没有帮助。这就是你的代码正在做的事情;因为你读过的每一行都是

for (i = 0; i <= 305; i++)
{
   for (x = 0; x <= 3; x++)
   {
      hiaData[i][x] = Integer.parseInt(nextLine[x]);

所以你保持覆盖你的数据,而不是

line1
line2
...

你一直在写

line i
line i...

因此,最后,你只有最后一行。

我的建议:不要自己做那些与手动大小相关的迭代。只需使用

List<String[]> allLines = csvreader.readAll();

4个值,395行...... 没有。用这一个调用将所有这些都推入内存。

含义:库为您提供了一个很好的抽象,需要您一个代码行来读取所有内容。您选择编写20,30行代码。事情就是这样:你编写的代码越多,创建错误的机会就越大。

最后:不要在源代码中直接使用305,4,1205这样的数字。如果有的话,在那里使用常量。但是在你的循环中对这些值进行硬编码...... 非常糟糕的做法 - 你需要更改每个和任何处理输入的地方,例如5列进来,而不是4。

答案 3 :(得分:0)

问题:

1

for (i = 0; i <= 305; i++)

不需要此循环,因为reader.readNext()将收集所有行而无需进一步帮助。所以,这肯定是一种改进:

        int i = 0;
        while ((nextLine = reader.readNext()) != null)
        {           
            //for (i = 0; i <= 305; i++)
            //{
                for (x = 0; x <= 3; x++)
                {
                    iaData[i++][x] = Integer.parseInt(nextLine[x]);
                }
            //}
        }

2

你遇到的另一个问题是你只迭代第一个元素的元素:

        for (int z = 0; z <= 3; z++)
        {
        System.out.println(iaData[0][z] + "\n");
        }

相反:

        for (i = 0; i < iaData.length; i++)
        {
            for (int z = 0; z <= 3; z++)
            {
            System.out.println(iaData[i][z] + "\n");
            }
            System.out.println("");
        }

答案 4 :(得分:0)

如果程序要将整个文件读入数组......是不是将它读入内存并稍后处理?

像这样:

import au.com.bytecode.opencsv.CSVReader;

import java.io.IOException;
import java.io.StringReader;
import java.util.List;

public class Csv {

    public static void main(String[] args) throws IOException {
        String string = "76,67,0,1\n" +
                "77,65,3,1\n" +
                "78,65,1,2\n" +
                "83,58,2,2";

        CSVReader reader = new CSVReader(new StringReader(string),',');
        List<String[]> lines = reader.readAll();

        for (String[] entries : lines) {
            for (String entry:  entries) {
                System.out.println(Integer.parseInt(entry));
            }
        }
    }

}

注意内存问题并通过更改循环来设置上限或处理一行:

    String[] entries;
    while((entries = reader.readNext()) != null) {
        for (String entry : entries) {
            System.out.println(Integer.parseInt(entry));
        }
    }