4

概要: データをポンピングする ByteBuffer があります。その後、このデータをソケット経由で送信したいと思います。

そこで、次のようなコードを書きました。

    private static void serialize(ByteBuffer buffer, EmployeeData emp, CharsetEncoder encoder)
{
    // id
    buffer.putInt(emp.getId());
    
    CharBuffer nameBuffer = CharBuffer.wrap(emp.getFirstName().toCharArray());
    ByteBuffer nbBuffer = null;
    
    // length of first name
    try
    {
        nbBuffer = encoder.encode(nameBuffer);
    } 
    catch(CharacterCodingException e)
    {
        throw new ArithmeticException();
    }

    System.out.println(String.format("String [%1$s] #bytes = %2$s", emp.getFirstName(), nbBuffer.limit()));
    buffer.putInt(nbBuffer.limit());
    buffer.put(nbBuffer);

    // put lastname
    nameBuffer = CharBuffer.wrap(emp.getLastName().toCharArray());
    nbBuffer = null;
    
    // length of first name
    try
    {
        nbBuffer = encoder.encode(nameBuffer);          
    } 
    catch(CharacterCodingException e)
    {
        throw new ArithmeticException();
    }

    System.out.println(String.format("String [%1$s] #bytes = %2$s", emp.getLastName(), nbBuffer.limit()));
    buffer.putInt(nbBuffer.limit());
    buffer.put(nbBuffer);
    
    // salary
    buffer.putInt(emp.getSalary());
}

呼び出しコードでは、次のことを行います。最初にシリアル化された ByteBuffer を取得し、それをソケットに書き込みます...

            Socket client = new Socket("localhost", 8080);
        
        OutputStream oStream = client.getOutputStream();

        serialize(buffer, emp, encoder);
        
        buffer.rewind();            
        while(buffer.hasRemaining())
        {
            byte temp = buffer.get();
            ++ written;
        }
        
        buffer.rewind();
        System.out.println("#Bytes in output buffer: " + written + " limit = " + buffer.limit() + " pos = " + buffer.position() + " remaining = " + buffer.remaining());
        
        int remaining = buffer.remaining();
        while(remaining > 0)
        {
            oStream.write(buffer.get());
            -- remaining;
        }

buffer.remaining() は、バッファに送り込んだ #bytes と正確に等しくなければならないことを期待しています。ただし、そうではないことがわかりました。常に、バッファーの基になる配列のサイズである 1024 に等しくなります。

これがバッファの作成方法です...

        Charset charset = Charset.forName("UTF-8");
    CharsetDecoder decoder = charset.newDecoder();
    CharsetEncoder encoder = charset.newEncoder();
    byte [] underlyingBuffer = new byte[1024];
    ByteBuffer buffer = ByteBuffer.wrap(underlyingBuffer);
    buffer.order(ByteOrder.LITTLE_ENDIAN);

これは、printステートメントの出力として得られるものです...

文字列 [John] #bytes = 4 文字列 [Smith] #bytes = 5

#出力バッファ内のバイト: 1024 制限 = 1024 pos = 0 残り = 1024

バッファに入れられた正確な #bytes を取得するにはどうすればよいですか?

ありがとう!

4

1 に答える 1

13

バイトをバッファーに入れ終わったら、それを行う必要がflipあります。おそらく、代わりに最初の呼び出しのrewind代わりにこれを行うことができます。

Aは と をjava.nio.Buffer区別capacitylimitます。反転しない場合、制限と容量は初期化に使用した配列の長さと同じになります。

反転すると、制限はエンコードしたデータの最後に設定され、容量は 1024 のままです ByteBuffer#remaining。位置と制限の間のデルタを調べます。

于 2009-11-15T04:37:02.793 に答える