Как снова прочитать части двоичного файла, если DataInputStream не поддерживает пометку / сброс

#java #file #binary #datainputstream

#java #файл #двоичный #datainputstream

Вопрос:

Мне нужно прочитать раздел структурированного двоичного файла, передав индекс. Однако DataInputStream не поддерживает пометку / сброс. Как я могу достичь того, чего я хочу? Существуют ли какие-либо другие классы, которые позволяют мне легко достичь этого?

 import java.io.*;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.FileInputStream;

class Test {
  public static int getInt(DataInputStream stream, int index) throws IOException {
    int offset = index * 4; // size of int
    stream.reset();
    stream.skip(offset);
    return stream.readInt();
  }

  public static void main(String[] args) {
    String filename = "test.data";
    try {
      DataOutputStream ostream = new DataOutputStream(new FileOutputStream(filename));
      for (int i=0; i<10; i  ) {
        ostream.writeInt(i);
      }
      ostream.close();

      DataInputStream istream = new DataInputStream(new FileInputStream(filename));
      istream.mark(0);
      int i0 = getInt(istream, 0);
      int i3 = getInt(istream, 3);
      int i5 = getInt(istream, 5);
      System.out.printf("i0 = %d, i3 = %d, i5 = %dn", i0, i3, i5);
      istream.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
  

Комментарии:

1. обнаружил, что то, что мне действительно нужно, это RandomAccessFile

2. Похоже, вам не нужна пометка / сброс, поскольку вы читаете данные по порядку. Я бы не стал усложнять ситуацию больше, чем она должна быть.

Ответ №1:

Это не DataInputStream, который не поддерживает пометку / сброс. DataInputStream просто делегирует вызовы для mark / reset базовому потоку (в данном случае FileInputStream). Однако FileInputStream не поддерживает операции пометки / сброса (iirc). Решение этой проблемы заключается в том, чтобы сначала обернуть FileInputStream в BufferedInputStream, прежде чем передавать его в DataInputStream. Это должно позволить использовать требуемые операции. Ie:

 DataInputStream istream = new DataInputStream(new BufferedInputStream(new FileInputStream(filename)));
  

Кроме того, я не совсем уверен, но, насколько я понимаю, вы, возможно, неправильно используете аргумент для mark. Согласно JavaDoc, аргумент означает:

максимальный предел байтов, которые могут быть прочитаны до позиции метки, становится недействительным.

Таким образом, вызов mark с нулевым аргументом не был бы особенно полезен.

Ответ №2:

оберните в BufferedInputStream, он реализует mark

кстати, ваш вызов mark должен выдавать количество байтов, которое вы ожидаете прочитать, пока не произойдет сброс. если вы прочитаете дальше, отметка станет недействительной, и сброс приведет к сбросу

или используйте RandomAccessFile