9

ファイル読み取りの質問に対する私の回答に応えて、コメント投稿者FileInputStream.read(byte[])は「バッファをいっぱいにすることは保証されていません」と述べました。

File file = /* ... */  
long len = file.length();
byte[] buffer = new byte[(int)len];
FileInputStream in = new FileInputStream(file);
in.read(buffer);

(コードは、ファイルの長さが2GBを超えないことを前提としています)

とは別に、メソッドがファイルの内容全体を取得しないIOException原因は何ですか?read

編集:

コードのアイデア(および私が答えた質問のOPの目標)は、ファイル全体を1回の急降下でメモリのチャンクに読み込むことです。そのため、buffer_size = file_sizeです。

4

6 に答える 6

6

IOExceptionとは別に、readメソッドがファイルの内容全体を取得しない原因は何でしょうか。

私自身のAPI実装では、そして私のホームロールファイルシステムでは、単にバッファの半分を埋めることを選択します......冗談です。

私のポイントは、冗談でなくても、技術的に言えばバグではないということです。メソッド契約の問題です。この場合の契約(文書)は次のとおりです。

この入力ストリームから最大 b.lengthバイトのデータをバイトの配列に読み取ります。

つまり、バッファがいっぱいになる保証はありません。

APIの実装によっては、おそらくファイルシステムによっては、readメソッドがバッファをいっぱいにしないことを選択する場合があります。それは基本的にメソッドのコントラクトが何を言っているかという問題です。


結論:おそらく機能しますが、機能することが保証されているわけではありません。

于 2011-05-25T13:07:04.880 に答える
6

readメソッドがファイルの内容全体を取得しない原因は何ですか?

たとえば、ファイルがファイルシステム上でフラグメント化されており、低レベルの実装が、HDが次のフラグメントをシークするのを待機する必要があることを認識している場合(これは、CPU操作に比べてかなりの時間がかかります)。read()バッファの一部を埋めずに呼び出しを返すことは、アプリケーションが受信したデータですでに何かを実行する機会を与えるために意味があります。

実装が実際にそのように機能するかどうかはわかりませんが、要点は、APIコントラクトによって保証されていないため、バッファがいっぱいになることに依存してはならないということです。

于 2011-05-25T13:18:06.853 に答える
3

まず第一に、あなたは自分自身を誤った二分法にしています。完全に正常な状況の 1 つは、ファイル内にそれほど多くのバイトが残っていないため、バッファーがいっぱいにならないことです。これは ではありIOExceptionませんが、ファイルの内容全体が読み取られていないという意味ではありません。

仕様によると、メソッドはストリームの終わりを示す -1 を返すか、少なくとも 1 バイトが読み取られるまでブロックします。の実装InputStream者は、必要に応じて最適化できます (たとえば、TCP ストリームは、呼び出し側のバッファ サイズの選択に関係なく、パケットが着信するとすぐにデータを返す場合があります)。AFileInputStreamは、1 ブロック分のデータでバッファーを埋める場合があります。呼び出し元として、メソッドが を返すまで-1読み続ける必要があること以外は何もわかりません。

編集

実際には、あなたの例では、(標準的な実装で) バッファーが満たされない唯一の状況は、バッファーを割り当てた後、読み取りを開始する前にファイルのサイズが変更された場合です。ファイルをロックダウンしていないため、これは可能性です。

于 2011-05-25T13:04:24.433 に答える
2

人々は a での読み取りについて、仮説的にはバッファーを満たさないものFileInputStreamとして話してきました。実際、いくつかの状況では現実です。

  • 「/dev/tty」または名前付きパイプで FileInputStream を開くと、read現在利用可能なデータのみが返されます。他のデバイス ファイル同じように動作する場合があります。(ただし、これらのファイルはおそらく0Lファイル サイズとして返されます。)

  • FUSEファイル システムは、ファイル システムがオプションでマウントされている場合、またはファイルが対応するフラグで開かれている場合、読み取りバッファーを完全に満たさないように実装できますdirect_io

上記は Linux に適用されますが、他のオペレーティング システムや Java 実装にも同様のケースが存在する可能性があります。肝心なのは、javadocs ではこの動作が許可されており、アプリケーションがそれが発生しないと想定している場合、問題が発生する可能性があるということです。

「完全に読み取る」動作を実装するサードパーティのライブラリがあります。たとえば、Apache commons はFileUtils.readFileToByteArrayまたはIOUtils.toByteArray類似のメソッドを提供します。その動作が必要な場合は、これらのライブラリのいずれかを使用するか、自分で実装する必要があります。

于 2011-05-25T13:44:23.373 に答える
1

バッファをいっぱいにすることは保証されていません。

ファイルサイズがバッファよりも小さい場合や、ファイルの残りの部分がバッファよりも小さい場合があります。

于 2011-05-25T13:06:20.920 に答える
0

あなたの質問は自己矛盾しています。バッファ全体を読み取るという保証はありません。たとえそうしないと考えられる状況がなくてもです。保証はありませんので、ご安心ください。

于 2011-05-26T00:01:00.153 に答える