- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
所以我正在解析 .csv 文件。我接受了 StackOverflow 上某个地方的另一个线程的建议并下载了 SuperCSV。我终于让几乎所有的东西都能正常工作,但现在我遇到了一个似乎很难修复的错误。
出现此问题是因为最后两列数据可能已填充也可能未填充。这是一个 .csv 文件的示例,其中第一行缺少最后一列,第二行完全完整:
2012:07:25,11:48:20,922,"uLog.exe","",Key pressed,1246,341,-1.00,-1.00,1.00,Shift 2012:07:25,11:48:21,094,"uLog.exe","",Key pressed,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(){}
}
我收到的异常(请注意,这行与我上面的示例不同,缺少最后两列):
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)
是的,编写所有这些 getter 和 setter 是一件很痛苦的事情。另外,我很抱歉,我在使用 SuperCSV 时可能没有完美的约定(例如,如果您只想要未修改的字符串,则使用什么 CellProcessor),但您明白了。另外,这段代码显然不完整。现在,我只是想成功地检索一行数据。
此时,我想知道是否可以使用 CsvBeanReader 来实现我的目的。如果没有,我有点失望,因为 CsvListReader(我会发布超链接,但 StackOverflow 也不允许我这样做,也是愚蠢的)就像根本不使用 API 一样简单,只使用 Scanner.next ().
如有任何帮助,我们将不胜感激。提前致谢!
最佳答案
编辑:更新 Super CSV 2.0.0-beta-1
请注意 Super CSV 2.0.0-beta-1 中的 API 已更改(代码示例基于 1.52)。所有读取器上的 getCSVHeader()
方法现在是 getHeader()
(与写入器上的 writeHeader
保持一致)。
此外,SuperCSVException
已重命名为 SuperCsvException
。
编辑: Super CSV 2.1.0 更新
从版本 2.1.0 开始,可以通过使用新的 executeProcessors()
方法在读取一行 CSV 后 执行单元处理器。有关详细信息,请参阅 this example在项目网站上。请注意,这仅与 CsvListReader
相关,因为它是唯一允许可变列长度的阅读器。
您是对的 - CsvBeanReader
不支持列数可变的 CSV 文件。根据大多数 CSV 规范(包括 RFC 4180 ),每一行的列数必须相同。
出于这个原因(作为 Super CSV 开发人员)我不愿意将此功能添加到 Super CSV。如果您能想到一种优雅的方式来添加它,那么请随时在该项目的 SourceForge 站点上提出建议。这可能意味着一个新的阅读器扩展了 CsvBeanReader
:它必须将阅读和映射/处理分成两个单独的方法(你不能对 bean 的字段进行任何处理或映射,除非你知道有多少列)。
对此的简单解决方案(如果您可以控制正在使用的 CSV 文件)是在编写 CSV 文件时简单地添加一个空白列(示例中的第一行末尾有一个逗号 -以指示最后一列为空)。这样,您的 CSV 文件将是有效的(它将在每一行上具有相同数量的列)并且您可以像您已经在做的那样使用 CsvBeanReader
。
如果那不可能,那么一切都不会丢失!
您可能已经意识到,CsvBeanReader
使用名称映射将 CSV 文件中的每一列与 bean 中的一个字段相关联,并使用 CellProcessor 数组来处理每一列。换句话说,如果你想使用它,你必须知道有多少列(以及它们代表什么)。
CsvListReader
另一方面,它非常原始,可以读取不同长度的行(因为它不需要处理或映射它们)。
因此,您可以将 CsvBeanReader
的所有功能与 CsvListReader
结合起来(如以下示例中所示),方法是使用两个读取器并行读取文件:使用 CsvListReader
计算出有多少列,CsvBeanReader
进行处理/映射。
请注意,这假设只有 birthDate 列可能不存在(即,如果您无法判断缺少哪一列,它就不会起作用)。
package example;
import java.io.StringReader;
import java.util.Date;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.exception.SuperCSVException;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.CsvListReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.io.ICsvListReader;
import org.supercsv.prefs.CsvPreference;
public class VariableColumns {
private static final String INPUT = "name,birthDate,city\n"
+ "John,New York\n"
+ "Sally,22/03/1974,London\n"
+ "Jim,Sydney";
// cell processors
private static final CellProcessor[] NORMAL_PROCESSORS =
new CellProcessor[] {null, new ParseDate("dd/MM/yyyy"), null };
private static final CellProcessor[] NO_BIRTHDATE_PROCESSORS =
new CellProcessor[] {null, null };
// name mappings
private static final String[] NORMAL_HEADER =
new String[] { "name", "birthDate", "city" };
private static final String[] NO_BIRTHDATE_HEADER =
new String[] { "name", "city" };
public static void main(String[] args) {
// using bean reader and list reader together (to read the same file)
final ICsvBeanReader beanReader = new CsvBeanReader(new StringReader(
INPUT), CsvPreference.STANDARD_PREFERENCE);
final ICsvListReader listReader = new CsvListReader(new StringReader(
INPUT), CsvPreference.STANDARD_PREFERENCE);
try {
// skip over header
beanReader.getCSVHeader(true);
listReader.getCSVHeader(true);
while (listReader.read() != null) {
final String[] nameMapping;
final CellProcessor[] processors;
if (listReader.length() == NORMAL_HEADER.length) {
// all columns present - use normal header/processors
nameMapping = NORMAL_HEADER;
processors = NORMAL_PROCESSORS;
} else if (listReader.length() == NO_BIRTHDATE_HEADER.length) {
// one less column - birth date must be missing
nameMapping = NO_BIRTHDATE_HEADER;
processors = NO_BIRTHDATE_PROCESSORS;
} else {
throw new SuperCSVException(
"unexpected number of columns: "
+ listReader.length());
}
// can now use CsvBeanReader safely
// (we know how many columns there are)
Person person = beanReader.read(Person.class, nameMapping,
processors);
System.out.println(String.format(
"Person: name=%s, birthDate=%s, city=%s",
person.getName(), person.getBirthDate(),
person.getCity()));
}
} catch (Exception e) {
// handle exceptions here
e.printStackTrace();
} finally {
// close readers here
}
}
public static class Person {
private String name;
private Date birthDate;
private String city;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
}
希望对您有所帮助。
哦,还有什么原因导致您的 Entry
类中的字段不遵循正常的命名约定 (camelCase)?如果您更新 header
数组以使用驼峰式大小写,那么您的字段也可以是驼峰式大小写。
关于java - 使用 CsvBeanReader 读取列数可变的 CSV 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11678238/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!