Как получить прогресс больших файлов с помощью XMLStreamReader

Я использую приведенный ниже код для чтения большого XML-файла (в ГБ) в Hadoop RecordReader с использованием XMLStreamReader.

public class RecordReader {
   int progressCouunt = 0;
   public RecordReader() {
    XMLInputFactory factory = XMLInputFactory.newInstance();
    FSDataInputStream fdDataInputStream = fs.open(file); //hdfs file
    try {
          reader = factory.createXMLStreamReader(fdDataInputStream);
    } catch (XMLStreamException exception) {
           throw new RuntimeException("XMLStreamException exception : ", exception);
    }
   }
   @Override
  public float getProgress() throws IOException, InterruptedException {
     return progressCouunt; 
   }
}

Мой вопрос заключается в том, как получить ход чтения файла с помощью XMLStreamReader, поскольку он не предоставляет никакой начальной или конечной позиции для расчета процента выполнения. Я сослался на Как сделать Я отслеживаю ход обработки больших файлов в StAX?, но не могу использовать filterReader. Пожалуйста, помогите мне здесь.


person Bhushan Kawadkar    schedule 10.06.2016    source источник
comment
Вы знаете полную длину потока?   -  person biziclop    schedule 10.06.2016
comment
нет, со stax это невозможно, так как он использует потоковую передачу по запросу, поэтому не может получить весь размер файла.   -  person Bhushan Kawadkar    schedule 10.06.2016
comment
Я имею в виду, откуда-то еще. Потому что, если у вас нет возможности определить общую длину ваших данных до начала их потоковой передачи, вы не сможете отслеживать прогресс.   -  person biziclop    schedule 10.06.2016


Ответы (1)


Вы можете обернуть InputStream, расширив FilterInputStream.

public interface InputStreamListener {
    void onBytesRead(long totalBytes);
}

public class PublishingInputStream extends FilterInputStream {
    private final InputStreamListener;
    private long totalBytes = 0;

    public PublishingInputStream(InputStream in, InputStreamListener listener) {
       super(in);
       this.listener = listener;
    }

    @Override
    public int read(byte[] b) {
       int count = super.read(b);
       this.totalBytes += count;
       this.listener.onBytesRead(totalBytes);
    }

    // TODO: override the other read() methods
}

Применение

XMLInputFactory factory = XMLInputFactory.newInstance();
InputStream in = fs.open(file);
final long fileSize = someHadoopService.getFileLength(file);
InputStremListener listener = new InputStreamListener() {
    public void onBytesRead(long totalBytes) {
        System.out.println(String.format("Read %s of %s bytes", totalBytes, fileSize));
    }
};
InputStream publishingIn = new PublishingInputStream(in, listener);
try {
    reader = factory.createXMLStreamReader(publishingIn);
    // etc
person lance-java    schedule 10.06.2016
comment
на самом деле я использую org.apache.hadoop.mapreduce.RecordReader и мне нужно читать прогресс внутри него. Не могли бы вы помочь мне здесь. - person Bhushan Kawadkar; 10.06.2016
comment
Итак, обновите прогресс в кастомном InputStreamListener . Чтобы получить процент, вам нужно знать общее количество байтов. InputStream.available() НЕ гарантирует возврат общего количества байтов (он возвращает общее число, которое можно прочитать без блокировки). Но вы можете обнаружить, что этот метод работает (в зависимости от реализации InputStream) - person lance-java; 10.06.2016
comment
Я пытался использовать метод .available(), но здесь общее количество прочитанных байтов и доступных байтов всегда одинаковы. - person Bhushan Kawadkar; 13.06.2016