【问题标题】:Java: Read .csv file and save into arraysJava:读取 .csv 文件并保存到数组中
【发布时间】:2012-11-06 04:06:24
【问题描述】:

我在尝试读取 .csv 文件并将每一列保存到数组中时遇到异常问题。 虽然,它可能看起来很长,但事实并非如此。我只有 15 个不同的数组。

这是行中的异常“Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2”

部门[i] = dataArray[2];

有什么我可以做的吗?

      BufferedReader CSVFile = 
            new BufferedReader(new FileReader("Sub-Companies.csv"));

      String dataRow = CSVFile.readLine();
      // Read the number of the lines in .csv file 
      // i = row of the .csv file
      int i = 0; 
      while (dataRow != null){
          i++;
          dataRow = CSVFile.readLine();

        }
      System.out.println(i);
      // Close the file once all data has been read.
      CSVFile.close();

      // End the printout with a blank line.
      System.out.println();

      // Save into arrays
      customer_id = new String[i];
      company_name = new String[i];
      department = new String[i];
      employer = new String[i];
      country = new String[i];
      zipcode = new String[i];
      address = new String[i];
      city = new String[i];
      smth1 = new String[i];
      smth2 = new String[i];
      phone_no1 = new String[i];
      phone_no2 = new String[i];
      email = new String[i];
      website = new String[i];
      customer_no = new String[i];

      // Read first line.
      // The while checks to see if the data is null. If 
      // it is, we've hit the end of the file. If not, 
      // process the data.
      int j;
      int counter;
      i = 0;

      // Read the file again to save the data into arrays
      BufferedReader CSV = 
            new BufferedReader(new FileReader("Sub-Companies.csv"));

      String data = CSV.readLine();

      while (data != null){
          String[] dataArray = data.split(";");
          for (String item:dataArray) {
            customer_id[i] = dataArray[0];
            company_name[i] = dataArray[1];
            department[i] = dataArray[2];
            employer[i] = dataArray[3];
            country[i] = dataArray[4];
            zipcode[i] = dataArray[5];
            address[i] = dataArray[6];
            city[i] = dataArray[7];
            smth1[i] = dataArray[8];
            smth2[i] = dataArray[9];
            phone_no1[i] = dataArray[10];
            phone_no2[i] = dataArray[11];
            email[i] = dataArray[12];
            website[i] = dataArray[13];
            customer_no[i] = dataArray[14];
            }


          //System.out.print(address[i] + "\n"); 
          data = CSV.readLine(); // Read next line of data.
          i++;
      }

提前谢谢你!

一些数据是 "E3B3C5EB-B101-4C43-8E0C-ADFE76FC87FE;"Var Welk" Inh. Kar;NULL;NULL;DE;16278;Rotr 3;Angermünde;NULL;NULL;03331/354348-0;0343331/ 364548-15;info@aalls.com;http://www.adss.com;ipo241",但可能有所不同(更小或更大)。

【问题讨论】:

  • 为什么要重新发明轮子?使用 CSV 解析库,例如 Super CSV 或我最喜欢的 opencsv。
  • 抛出该错误表示已使用非法索引访问了数组。索引大于或等于数组的大小。
  • 这对我防止异常有帮助吗?我在想一些尝试,抓住,但问题是我想确保正确保存数据
  • 请显示csv文件内容...
  • String[] dataArray = data.split(";");之后做System.out.println("array elements: " + dataArray.length);

标签: java arrays csv


【解决方案1】:

这应该可以解决问题:它基本上创建了 csv 文件的矩阵表示。

LinkedList<String[]> rows = new LinkedList<String[]>();
String dataRow = CSVFile.readLine();
// Read the number of the lines in .csv file 
// i = row of the .csv file
int i = 0; 
while ((datarow = CSVFile.readLine()) != null){
    i++;
    rows.addLast(dataRow.split(","));
}

String[][] csvMatrix = rows.toArray(new String[rows.size()][]);

在 csvMatrix[row][col]...

访问列时,通过执行以下操作断言您尝试访问的列号在范围内:

if(col < csvMatrix[row].length)

【讨论】:

  • 我明白你在说什么,但我不明白 if(col
  • 对不起,我错过了这一行的一些信息:这不是因为一行有 X 列,所以所有行的数量都相同......所以要小心,在尝试访问索引之前,请验证索引存在:在您的情况下,该行可能无效,因此您甚至可能希望忽略将其添加到列表中......所以不要使用“rows.addLast(dataRow.split(","));"在循环中,你可能有这个: String[] temp = dataRow.split(","); if(temp.length == ACCEPTED_COLUMN_COUNT) { rows.addLast(temp); }
  • 嘿@医生杀手。我刚刚解决了我的问题。非常感谢您的回复。
【解决方案2】:

最好使用ArraList&lt;String&gt;,如果你想使用convert as Array

您的问题是您没有计算行数来创建数组大小,但您正在添加数据 基于 split(";") 所以数组长度和从 split(";") 添加到数组中的可用值不匹配。

【讨论】:

  • 请多解释一下,这样能防止异常吗?
  • gh;ghj;ghjk;ghj;例如像这样你有两行,当你要创建数组时,你使用行数作为数组大小的 2。但是当你分割(“;”)时,它的大小是 4,你尝试向数组添加 4 个值它只能有 2 个值。所以会有 java.lang.ArrayIndexOutOfBoundsException. Thats all.
  • 现在我很困惑,在每个数组中,我从每一行保存一个条目。所以条目等于文件的行,不是吗?
  • @Dimitra 但你说他们都是 15 岁
  • @mcalex 在你建议的打印之后,是的,他们都是 15 :(
【解决方案3】:

您的代码存在几个问题。异常是由于其中一行不包含足够的 ';'分隔值。

您的代码的奇怪之处在于:

  for (String item:dataArray) {
    customer_id[i] = dataArray[0];

这只是意味着您重复相同的分配 15 次(只需删除 for (String item: ...))。

如果我是你,我会这样做:

创建一个类;像这样:

public class Customer {
    private String customerId;
    private String companyName;

    // ...
    public static Customer create(final String... args) {
        if (args.length != 15) {
            return null; // or throw an exception
        }
        final Customer rv = new Customer();
        rv.setCustomerId(args[0]);
        rv.setCompanyName(args[1]);
        // ...
        return rv;
    }

    public String getCustomerId() {
        return customerId;
    }

    public void setCustomerId(final String customerId) {
        this.customerId = customerId;
    }

    public String getCompanyName() {
        return companyName;
    }

    public void setCompanyName(final String companyName) {
        this.companyName = companyName;
    }
}

使用集合(如上面帖子中所建议的):

    BufferedReader csv = new BufferedReader(new FileReader("Sub-Companies.csv"));
    List<Customer> customers = new LinkedList<Customer>();

    String data;
    while ((data = csv.readLine()) != null){
        Customer customer = Customer.create(data.split(";"));
        if (customer != null) {
            customers.add(customer);
        }
    }

如果你需要数组而不是集合,你可以这样做:

Customer[] arr = customers.toArray(new Customer[customers.size()]);

使用库来读取文件...例如,您可以尝试http://opencsv.sourceforge.net/

【讨论】:

  • 我也在考虑使用if (args.length != 15) { return null; // or throw an exception ,然后将每个数组保存为数组[15],其他条目为NULL
【解决方案4】:
department[i] = dataArray[2];  

异常意味着dataArray 没有那么多元素(即 3 个)。
如果您想解析您的 CSV 文件,您可以通过指定任何缺失的元素必须有一个占位符来让您的生活更轻松。
我的意思是你可以有这样的记录:

a;b;c;d;e;f;g;h;j
其中每个字符代表列的值当元素缺少格式时必须为:
a;;;;;f;g;h;j不是 a;f;g;h;j

这不是一个不寻常的期望,而是 CSV 文件中的规范,并且会大大简化您的代码,并且会避免数组索引异常,因为您的行将始终具有预期的列

【讨论】:

  • “如果你想解析你的 CSV 文件,你可以通过指定任何缺失的元素必须有一个占位符来让你的生活更轻松。”我明白你的意思,但有没有办法做到这一点?也许,我能读多少遍“;”出现,然后添加“;”如果它丢失了。
  • 但是您的 CSV 文件是如何生成的?如果是手动生成的,那么只需为每个缺失的元素添加无关的 ;。如果您通过代码生成它们,则相同。因此,当您解析 CSV 行时,当您执行 split(';')知道返回数组的大小
  • 这个 cvs 文件是给我的。是的,当我拆分它时,我就知道了。
  • 如果给你,你应该指定对csv格式的期望
【解决方案5】:

使用数组列表:

public ArrayList<ArrayList<String>> parseDataFromCsvFile()
{
     ArrayList<ArrayList<String>> dataFromFile=new ArrayList<ArrayList<String>>();
     try{
         Scanner scanner=new Scanner(new FileReader("CSV_FILE_PATH"));
         scanner.useDelimiter(";");

         while(scanner.hasNext())
         {
            String dataInRow=scanner.nextLine();
            String []dataInRowArray=dataInRow.split(";");
            ArrayList<String> rowDataFromFile=new ArrayList<String>(Arrays.asList(dataInRowArray));
            dataFromFile.add(rowDataFromFile);
         }
         scanner.close();
     }catch (FileNotFoundException e){
        e.printStackTrace();
     }
     return dataFromFile;
}

调用方法(显示csv内容):

ArrayList<ArrayList<String>> csvFileData=parseDataFromCsvFile();

public void printCsvFileContent(ArrayList<ArrayList<String>> csvFileData)
{
    for(ArrayList<String> rowInFile:csvFileData)
    {
        System.out.println(rowInFile);
    }
}

【讨论】:

    【解决方案6】:

    如果您想使用 Gradle(而不是 Maven)将数据加载到参数化 JUnit 测试中,方法如下:

    // import au.com.bytecode.opencsv.CSVReader;
    @Parameters(name = "{0}: {1}: {2}")
    public static Iterable<String[]> loadTestsFromFile2() {
        String separator = System.getProperty("file.separator");
        File tFile = loadGradleResource( System.getProperty("user.dir") + 
            separator +  "build" + separator + "resources" + separator +  "test" + 
                separator + "testdata2.csv" );
        List<String[]> rows = null;
        if ( tFile.exists() ) {
            CSVReader reader = null;
            try {
                reader = new CSVReader( new FileReader( tFile ), ',' );
                rows = reader.readAll();
            } catch (FileNotFoundException e) {
                    e.printStackTrace();
            } catch (IOException e) {
                    e.printStackTrace();
            }   
        }
        staticlogger.info("Finished loadTestsFromFile2()");
        return rows;
    } 
    

    【讨论】:

      【解决方案7】:

      请检查java.util.StringTokenizer是否有帮助

      例子:

      StringTokenizer tokenizer = new StringTokenizer(inputString, ";")
      

      手册:StringTokenizer docs

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多