JAVA - import CSV to ArrayList

2019-02-17 10:42发布

问题:

I'm trying import CSV file to Arraylist using StringTokenizer:

public class Test
{
  public static void main(String [] args)
  {
    List<ImportedXls> datalist = new ArrayList<ImportedXls>();

    try
    {
      FileReader fr = new FileReader("c:\\temp.csv");
      BufferedReader br = new BufferedReader(fr);
      String stringRead = br.readLine();

      while( stringRead != null )
      {
        StringTokenizer st = new StringTokenizer(stringRead, ",");
        String docNumber = st.nextToken( );
        String note = st.nextToken( );  /** PROBLEM */
        String index = st.nextToken( ); /** PROBLEM */

        ImportedXls temp = new ImportedXls(docNumber, note, index);
        datalist.add(temp);

        // read the next line
        stringRead = br.readLine();
      }
      br.close( );
    }
    catch(IOException ioe){...}

    for (ImportedXls item : datalist) {
      System.out.println(item.getDocNumber());
    }
  }
}

I don't understand how the nextToken works, because if I keep the initialize three variables (docNumber, note and index) as nextToken(), it fails on:

Exception in thread "main" java.util.NoSuchElementException
    at java.util.StringTokenizer.nextToken(Unknown Source)
    at _test.Test.main(Test.java:32)

If I keep docNumber only, it works. Could you help me?

回答1:

It seems that some of the rows of your input file have less then 3 comma separated fields.You should always check if tokenizer has more tokens (StringTokenizer.hasMoreTokens), unless you are are 100% sure your input is correct.

CORRECT parsing of CSV files is not so trivial task. Why not to use a library that can do it very well - http://opencsv.sourceforge.net/ ?



回答2:

Seems like your code is getting to a line that the Tokenizer is only breaking up into 1 part instead of 3. Is it possible to have lines with missing data? If so, you need to handle this.



回答3:

Most probably your input file doesn't contain another element delimited by , in at least one line. Please show us your input - if possible the line that fails.

However, you don't need to use StringTokenizer. Using String#split() might be easier:

...
while( stringRead != null )
{
    String[] elements = stringRead.split(",");

    if(elements.length < 3) {
      throw new RuntimeException("line too short"); //handle missing entries
    }

    String docNumber = elements[0];
    String note = elements[1];
    String index = elements[2];

    ImportedXls temp = new ImportedXls(docNumber, note, index);
    datalist.add(temp);

    // read the next line
    stringRead = br.readLine();
}
...


回答4:

You should be able to check your tokens using the hasMoreTokens() method. If this returns false, then it's possible that the line you've read does not contain anything (i.e., an empty string).

It would be better though to use the String.split() method--if I'm not mistaken, there were plans to deprecate the StringTokenizer class.