我有一个文本文件,我必须遍历它,并希望将每行的某些元素移动到ArrayList
中。文件的每一行的格式都是:number。字符串编号。十进制由于这两个数字的末尾有一个句号(.(,并且我需要将其作为字符串读取,因此删除了。使用子串,然后转换为基元数据类型(int
或short
(。
文件示例:294.ABC123 66。00
如果我尝试这样做,我会得到一个字符串范围错误:(*temp是一个字符串(
while(fileLine.hasMoreTokens())
{
oneNumber = Integer.valueOf(fileLine.nextToken().substring(0,
fileLine.nextToken().indexOf('.')));
twoString = fileLine.nextToken();
threeNumber = Short.valueOf(fileLine.nextToken().substring(0,
fileLine.nextToken().indexOf('.')));
temp = fileLine.nextToken(); //Handle attributes not required
temp = fileLine.nextToken(); //Handle attributes not required
}
我相信发生这种情况的原因是子字符串参数中的nextToken((混淆了StringTokenizer。所以我这样修复它:
while(fileLine.hasMoreTokens())
{
temp = fileLine.nextToken();
oneNumber = Integer.valueOf(temp.substring(0, temp.indexOf('.')));
twoString = fileLine.nextToken();
temp = fileLine.nextToken();
threeNumber= Short.valueOf(temp.substring(0, temp.indexOf('.')));
temp = fileLine.nextToken();
temp = fileLine.nextToken();
}
虽然这很有效,但感觉有点多余。在保留StringTokenizer
的使用权的同时,有什么东西可以让它更干净吗?
这是.nextToken()
的预期行为:它返回令牌并移动经过当前令牌。当您使用Integer.valueOf(fileLine.nextToken().substring(0, fileLine.nextToken().indexOf('.')))
时,您将调用.nextToken()
两次,这意味着您将处理两个不同的令牌。这与String#substring
的工作方式无关。如果需要对令牌执行其他操作,则需要将其存储在变量中。在应该存储值的情况下,使用BufferedReader#readLine
两次也可能导致完全相同的问题。
nextToken()
是有状态的,调用它会改变事情,所以在一行中使用两次它将消耗两个令牌。
对我来说,你的第二个片段似乎更容易阅读,所以我不确定问题出在哪里。大概你希望你的代码更可读。
一个简单的解决方案是制作辅助方法:
while (fileLine.hasMoreTokens()) {
oneNumber = fetchHeadingNumber(fileLine);
twoString = fileLine.nextToken();
threeNumber = fetchHeadingNumber(fileLine);
fileLine.nextToken(); // no need to assign it.
fileLine.nextToken();
}
使用这种方法:
int fetchHeadingNumber(StringTokenizer t) {
String token = t.nextToken();
return Integer.parseInt(token.substring(0, token.indexOf('.')));
}
你可以更进一步,创建一个代表一行的类,它包含解析它所需的所有代码(我编了名字;你的代码片段不清楚这行代表什么样的东西(:
@lombok.Value class InventoryItem {
int warehouse;
String name;
int shelf;
public static InventoryItem read(StringTokenizer tokenizer) {
int warehouse = num(tokenizer);
String name = tokenizer.nextToken();
int shelf = num(tokenizer);
tokenizer.nextToken();
tokenizer.nextToken();
return new InventoryItem(warehouse, name, shelf);
}
private static int num(StringTokenizer t) {
String token = t.nextToken();
return Integer.parseInt(token.substring(0, token.indexOf('.')));
}
}
然后读取一行并检索,比如说,它存储的位置要好得多:现在东西实际上有了名字!
InventoryItem item = InventoryItem.read(fileLine);
System.out.println("This item is in warehouse " + item.getWarehouse());
注意:使用lombok的@Value来避免在这个答案中加入很多样板。