Java 如何确定从流中读取了多少字符或字节?

Java 如何确定从流中读取了多少字符或字节?,java,io,Java,Io,Java有LineNumberReader,它让我可以跟踪我所在的行,但是如何跟踪流中的字节(或字符)位置呢 对于C语言中的文件,我需要类似于lseek(,0,SEEK\u CUR)的东西 编辑: 我正在使用LineNumberReader in=new LineNumberReader(new FileReader(file))读取一个文件,我希望能够不时打印类似“已处理文件的XX%”的内容。我知道的最简单的方法是首先查看file.length()并将当前文件位置除以它。我建议按如下方式扩展F

Java有
LineNumberReader
,它让我可以跟踪我所在的行,但是如何跟踪流中的字节(或字符)位置呢

对于C语言中的文件,我需要类似于
lseek(,0,SEEK\u CUR)
的东西

编辑:
我正在使用
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());
}
您会注意到以下几点:

  • 此版本统计字节数,因为它实现了InputStream
  • 在客户端代码中自己计算字符或字节可能更容易
  • 当字节从文件系统读入缓冲区时,即使LineNumberReader尚未对其进行处理,此代码也会对字节进行计数。您可以将计数字符放在LineNumberReader的子类中,以避免此问题。不幸的是,您无法轻松地生成百分比,因为与字节不同,没有廉价的方法可以知道文件中的字符数

  • 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定义的许多方法,这些方法与我的目的无关。

    您尝试使用哪种类型的流?一个文件流,一个实时通信流,等等…??我无法想象你为什么想知道,也无法想象你是如何真正弄明白的。事实上,这是一个流,使它不可能有一个职位,因为你不断收到更多。您所能做的最多就是跟踪自通过简单整数建立流并递增流以来读取的字节数。也许如果你给我们更多关于你的意图的细节…你可以研究一下,但我不知道它是否适合你所看到的流。我能用RandomAccessFile制作一个LineNumberReader吗?我相信Apache Commons IO有一个计数输入流装饰器。