我的文本文件布局如下。
Product Name
HP Compaq Elite 8300 CMT
(HP Compaq Elite 8300 CMT在它自己的产品线上,前面有一个标签空间)
我正在尝试逐行读取并删除以制表符开头的行。首先,我将文件转换为字符串列表:
public static List<String> readFile2(File file) throws IOException {
FileInputStream fis = new FileInputStream(file);
List<String> list = new ArrayList<>();
//Construct BufferedReader from InputStreamReader
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
String line = null;
while ((line = br.readLine()) != null) {
list.add(br.readLine());
}
br.close();
return list;
}
我在阅读列表时在循环中尝试了许多不同的语句但是没有返回正确的行:
for(int i=0; i<list.size(); i++)
{
if(list.get(i).indexOf("\u0009")>-1 || list.get(i).contains("\u0009") || list.get(i).indexOf((char)9)>-1 || list.get(i).startsWith(" ") || list.get(i).startsWith("\t"))
{
list.remove(i);
}
}
有什么建议吗?谢谢!
答案 0 :(得分:0)
Java的String
class has a startsWith
方法,允许您测试String是否以给定的前缀开头。您可以使用它来标识以制表符开头的行。通过使用它,您可以测试刚从缓冲区中读取的行,而不是首先将它添加到列表中。
String line = null;
while ((line = br.readLine()) != null) {
if(!line.startsWith("\u0009")) {
list.add(line);
}
}
答案 1 :(得分:0)
其他答案建议(更好的 1 )替代方法,避免首先将匹配的行放入列表中。
以下解释了您的版本无法运作的原因:
for (int i = 0; i < list.size(); i++) {
if (/* match line */) {
list.remove(i);
}
}
问题是当你删除第i个list元素时,较大索引的所有元素都会被重新编号&#34 ;;例如list.get(i + 1)
变为list.get(i)
,依此类推。
但接下来你要做的就是增加i
。所以...实际上...当你删除一个元素时,下一个元素不会被检查。
这是一种正确的方法:
int i = 0;
while (i < list.size()) {
if (/* match line */) {
list.remove(i);
} else {
i++;
}
}
请注意,如果您删除了i
元素,则不会增加i
。
对于记录,您使用的任何一个测试都足以匹配包含TAB的行。以相同的方式编写相同的测试并没有多大帮助。对你来说有一个教训......
1 - 它更简单(代码更少),并且在处理大文件时也显着提高效率。从ArrayList
中的任意位置删除元素是O(N)
操作。