JavaLineNumberReader
可以让我跟踪我所在的行,但是如何跟踪流中的字节(或字符)位置?
我想要类似于lseek(<fd>,0,SEEK_CUR)
C 中的文件的东西。
编辑:我正在阅读一个文件LineNumberReader in = new LineNumberReader(new FileReader(file))
,我希望能够不时打印“已处理 XX% 的文件”之类的内容。我知道的最简单的方法是查看第file.length()
一个并将当前文件位置除以它。
我建议扩展 FilterInputStream 如下
public class ByteCountingInputStream extends FilterInputStream {
private long position = 0;
protected ByteCountingInputStream(InputStream in) {
super(in);
}
public long getPosition() {
return position;
}
@Override
public int read() throws IOException {
int byteRead = super.read();
if (byteRead > 0) {
position++;
}
return byteRead;
}
@Override
public int read(byte[] b) throws IOException {
int bytesRead = super.read(b);
if (bytesRead > 0) {
position += bytesRead;
}
return bytesRead;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
int bytesRead = super.read(b, off, len);
if (bytesRead > 0) {
position += bytesRead;
}
return bytesRead;
}
@Override
public long skip(long n) throws IOException {
long skipped;
skipped = super.skip(n);
position += skipped;
return skipped;
}
@Override
public synchronized void mark(int readlimit) {
return;
}
@Override
public synchronized void reset() throws IOException {
return;
}
@Override
public boolean markSupported() {
return false;
}
}
你会像这样使用它:
File f = new File("filename.txt");
ByteCountingInputStream bcis = new ByteCountingInputStream(new FileInputStream(f));
LineNumberReader lnr = new LineNumberReader(new InputStreamReader(bcis));
int chars = 0;
String line;
while ((line = lnr.readLine()) != null) {
chars += line.length() + 2;
System.out.println("Chars read: " + chars);
System.out.println("Bytes read: " + bcis.getPosition());
}
你会注意到一些事情:
ByteCountingInputStream解决方案有一个缺点,它甚至在LineNumberReader处理输入字节之前就对其进行计数。这不是我的报告所需要的,我想出了一个替代方案。我假设输入文件是 ASCII 文本,带有 Unix 风格的行尾(单个LF字符)。
我已经构建了LineNumberReader的一个子集,它添加了位置报告:
import java.io.*;
public class FileLineNumberReader {
private final LineNumberReader lnr;
private final long length;
private long pos;
public FileLineNumberReader(String path) throws IOException {
lnr = new LineNumberReader(new FileReader(path));
length = new File(path).length();
}
public long getLineNumber() {
return lnr.getLineNumber();
}
public String readLine() throws IOException {
String res = lnr.readLine();
if (res != null) {
pos += res.length() + 1;
}
return res;
}
public long getPercent() {
return 100*pos/length;
}
}
请注意,此类隐藏了许多为封装的LineNumberReader定义的方法,这些方法与我的目的无关。