遇到一個比較有意思的NIO問題!

關於NIO的ByteBuffer操作很多人都會,但有時候稍不注意就會犯錯。比如:

private void doWrite(SocketChannel sc, String response) throws IOException {
        if (response != null && response.trim().length() > 0) {
            ByteBuffer buf = ByteBuffer.wrap(response.getBytes());
            buf.flip();
            sc.write(buf);
        }
    }

private void doWrite(SocketChannel channel, String response) throws IOException {
        if (response != null && response.trim().length() > 0) {
            byte[] bytes = response.getBytes();
            ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
            writeBuffer.put(bytes);
            writeBuffer.flip();
            channel.write(writeBuffer);
        }
    }

不仔細想,兩個方法的效果看起來是一樣的,而且上面一個更簡單。
可是在運行時,會發現上面的實現卻寫不出來數據。
原因就出在ByteBuffer.flip()和ByteBuffer.wrap()連用了。
仔細讀註釋會發現:
wrap()方法
新的緩衝區將由給定的字節數組支持;也就是說,對緩衝區的修改會導致數組被修改,反之亦然。新的緩衝區的capacity和limit將是數組長度,它的position是0,它的mark將沒有定義。它的支持數組將是給定數組,它的數組偏移>將爲零。
capacity=limit=array.len;position=0
flip()方法,大家都很熟悉。
capacity:在讀/寫模式下都是固定的,就是我們分配的緩衝大小(容量)。
position:類似於讀/寫指針,表示當前讀(寫)到什麼位置。
limit:在寫模式下表示最多能寫入多少數據,此時和capacity相同。在讀模式下表示最多能讀多少數據,此時和緩存中的實際數據大小相同。
這是源代碼:

public final Buffer flip() {  
    limit = position;  
    position = 0;  
    mark = -1;  
    return this;  
}  

所以limit=0;position=0;
然後執行寫入操作,就造成了寫不進去數據的情況,因爲寫操作是從position到limit,但是他們都是0。
要想寫進去數據也很簡單,直接寫buffer就可以了

private void doWrite(SocketChannel sc, String response) throws IOException {
        if (response != null && response.trim().length() > 0) {
            ByteBuffer buf = ByteBuffer.wrap(response.getBytes());
            sc.write(buf);
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章