我尝试读取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]
中保留的内容?
答案 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));
}
}