8

Javaのドキュメントによると、Class InputStreamサーバーのmarkメソッドのreadlimitパラメータに「マーク位置が無効になるまでに読み取れる最大バイト数」を設定するようです。. 内容が「hello」のsample.txtという名前のファイルがあります。そして、私はこのコードを書きました:

import java.io.*;
public class InputStream{
 public static void main (String[] args) throws IOException {
  InputStream reader = new FileInputStream("sample.txt");
  BufferedInputStream bis = new BufferedInputStream(reader);
  bis.mark(1);
  bis.read();
  bis.read();
  bis.read();
  bis.read();
  bis.reset();
  System.out.println((char)bis.read());
 }
}

出力は「h」です。しかし、markメソッドの後に複数のバイトを読み取った場合、無効なリセットメソッド呼び出しのエラーが発生するのではないでしょうか?

4

4 に答える 4

5

私はこれをドキュメンテーションエラーに置きます。

非パラメータドキュメントBufferedInputStreamは、「InputStream のマークメソッドの一般的な契約を参照してください」です。これはBufferedInputStream、パラメータドキュメントにもかかわらず、異なる動作をしないことを示しています。

で指定される一般契約はInputStream

readlimit 引数は、この入力ストリームに、マーク位置が無効になる前に多くのバイトを読み取ることを許可するように指示します [...] readlimit を超えるバイトがストリームから読み取られる場合、ストリームはデータをまったく記憶する必要はありません

言い換えれば、readlimit提案です。ストリームは、約束を守らず、過剰に配信することは自由です。

于 2012-09-05T21:04:01.777 に答える
3

source 、特に fill() メソッドを見ると、(しばらくしてから!) 絶対に必要な場合にのみマークを無効にすることがわかります。つまり、ドキュメントが示唆するよりも寛容です。

...
else if (pos >= buffer.length)  /* no room left in buffer */
   if (markpos > 0) {  /* can throw away early part of the buffer */
     int sz = pos - markpos;
     System.arraycopy(buffer, markpos, buffer, 0, sz);
     pos = sz;
     markpos = 0;
   } else if (buffer.length >= marklimit) {
     markpos = -1;   /* buffer got too big, invalidate mark */
     pos = 0;        /* drop buffer contents */
     ....

デフォルトのバッファー サイズは比較的大きい (8K) ため、この例では無効化はトリガーされません。

于 2012-09-05T20:58:09.873 に答える
1

の実装を見ると、 (保護されたフィールドの)BufferedInputStreamJavaDocs内のマーカー位置の重要性が説明されています。markpos

[ markposis]最後のメソッドが呼び出さposれたときのフィールドの値。mark

この値は常にからまでの範囲にあり-1ますpos。入力ストリームにマークされた位置がない場合、このフィールドは-1です。入力ストリームにマークされた位置がある場合、は操作buf[markpos]後に入力として提供される最初のバイトresetです。markposでない場合、位置から-1のすべてのバイトはバッファ配列に残っている必要があります(ただし、、、、およびの値を適切に調整して、バッファ配列内の別の場所に移動できます)。との差が。を超えない限り、それらを破棄することはできません。buf[markpos]buf[pos-1]countposmarkposposmarkposmarklimit

お役に立てれば。の定義とクラスのプライベートメソッドを覗いて、readすべてresetfillどのように結びついているかを確認してください。

つまり、クラスがバッファを埋めるためにさらにデータを取得する場合にのみ、マークの位置が考慮されます。mark許可された呼び出しよりも多くのバイトが読み取られた場合、正しく無効になります。その結果、への呼び出しreadは、パブリックJavaDocコメントでアドバタイズされた動作を必ずしもトリガーしません。

于 2012-09-05T20:45:34.150 に答える
1

これは微妙なバグのように見えます。バッファサイズを減らすと、IOException

public static void main(String[] args) throws IOException {
    InputStream reader = new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5, 6, 7, 8});
    BufferedInputStream bis = new BufferedInputStream(reader, 3);
    bis.mark(1);
    bis.read();
    bis.read();
    bis.read();
    bis.read();
    bis.reset();
    System.out.println((char)bis.read());
}
于 2012-09-05T20:57:34.777 に答える