![](/img/trans.png)
[英]Is there an implementation of ByteBuffer that allows for dynamic growing and extends java.nio.ByteBuffer?
[英]Growing ByteBuffer
有沒有人見過 java.nio.ByteBuffer 的實現,如果 putX() 調用超出容量,它會動態增長?
我想這樣做的原因有兩個:
為了讓異步 I/O 工作,你必須有連續的內存。 在 C 中你可以嘗試重新分配一個數組,但在 Java 中你必須分配新的內存。 您可以寫入ByteArrayOutputStream
,然后在准備發送時將其轉換為ByteBuffer
。 缺點是您正在復制內存,而高效 IO 的關鍵之一是減少復制內存的次數。
ByteBuffer 不能真正以這種方式工作,因為它的設計概念只是一個特定數組的視圖,您也可以直接引用它。 它無法嘗試將該數組交換為更大的數組而不會發生奇怪的事情。
您要使用的是DataOutput
。 最方便的方法是使用(預發布)Guava 庫:
ByteArrayDataOutput out = ByteStreams.newDataOutput();
out.write(someBytes);
out.writeInt(someInt);
// ...
return out.toByteArray();
但是您也可以手動從 ByteArrayOutputStream 創建一個 DataOutputStream,並通過將它們鏈接到 AssertionErrors 來處理虛假的 IOExceptions。
看看 Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html這是一個替代品(它包裝了 ByteBuffer)
但是,我建議你分配比你需要的更多,不要太擔心。 如果您分配一個緩沖區(尤其是直接緩沖區),操作系統會為其提供虛擬內存,但僅在實際使用時才使用物理內存。 虛擬內存應該很便宜。
看看 Netty 的DynamicChannelBuffer也可能是值得的。 我覺得方便的事情是:
slice(int index, int length)
另一種選擇是使用帶有大緩沖區的直接內存。 這會消耗虛擬內存,但僅使用您使用的物理內存(按頁面,通常為 4K)
因此,如果您分配 1 MB 的緩沖區,它會占用 1 MB 的虛擬內存,但唯一的操作系統為實際使用的應用程序提供物理頁面。
結果是您看到您的應用程序使用了大量虛擬內存,但駐留內存量相對較少。
事實上,自動擴展緩沖區使用起來更加直觀。 如果你能負擔得起重新分配的性能奢侈,你為什么不呢!?
Netty 的ByteBuf
正是為您提供了這一點。 就像他們采用了java.nio
的ByteBuffer
並刮掉了邊緣,使其更易於使用。
此外,它位於 Maven 上的獨立netty-buffer
包中,因此您無需包含完整的 Netty 套件即可使用。
我建議使用輸入流從文件接收數據(如果您需要非阻塞,則使用獨立線程)然后將字節讀入 ByteArrayOutstream ,這使您能夠將其作為字節數組獲取。 這是一個沒有添加太多解決方法的簡單示例。
try (InputStream inputStream = Files.newInputStream(
Paths.get("filepath"), StandardOpenOption.READ)){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int byteRead = 0;
while(byteRead != -1){
byteRead = inputStream.read();
baos.write(byteRead);
}
ByteBuffer byteBuffer = ByteBuffer.allocate(baos.size())
byteBuffer.put(baos.toByteArray());
//. . . . use the buffer however you want
}catch(InvalidPathException pathException){
System.out.println("Path exception: " + pathException);
}
catch (IOException exception){
System.out.println("I/O exception: " + exception);
}
另一個解決方案是分配足夠多的內存,填充ByteBuffer
,然后只返回占用的字節數組:
初始化一個大的ByteBuffer
:
ByteBuffer byteBuffer = ByteBuffer.allocate(1000);
在你把東西放進去之后:
private static byte[] getOccupiedArray(ByteBuffer byteBuffer)
{
int position = byteBuffer.position();
return Arrays.copyOfRange(byteBuffer.array(), 0, position);
}
但是,從一開始就使用org.apache.commons.io.output.ByteArrayOutputStream
可能是最好的解決方案。
Netty ByteBuf 在這方面做得很好。
Vector 允許持續增長
Vector<Byte> bFOO = new Vector<Byte>();
bFOO.add((byte) 0x00);`
要序列化某些東西,您將需要條目中的對象。 您可以做的是將您的對象放在對象集合中,然后進行循環以獲取迭代器並將它們放入字節數組中。 然后,調用ByteBuffer.allocate(byte[].length)
。 這就是我所做的,它對我有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.