如何在 Java 中的文本文件中找到制表符行?
How do I find tabbed lines in text file in Java?
我有如下布局的文本文件。
Product Name
HP Compaq Elite 8300 CMT
(HP Compaq Elite 8300 CMT 独占一行,前面有一个标签 space)
我正在尝试找到一种方法来逐行阅读并删除以制表符开头的行。首先,我将文件转换为字符串列表:
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);
}
}
有什么建议吗?谢谢!
Java 的 String
class has a startsWith
方法允许您测试字符串是否以给定前缀开头。您可以使用它来识别以制表符开头的行。通过使用它,您可以测试刚刚从缓冲区中读出的行,而不是将其添加到您的列表中。
String line = null;
while ((line = br.readLine()) != null) {
if(!line.startsWith("\u0009")) {
list.add(line);
}
}
其他答案提出了(更好的1)替代方法,避免首先将匹配的行放入列表中。
这里解释了为什么您的版本不起作用:
for (int i = 0; i < list.size(); i++) {
if (/* match line */) {
list.remove(i);
}
}
问题是,当您删除第 i 个列表元素时,较大索引处的所有元素都会得到 "renumbered";例如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)
操作。
我有如下布局的文本文件。
Product Name
HP Compaq Elite 8300 CMT
(HP Compaq Elite 8300 CMT 独占一行,前面有一个标签 space)
我正在尝试找到一种方法来逐行阅读并删除以制表符开头的行。首先,我将文件转换为字符串列表:
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);
}
}
有什么建议吗?谢谢!
Java 的 String
class has a startsWith
方法允许您测试字符串是否以给定前缀开头。您可以使用它来识别以制表符开头的行。通过使用它,您可以测试刚刚从缓冲区中读出的行,而不是将其添加到您的列表中。
String line = null;
while ((line = br.readLine()) != null) {
if(!line.startsWith("\u0009")) {
list.add(line);
}
}
其他答案提出了(更好的1)替代方法,避免首先将匹配的行放入列表中。
这里解释了为什么您的版本不起作用:
for (int i = 0; i < list.size(); i++) {
if (/* match line */) {
list.remove(i);
}
}
问题是,当您删除第 i 个列表元素时,较大索引处的所有元素都会得到 "renumbered";例如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)
操作。