Java BufferedReader--通过令牌而不是readLine()读取?
有没有办法从BufferedReader读取,直到它到达一个不是换行符或回车符的字符(readLine()就是这样做的)Java BufferedReader--通过令牌而不是readLine()读取?,java,bufferedreader,Java,Bufferedreader,有没有办法从BufferedReader读取,直到它到达一个不是换行符或回车符的字符(readLine()就是这样做的) 我不想读一行然后分开。我想忽略新行和返回车厢,只考虑一个特定的令牌(如Tab),具有BuffelDead阅读器性能。 < P>这不是很优雅,但可能起作用。 将openjdk BufferedReader源代码复制到另一个包中(JVM不会让您的类加载器覆盖任何默认Java类)。你可以从这里得到它-- 创建从该BufferedReader副本扩展的子类,创建构造函数并重写read
我不想读一行然后分开。我想忽略新行和返回车厢,只考虑一个特定的令牌(如Tab),具有BuffelDead阅读器性能。 < P>这不是很优雅,但可能起作用。
import java.io.IOException;
import java.io.Reader;
public class MyBufferedReader extends BufferedReader {
/**
*
* @param in
*/
public MyBufferedReader(Reader in) {
super(in);
}
@Override
String readLine(boolean ignoreLF) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
bufferLoop:
for (;;) {
if (nextChar >= nChars)
fill();
if (nextChar >= nChars) { /* EOF */
if (s != null && s.length() > 0)
return s.toString();
else
return null;
}
boolean eol = false;
char c = 0;
int i;
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\t'))
nextChar++;
skipLF = false;
omitLF = false;
charLoop:
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if (c == '\t') {
eol = true;
break charLoop;
}
}
startChar = nextChar;
nextChar = i;
if (eol) {
String str;
if (s == null) {
str = new String(cb, startChar, i - startChar);
} else {
s.append(cb, startChar, i - startChar);
str = s.toString();
}
nextChar++;
if (c == '\t') {
skipLF = true;
}
return str;
}
if (s == null)
s = new StringBuffer(defaultExpectedLineLength);
s.append(cb, startChar, i - startChar);
}
}
}
}
对于这样的输入
MyBufferedReader my = new MyBufferedReader(new InputStreamReader(Main.class.getResourceAsStream("fileWithTabs.txt")));
String line = null;
while((line = my.readLine())!=null) {
System.out.println(line);
}
my.close();
some string some other string
some third string after a newline some forth
and so on
结果是
some string
some other string
some third string after a newline
some forth
and so on
然而,这看起来是一个非常麻烦的解决方案,所以我真的希望在这里看到其他聪明的答案是的
BufferedReader br = ...
StringBuilder sb = new StringBuilder(ESTIMATED_LENGTH);
int ch;
while ((ch = br.read()) != -1 && ch != '\t') {
sb.append(ch);
}
在最好的情况下,您将获得几乎与BufferedReader.readLine()
一样好的性能。在最坏的情况下,您会执行一到两个额外的字符副本(我认为)。。。这也不算太糟糕,性能达到1
要获得与BufferedReader
一样好的性能,需要对代码BufferedReader
本身进行黑客攻击。。。或者重写它
(扩展BufferedReader
的尝试无效,因为您正在从父类调用private
方法。这是不允许的!如果您要通过更改方法访问来“修复”此问题,那么您也可以只“克隆”BufferedReader
类,并将您的方法添加到其中。当然,您的类不再是java.io.BufferedReader
或其子类。)
1——通过正当理由,考虑大局。如果您正在从某处读取大量数据,那么性能瓶颈可能是I/O或读取令牌后如何处理它们。如果不是这样,那么您可能应该使用1)java.nio/
CharBuffer
,2)自定义I/O堆栈或3)其他编程语言。对于类似的情况,您甚至不应该使用BufferedReader。我会这样使用NIO:
public String[] splitContentsBy(String split, File file){
try{
byte[] bytes = Files.readAllBytes(file);
String contents = new String(bytes);
String[] array = contents.spilt(split);
}catch(IOException e){
e.printStackTrace();
}
}
如果您只想要一个角色,您可以:
char c = '?'; //A question mark, as an example.
String[] parts = splitContentsBy(String.valueOf(c), new File("file.txt");
要忽略新行并返回,只需将readLine参数设置为: 字符串读取行(true);
并实现一个条件来检测选项卡。实际上,步骤1到4显示我正在使用BufferedReader的副本,并且所有私有属性和方法都已更改为受保护(步骤3)您可以将BufferedReader包装在扫描仪中。我同意这可以解决问题,但对于足够大的文本文件来说可能不是一个好主意(例如,服务器日志)