Uso de CsvBeanReader para leer un archivo CSV con un número variable de columnas
Así que estoy trabajando en analizar un archivo .csv. Seguí el consejo de otro hilo en algún lugar de StackOverflow y descargué SuperCSV. Finalmente conseguí que casi todo funcionara, pero ahora me he topado con un error que parece difícil de solucionar.
El problema se produce porque las dos últimas columnas de datos pueden o no estar completas. Este es un ejemplo de un archivo .csv con la primera fila que falta en la última columna y la segunda fila completamente completa:
2012: 07: 25,11: 48: 20,922, "uLog.exe", "", tecla presionada, 1246,341, -1.00, -1.00,1.00, cambio 2012: 07: 25,11: 48: 21,094, " uLog.exe "," ", tecla presionada, 1246,341, -1.00, -1.00,1.00, b, Shift
Desde mi entendimiento de laSuper CSV Javadoc, no hay manera de poblar un Java Bean con elCsvBeanReader Si hay un número variable de columnas. Esto parece realmente tonto porque siento que estas columnas faltantes deberían ser nulas o algún otro valor predeterminado cuando se inicializa el Bean.
Para referencia, aquí está mi código completo para el analizador:
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();
}
}
Y el código para la clase 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(){}
}
Y la excepción que recibo (note que esta es una línea diferente a mi ejemplo anterior, faltan las dos últimas columnas):
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)
Sí, escribir a todos esos captadores y colocadores fue un dolor en el culo. Además, pido disculpas, probablemente no tenga una convención perfecta en mi uso de SuperCSV (como qué CellProcessor usar si solo quieres la cadena no modificada), pero entiendes la idea. Además, este código obviamente no está completo. Por ahora, solo estoy tratando de recuperar con éxito una línea de datos.
En este punto, me pregunto si usar CsvBeanReader es posible para mis propósitos. Si no, estoy un poco decepcionado, ya que CsvListReader (publicaría un hipervínculo, pero StackOverflow tampoco me permite, también es tonto) es tan fácil como no usar la API en absoluto, y solo usar Scanner.next ().
Cualquier ayuda sería apreciada. ¡Gracias por adelantado!