所以我正在解析一个 .csv 文件。我在 StackOverflow 的某个地方听取了另一个线程的建议并下载了 SuperCSV。我终于得到了几乎所有的工作,但现在我遇到了一个似乎很难修复的错误。
出现此问题的原因是最后两列数据可能已填充,也可能未填充。这是一个 .csv 文件的示例,其中第一行缺少最后一列,第二行完全完整:
2012:07:25,11:48:20,922,"uLog.exe","",按键,1246,341,-1.00,-1.00,1.00,Shift 2012:07:25,11:48:21,094," uLog.exe","",按键,1246,341,-1.00,-1.00,1.00,b,Shift
根据我对Super CSV Javadoc的理解,如果列数可变,则无法使用CsvBeanReader填充 Java Bean 。这看起来真的很愚蠢,因为我觉得在初始化 Bean 时应该允许这些缺失的列为 null 或其他一些默认值。
作为参考,这是我的解析器的完整代码:
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();
}
}
以及 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(){}
}
我收到的异常(请注意,这与我上面的示例不同,缺少最后两列):
线程“主”中的异常值数组(大小 12)必须与处理器数组(大小 13)匹配:您可能正在读取列数与指定的单元处理器数不同的 CSV 行上下文:行:2 列:0生线: [2012:07:25, 11:48:05, 740, uLog.exe, , 开始记录, -1, -1, -1.00, -1.00, -1.00, ] 违规处理器:null 在 org.supercsv.util.Util.processStringList(未知来源) 在 org.supercsv.io.CsvBeanReader.read(未知来源) 在处理.ULogParser.parse(ULogParser.java:59) 在 ui.ParseImplicitData.main(ParseImplicitData.java:15)
是的,编写所有这些 getter 和 setter 是一件很痛苦的事情。另外,我很抱歉,我在使用 SuperCSV 时可能没有完美的约定(例如,如果您只想要未修改的字符串,则使用 CellProcessor),但您明白了。另外,这段代码显然不完整。现在,我只是想成功检索一行数据。
在这一点上,我想知道使用 CsvBeanReader 是否可以用于我的目的。如果不是,我有点失望,因为 CsvListReader(我会发布超链接,但 StackOverflow 也不允许我,也很愚蠢)就像根本不使用 API 一样简单,只使用 Scanner.next ()。
任何帮助,将不胜感激。提前致谢!