Używanie CsvBeanReader do odczytu pliku CSV ze zmienną liczbą kolumn
Pracuję więc nad analizowaniem pliku .csv. Wziąłem radę innego wątku gdzieś na StackOverflow i pobrałem SuperCSV. W końcu dostałem prawie wszystko, co działa, ale teraz natrafiłem na błąd, który wydaje się trudny do naprawienia.
Problem występuje, ponieważ dwie ostatnie kolumny danych mogą być wypełniane lub nie. Oto przykład pliku .csv z pierwszym wierszem, w którym brakuje ostatniej kolumny, a drugi wiersz całkowicie wypełniony:
2012: 07: 25,11: 48: 20,922, „uLog.exe”, „”, naciśnięto klawisz, 1246,341, -1.00, -1.00,1.00, Shift 2012: 07: 25,11: 48: 21,094, ” uLog.exe "," ", naciśnięto klawisz, 1246,341, -1.00, -1.00,1.00, b, Shift
Z mojego rozumieniaSuper CSV Javadoc, nie ma możliwości zapełnienia Java Bean za pomocąCsvBeanReader jeśli istnieje zmienna liczba kolumn. Wydaje się to naprawdę głupie, ponieważ czuję, że te brakujące kolumny powinny mieć wartość NULL lub inną wartość domyślną podczas inicjowania komponentu Bean.
Dla odniesienia, oto mój kompletny kod dla parsera:
public class ULogParser {
String uLogFileLocation;
String screenRecorderFileLocation;
private static final CellProcessor[] cellProcessor = new CellProcessor[] {
new ParseDate("yyyy:MM:dd"),
new ParseDate("HH:mm:ss"),
new ParseDate("SSS"),
new StrMinMax(0, 100),
new StrMinMax(0, 100),
new StrMinMax(0, 100),
new ParseInt(),
new ParseInt(),
new ParseDouble(),
new ParseDouble(),
new ParseDouble(),
new StrMinMax(0, 100),
new StrMinMax(0, 100),
};
public String[] header = {"Date", "Time", "Msec", "Application", "Window", "Message", "X", "Y", "RelDist", "TotalDist", "Rate", "Extra1", "Extra2"};
public ULogParser(String uLogFileLocation, String screenRecorderFileLocation)
{
this.uLogFileLocation = uLogFileLocation;
this.screenRecorderFileLocation = screenRecorderFileLocation;
}
public void parse()
{
try {
ICsvBeanReader reader = new CsvBeanReader(new BufferedReader(new FileReader(uLogFileLocation)), CsvPreference.STANDARD_PREFERENCE);
reader.getCSVHeader(false); //parse past the header
Entry entry;
entry = reader.read(Entry.class, header, cellProcessor);
System.out.println(entry.Application);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void sendToDB()
{
Query query = new Query();
}
}
I kod klasy Entry:
public class Entry
{
private Date Date;
private Date Time;
private Date Msec;
private String Application;
private String Window;
private String Message;
private int X;
private int Y;
private double RelDist;
private double TotalDist;
private double Rate;
private String Extra1;
private String Extra2;
public Date getDate() { return Date; }
public Date getTime() { return Time; }
public Date getMsec() { return Msec; }
public String getApplication() { return Application; }
public String getWindow() { return Window; }
public String getMessage() { return Message; }
public int getX() { return X; }
public int getY() { return Y; }
public double getRelDist() { return RelDist; }
public double getTotalDist() { return TotalDist; }
public double getRate() { return Rate; }
public String getExtra1() { return Extra1; }
public String getExtra2() { return Extra2; }
public void setDate(Date Date) { this.Date = Date; }
public void setTime(Date Time) { this.Time = Time; }
public void setMsec(Date Msec) { this.Msec = Msec; }
public void setApplication(String Application) { this.Application = Application; }
public void setWindow(String Window) { this.Window = Window; }
public void setMessage(String Message) { this.Message = Message; }
public void setX(int X) { this.X = X; }
public void setY(int Y) { this.Y = Y; }
public void setRelDist(double RelDist) { this.RelDist = RelDist; }
public void setTotalDist(double TotalDist) { this.TotalDist = TotalDist; }
public void setRate(double Rate) { this.Rate = Rate; }
public void setExtra1(String Extra1) { this.Extra1 = Extra1; }
public void setExtra2(String Extra2) { this.Extra2 = Extra2; }
public Entry(){}
}
A wyjątek, który otrzymuję (pamiętaj, że jest to inna linia niż mój powyższy przykład, brakuje dwóch ostatnich kolumn):
Exception in thread "main" The value array (size 12) must match the processors array (size 13): You are probably reading a CSV line with a different number of columns than the number of cellprocessors specified context: Line: 2 Column: 0 Raw line: [2012:07:25, 11:48:05, 740, uLog.exe, , Logging started, -1, -1, -1.00, -1.00, -1.00, ] offending processor: null at org.supercsv.util.Util.processStringList(Unknown Source) at org.supercsv.io.CsvBeanReader.read(Unknown Source) at processing.ULogParser.parse(ULogParser.java:59) at ui.ParseImplicitData.main(ParseImplicitData.java:15)
Tak, pisanie wszystkich tych, którzy je zabrali, było bólem w dupie. Przepraszam, ale prawdopodobnie nie mam idealnej konwencji w używaniu SuperCSV (jak na przykład CellProcessor, jeśli chcesz mieć niezmodyfikowany String), ale masz pomysł. Kod ten oczywiście nie jest kompletny. Na razie próbuję tylko odzyskać linię danych.
W tym momencie zastanawiam się, czy korzystanie z CsvBeanReader jest możliwe dla moich celów. Jeśli nie, jestem trochę zawiedziony, ponieważ CsvListReader (chciałbym opublikować hiperłącze, ale StackOverflow nie pozwala mi także, również głupi) jest tak samo łatwy, jak w ogóle nie używanie API i po prostu używanie Scanner.next ().
Każda pomoc byłaby doceniana. Z góry dziękuję!