2

ive got this specification for a CSV file:

  • Key – Structured as Category:ID, where ID is a sequence number. There is no need (or use) to split this into its two pieces, just treat the key as a single unique value
  • Brand – Manufacturer of the product
  • Model – Model name of the product
  • WeightInKg – Weight of the product,rounded to the nearest kg
  • Price – Selling price of the product to 2 decimal places (2dp)

and i have got this code to tokenize each row:

public WarehouseItem(String warehouseItem) {
  String key, brand, model;
  int weightInKG;
  double price; 
  StringTokenizer strTok;

  strTok = new StringTokenizer(warehouseItem);
  try {
    key = strTok.nextToken();
    brand = strTok.nextToken();
    model = strTok.nextToken();
    weightInKG = Integer.parseInt(strTok.nextToken());
    price = Double.valueOf(strTok.nextToken());
  }
  catch (Exception e) {
    throw new IllegalStateException("CSV row had invalid format");
  }
}

when i try to run it i get the IllegalStateException for the CSV file.

Exception in thread "main" java.lang.IllegalStateException: CSV row had invalid format
    at WarehouseItem.<init>(WarehouseItem.java:23) // throwing exception
    at main.loadRecords(main.java:63) // records[numRows] = new WarehouseItem(warehouseItem); storing into array of objects
    at main.main(main.java:26) // loadRecords(); calling the function which reads a line
    at main.loadRecords(main.java:78) // main(null); recursing back to main
    at main.main(main.java:26) // loadRecords(); calling the function which reads a line

Heres an example of a row in the CSV file:

Couch:6,Fremarc,Deluxe,101,1871.7

im thinking maybe its because key has ID as a sequence number?? or does that not matter at all?? im confused and any help would be appreciated

6
  • 1
    Can you post the exact error you're getting? EDIT: No... you can't. Can you take it out of the try catch block, run it, and then tell us what error you're getting? Commented Oct 28, 2013 at 3:21
  • i get a NoSuchElementException now when i removed it on the try-catch block Commented Oct 28, 2013 at 3:25
  • What's line 23? Line 26? Line 63? Line 78? Commented Oct 28, 2013 at 3:26
  • the throwing exception part Commented Oct 28, 2013 at 3:26
  • EDIT: Nevermind... yea. What's the stacktrace look like when you're not in the try catch block? It will reference the line that's actually throwing the actual exception you need to figure out. Commented Oct 28, 2013 at 3:28

3 Answers 3

12

You're probably best off with a library. CSV can be surprisingly tricky to parse. Have a look at OpenCSV:

http://opencsv.sourceforge.net/

CSVParser parser = new CSVParser();
String[] fields = parser.parseLine(line);
Sign up to request clarification or add additional context in comments.

1 Comment

This is better than String.split(), especially in cases where one column in the CSV is of type string and might contain spaces or commas.
3

StringTokenizer is a little heavy for what you are trying to do (and at the same time, not complex enough if you are looking to parse the exact CSV format with double quotes).

An easier approach would be using String.split method, like this:

public WarehouseItem(String warehouseItem) {
    String key, brand, model;
    int weightInKG;
    double price; 
    String[] tok = warehouseItem.split(",");
    if (tok.length != 5) {
        throw new IllegalStateException("Invalid CSV: not enough columns");
    }
    key = tok[0];
    brand = tok[1];
    model = tok[2];
    weightInKG = Integer.parseInt(tok[3]);
    price = Double.valueOf(tok[4]);
    // Do something with the values you've got
    ...
}

7 Comments

This is definitely the approach I'd take. In every language in which I deal with a CSV, I always look for something like Java's String.split method.
i just used your way of doing things and it worked! ive successfully stored the csv rows in an array of objects. thanks
hey when i try to print it by using System.out.println(records[numRows]) (records is WarehouseItem[] and numRows is just a counter which is initialized to 0 and incremented by 1 after reading each line) i get the line WarehouseItem@b4e29b
@JadSapida You need to provide an override of the toString() method to see it print nicely.
sorry im fairly new to programming and i dont know what you mean :/
|
0

with org.apache.commons:commons-csv:1.9.0

    public static List<String> csvLineParse(String line) {
            try (CSVParser parse = CSVParser.parse(line, CSVFormat.DEFAULT)) {
                return parse.getRecords().get(0).toList();
            } catch (Exception e) {
                throw new RuntimeException("Failed parse line: " + line, e);
            }
    }


    @Test
    void test() {
            assertEquals(asList("a", "b"), csvLineParse("a,b"));
            assertEquals(asList("a", "b", ""), csvLineParse("\"a\",b,"));
            assertEquals(asList("I'a good, good.", "", ""), csvLineParse("\"I'a good, good.\",,"));
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.