0

これはキスの瞬間かもしれませんが、とにかく尋ねるべきだと思います。

スレッドがあり、ソケットの InputStream から読み取っています。特に小さいデータ サイズを扱っているため (受信できるデータが 100 ~ 200 バイトのオーダーであるため)、バッファー配列のサイズを 256 に設定しました。読み取り関数の一部として、 InputStream から読み取ったときに、すべてのデータを取得したことを確認します。そうでない場合は、読み取り関数を再帰的に呼び出します。再帰呼び出しごとに、2 つのバッファー配列をマージして元に戻します。

私の問題は、256 を超えるバッファーを使用することは決して予想していませんが、安全を確保したいということです。しかし、ヒツジが飛び始め、バッファーが読み取りよりも大幅に多い場合、関数は (推定により) 完了するまでに指数関数的な曲線を取り始めます。

読み取り機能やバッファ マージの効率を上げるにはどうすればよいですか?

これがそのままの read 関数です。

int BUFFER_AMOUNT = 256;

private int read(byte[] buffer) throws IOException {
   int bytes = mInStream.read(buffer); // Read the input stream

   if (bytes == -1) { // If bytes == -1 then we didn't get all of the data

        byte[] newBuffer = new byte[BUFFER_AMOUNT]; // Try to get the rest
        int newBytes;
        newBytes = read(newBuffer); // Recurse until we have all the data

        byte[] oldBuffer = new byte[bytes + newBytes]; // make the final array size

        // Merge buffer into the begining of old buffer.
        // We do this so that once the method finishes, we can just add the 
        // modified buffer to a queue later in the class for processing.
        for (int i = 0; i < bytes; i++) 
            oldBuffer[i] = buffer[i];

        for (int i = bytes; i < bytes + newBytes; i++) // Merge newBuffer into the latter half of old Buffer
            oldBuffer[i] = newBuffer[i];
        // Used for the recursion

        buffer = oldBuffer; // And now we set buffer to the new buffer full of all the data.
        return bytes + newBytes;
    }
    return bytes;
}

編集:私は(不当に)妄想的であり、バッファを2048に設定して完了と呼ぶべきですか?

4

3 に答える 3

2

BufferedInputStream、Rolandが指摘したように、およびDataInputStream.readFully()、すべてのループコードを置き換えます。

于 2011-06-30T23:41:11.873 に答える
0

「小さなデータサイズ」の意味がわかりません。時間がカーネル モード (readソケットで直接発行する s が多すぎる) で費やされているか、ユーザー モード (アルゴリズムが複雑すぎる) で費やされているかを測定する必要があります。

前者の場合、入力をBufferedInputStream4096 バイトのバッファでラップし、そこから読み取るだけです。

後者の場合は、次のコードを使用してください。

/**
  * Reads as much as possible from the stream.
  * @return The number of bytes read into the buffer, or -1
  *         if nothing has been read because the end of file has been reached.
  */
static int readGreedily(InputStream is, byte[] buf, int start, int len) {
  int nread;
  int ptr = start; // index at which the data is put into the buffer
  int rest = len; // number of bytes that we still want to read

  while ((nread = is.read(buf, ptr, rest)) > 0) {
    ptr += nread;
    rest -= nread;
  }

  int totalRead = len - rest;
  return (nread == -1 && totalRead == 0) ? -1 : totalRead;
}

このコードは、新しいオブジェクトの作成、不要なメソッドの呼び出しを完全に回避し、さらに --- 簡単です。

于 2011-06-30T21:15:35.777 に答える
0
int BUFFER_AMOUNT = 256;

実行時に変更したくない場合は、最終的なものにする必要があります。

if (bytes == -1) {

する必要があります !=

また、このコードで何を達成しようとしているのかは完全にはわかりません。それに光を当ててもよろしいですか?

于 2011-06-30T21:04:02.650 に答える