我必须解析具有以下形式的税务计算器的txt文件:
Name: Mary Jane
Age: 23
Status: Married
Receipts:
Id: 1
Place: Restaurant
Money Spent: 20
Id: 2
Place: Mall
Money Spent: 30
所以,到目前为止我所做的是:
public void read(File file) throws FileNotFoundException{
Scanner scanner = new Scanner(file);
String[] tokens = null;
while(scanner.hasNext()){
String line= scanner.nextLine();
tokens = line.split(":");
String lastToken = tokens[tokens.length - 1];
System.out.println(lastToken);
所以,我想只访问这个档案的第二栏(Mary Jane,23岁,已婚)给班级纳税人(姓名,年龄,身份)和收据'信息给Arraylist。
我想把最后一个令牌保存到String数组中,但是我不能这样做,因为我不能将字符串保存到字符串数组中。有人能帮我吗?谢谢。
答案 0 :(得分:1)
最快的方法是,如果您的数据是ASCII并且您不需要字符集转换,那就是使用BufferedInputStream并自己进行所有解析 - 找到行终止符,解析数字。不要使用Reader,或创建字符串,或每行创建任何对象,或使用parseInt。只需使用字节数组并查看字节。这有点麻烦,但是假装你正在编写C代码,它会更快。
还要考虑一下您创建的数据结构的紧凑程度,以及是否可以通过聪明的方式避免在每行创建一个对象。
答案 1 :(得分:0)
你真的需要它尽可能快吗?在这种情况下,创建一些对象并在此过程中进行一些垃圾收集通常很好,以便拥有更多可维护的代码。
我自己使用两个正则表达式(一个用于纳税人,另一个用于收据循环)。
我的代码看起来像:
public class ParsedFile {
private Taxpayer taxpayer;
private List<Receipt> receipts;
// getters and setters etc.
}
public class FileParser {
private static final Pattern TAXPAYER_PATTERN =
// this pattern includes capturing groups in brackets ()
Pattern.compile("Name: (.*?)\\s*Age: (.*?)\\s*Status: (.*?)\\s*Receipts:", Pattern.DOTALL);
public ParsedFile parse(File file) {
BufferedReader reader = new BufferedReader(new FileReader(file)));
String firstChunk = getNextChunk(reader);
Taxpayer taxpayer = parseTaxpayer(firstChunk);
List<Receipt> receipts = new ArrayList<Receipt>();
String chunk;
while ((chunk = getNextChunk(reader)) != null) {
receipts.add(parseReceipt(chunk));
}
return new ParsedFile(taxpayer, receipts);
}
private TaxPayer parseTaxPayer(String chunk) {
Matcher matcher = TAXPAYER_PATTERN.matcher(chunk);
if (!matcher.matches()) {
throw new Exception(chunk + " does not match " + TAXPAYER_PATTERN.pattern());
}
// this is where we use the capturing groups from the regular expression
return new TaxPayer(matcher.group(1), matcher.group(2), ...);
}
private Receipt parseReceipt(String chunk) {
// TODO implement
}
private String getNextChunk(BufferedReader reader) {
// keep reading lines until either a blank line or end of file
// return the chunk as a string
}
}
答案 2 :(得分:0)
首先,您为何需要将时间投入到最快的解决方案中?是因为输入文件很大吗?我也不明白你想如何存储解析结果?考虑新类,其中包含您需要从每个人的文件中提取的所有字段。
几点提示:
- 避免不必要的每行内存分配。代码中的line.split(":")
就是这样的例子。
- 使用缓冲输入。
- 最小化输入/输出操作。
如果这些还不够,请尝试阅读本文http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly