2012-06-17 3 views
1

Java имеет LineNumberReader, который позволяет мне отслеживать строку, в которой я состою, но как мне отслеживать положение байта (или символа) в потоке?Как узнать, сколько символов или байтов было прочитано из потока?

Я хочу что-то похожее на lseek(<fd>,0,SEEK_CUR) для файлов в С.

EDIT: Я читаю файл с помощью LineNumberReader in = new LineNumberReader(new FileReader(file)), и я хочу, чтобы иметь возможность напечатать что-то вроде «обработанного XX% файла» каждый сейчас и тогда. Самый простой способ, который я знаю, - сначала посмотреть на file.length() и разделить его текущую позицию.

+0

Какой тип потока вы пытаетесь использовать? Файловый поток живой комм. поток и т. д. ... ??? – trumpetlicks

+0

Я не могу себе представить, почему вы хотели бы знать это и как вы могли бы это понять. Тот факт, что это поток, делает невозможным положение, так как вы постоянно получаете больше. Самое большее, что вы можете сделать, это следить за тем, сколько байтов вы прочитали с момента создания потока через простое целое число и увеличиваете его. Возможно, если вы дадите нам более подробную информацию о том, каковы ваши намерения ... –

+0

Вы можете посмотреть [RandomAccessFile] (http://docs.oracle.com/javase/1.4.2/docs/api/java/io/RandomAccessFile. html), но я не знаю, соответствует ли он потоку, на который вы смотрите. – Thomas

ответ

1

Я предлагаю расширение 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()); 
} 

Вы заметите несколько вещей:

  1. Этой версия подсчитывает байты, потому что он реализует InputStream.
  2. Возможно, проще всего подсчитать символы или байты в клиентском коде.
  3. Этот код будет считать байты, как только они будут считаны из файловой системы в буфер, даже если они не были обработаны LineNumberReader. Вы могли бы поместить символы подсчета в подкласс LineNumberReader, чтобы обойти это. К сожалению, вы не можете легко получить процент, потому что, в отличие от байтов, нет дешевого способа узнать количество символов в файле.
+1

Я считаю, что Apache Commons IO имеет счетчик потока входного потока. http://commons.apache.org/io/api-1.4/org/apache/commons/io/input/CountingInputStream.html –

Смежные вопросы