0

以下のように連結されたファイル内に一連のオブジェクトが格納されています。

sizeOfFile1 || file1 || sizeOfFile2 || file2 ...

ファイルのサイズはシリアル化された長いオブジェクトであり、ファイルはファイルの生のバイトです。

入力ファイルからファイルを抽出しようとしています。以下は私のコードです:

FileInputStream fileInputStream = new FileInputStream("C:\Test.tst");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
while (fileInputStream.available() > 0)
{
  long size = (long) objectInputStream.readObject();
  FileOutputStream fileOutputStream = new FileOutputStream("C:\" + size + ".tst");
  BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
  int chunkSize = 256;
  final byte[] temp = new byte[chunkSize];
  int finalChunkSize = (int) (size % chunkSize);
  final byte[] finalTemp = new byte[finalChunkSize];
  while(fileInputStream.available() > 0 && size > 0)
  {
    if (fileInputStream.available() > finalChunkSize)
    {
      int i = fileInputStream.read(temp);
      secBufferedOutputStream.write(temp, 0, i);
      size = size - i;
    }
    else
    {
      int i = fileInputStream.read(finalTemp);
      secBufferedOutputStream.write(finalTemp, 0, i);
      size = 0;
    }
  }
  bufferedOutputStream.close();
}
fileOutputStream.close();

私のコードは、最初の sizeOfFile を読み取った後に失敗します。複数のファイルが保存されている場合、残りの入力ファイルを 1 つのファイルに読み込むだけです。

誰でもここで問題を見ることができますか?

よろしく。

4

4 に答える 4

0

代わりにNIOを試すことができます...

FileChannel roChannel = new RandomAccessFile(file, "r").getChannel();
ByteBuffer roBuf = roChannel.map(FileChannel.MapMode.READ_ONLY, 0, SIZE);

これにより、ファイルから SIZE バイトだけが読み取られます。

B

于 2013-12-21T00:17:31.600 に答える
0

This is using DataInput to read longs. In this particular case I am not using readFully() as a segment might be too long to keep it in memory:

DataInputStream in = new DataInputStream(FileInputStream());
byte[] buf = new byte[64*1024];
while(true) {
  OutputStream out = ...;
  long size;
  try { size = in.readLong(); } catch (EOFException e) { break; } 
  while(size > 0) {
    int len = (size > buf.length)?buf.length:size;
    len = in.read(buf, 0, len);
    out.write(buf, 0, len);
    size-=len;
  }
  out.close();
}
于 2014-10-09T00:38:59.503 に答える
-1

次のいずれかを実行することで、多くの問題を回避できます。

  1. Avro を使用するように切り替えてください。そうしないと頭がおかしいと思います。習得が容易で、スキーマの変更に対応します。ObjectXXXStream を使用することは、これまでで最悪のアイデアの 1 つです。スキーマを変更するとすぐに、古いファイルがゴミになります。
  2. またはThriftを使用する
  3. またはHibernateを使用します(ただし、これはおそらく優れたオプションではありません。Hibernateは学習に多くの時間を要し、多くの構成が必要です)

avro への切り替えを本当に拒否する場合は、apache の IOUtils クラスを読むことをお勧めします。ある入力ストリームから別の入力ストリームにコピーする方法があり、頭痛の種を大幅に節約できます。残念ながら、やりたいことはもう少し複雑です。各ファイルのプレフィックスとしてサイズが必要です。これを行うには、SequenceInputStream オブジェクトの組み合わせを使用できる場合があります。

GzipOutputStream と ZipOutputStream もありますが、クラスパスに他の jar も追加する必要があると思います。

正直なところ、avroまたはthriftを学んでそれを使用する必要があると思うので、例を書くつもりはありません.

于 2013-12-21T00:35:35.493 に答える