2012-11-17 100 views
3

我尝试读取.csv文件并将每列保存到数组中时出现异常问题。 虽然看起来很长的程序,但事实并非如此。我只有15个不同的阵列。Java:读取.csv文件并保存到数组中

这是例外 “异常在线程 ”主“ 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;[email protected];http://www.adss.com;ipo241“,但可能有所不同(更小或更大)。

+4

为什么重新发明轮子?使用像Super CSV或我最喜欢的opencsv这样的CSV解析库。 – dnault

+1

引发该错误以指示已使用非法索引访问数组。该索引大于或等于数组的大小。 –

+0

这会帮助我防止异常吗?我想的东西尝试,赶上,但问题是,我想确保数据正确保存 –

回答

2

最好是使用ArraList<String>,如果你想要convert as Array

你的问题是你正在计算创建数组大小的行数,但是你正在添加基于split(“;”)的数据 ,所以数组长度和可用值不匹配,以便从split(“ “)。

+0

请详细解释一下,这会防止异常吗? –

+0

gh; ghj; ghjk; ghj;例如像这样你有两行,当你要创建数组时,你使用行数为2来表示数组的大小。但是当你分割(“;”)时,它的大小是4,并且你尝试给数组添加4个值其中只能有2个值。所以会有java.lang.ArrayIndexOutOfBoundsException.Thats全部。 – sunleo

+0

现在我很困惑,在每个数组中,我从每一行保存一个条目。所以条目等于文件的行,不是? –

2

你的代码有几个问题。这种例外情况是由于其中一行没有包含足够的';'分隔值。

你的代码奇怪的是这一点:

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

这只是意味着你重复同样的作业15次(只是删除了(字符串项:...))。

如果我是你,我会做以下事情:

创建一个类;是这样的:

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/

+0

我正在考虑使用'if(args.length!= 15){ 返回null; //或者抛出一个异常'this this,然后将这些数组作为数组[15]与其他条目一起保存NULL –

1
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文件的规范,并会简化你的代码很多,并会避免数组索引异常因为你的行将总是有预期的列

+0

“如果要解析CSV文件,可以通过指定缺少的元素成为占位符。“我明白你的意思,但有没有办法做到这一点?也许,我可以读多少次“;”出现,然后添加“;”如果它丢失。 –

+0

但是,您的CSV文件是如何生成的?如果手动添加多余的';'为每个缺少的元素。如果你通过代码生成它们,它是相同的。所以,当你分割(';')'你知道*返回数组的大小时,解析CSV行。 – Cratylus

+0

这个CVS文件是给我的。 Yeap,当我分裂它时,我知道它。 –

4

这应该做的窍门:它基本上创建了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 [行] [COL] ...

当访问到列,断言,你要访问的山坳数量是在范围内做:

if(col < csvMatrix[row].length) 
+0

我明白你在说什么,但我不知道如何(col

+0

对不起,我错过了一些信息在这一行上: 这不是因为一行有X列,所有行将具有相同的数量...... 因此要谨慎,在尝试访问索引之前,验证索引是否存在:在您的情况中,行可能无效,因此你甚至可以忽略将它添加到列表中......所以不是“rows.addLast(dataRow.split(”,“));”在循环中,你可能有这样的: String [] temp = dataRow.split(“,”); if(temp.length == ACCEPTED_COLUMN_COUNT){row.addLast(temp); } –

+0

嘿@doctor杀手。我刚刚解决了我的问题。非常感谢您的回复。 –

0

如果你想将数据加载到使用摇篮(而不是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; 
} 
0

请检查java.util.StringTokenizer帮助

例子:

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

手册:StringTokenizer docs

1

使用的ArrayList:

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); 
    } 
}