2009-11-21 19 views
32

Có ai từng thấy việc triển khai java.nio.ByteBuffer sẽ phát triển động nếu cuộc gọi putX() vượt quá khả năng không?Trồng ByteBuffer

Lý do tôi muốn làm điều đó theo cách này có hai phần:

  1. tôi không biết bao nhiêu gian tôi cần trước thời hạn.
  2. Tôi không muốn làm một ByteBuffer.allocate mới() sau đó đặt hàng loạt() mỗi khi tôi hết dung lượng.

Trả lời

25

Để I/O không đồng bộ hoạt động, bạn phải có bộ nhớ liên tục. Trong C bạn có thể cố gắng phân bổ lại một mảng, nhưng trong Java bạn phải cấp phát bộ nhớ mới. Bạn có thể viết thư cho ByteArrayOutputStream và sau đó chuyển đổi nó thành ByteBuffer vào thời điểm bạn sẵn sàng gửi. Nhược điểm là bạn đang sao chép bộ nhớ, và một trong các phím để hiệu quả IO là giảm số lần bộ nhớ được sao chép.

+1

ByteArrayOutputStream là thực sự chính xác những gì tôi muốn (Tôi không thực sự làm bất kỳ I/O, tôi chỉ có một số serialization phức tạp để làm). Cảm ơn! – Seth

+1

Seth, tuyên bố của bạn về câu hỏi ("putX") ngụ ý rằng bạn sẽ cần các phương thức như putInt, putDouble, vv, ngụ ý rằng ByteArrayOutputStream sẽ không đủ cho bạn, do đó câu trả lời của tôi về ByteArrayDataOutput. –

+0

Tôi thậm chí sẽ không hỏi làm thế nào buf kích thước cố định là chính xác những gì bạn muốn sau khi bạn yêu cầu buf kích thước không giới hạn. Chúng ta đang sống trong thế giới nơi mà vô lý là một chuẩn mực. – Val

6

Có một cái nhìn tại Mina IOBuffer https://mina.apache.org/mina-project/userguide/ch8-iobuffer/ch8-iobuffer.html mà là một thả thay thế (nó kết thúc tốt đẹp ByteBuffer)

Tuy nhiên, tôi đề nghị bạn phân bổ nhiều hơn bạn cần và đừng lo lắng về nó quá nhiều. Nếu bạn cấp phát một bộ đệm (đặc biệt là bộ đệm trực tiếp), hệ điều hành sẽ cho nó bộ nhớ ảo nhưng nó chỉ sử dụng bộ nhớ vật lý khi nó thực sự được sử dụng. Bộ nhớ ảo phải rất rẻ.

+6

Tôi thích cảnh báo trên trang: "Lý do chính tại sao MINA có trình bao bọc riêng của mình trên đầu trang của ByteBuffer nio là có bộ đệm mở rộng. Đây là một quyết định rất tồi tệ". – Suppressingfire

+0

Thật vậy, viết vào bộ nhớ ngụ ý rằng bạn cuối cùng muốn có một số giới hạn và, hơn nữa, không phải là giới hạn lớn. Vẫn chưa biết liệu một phần không sử dụng ArrayBuffer có được miễn phí cho các ứng dụng/sử dụng khác hay không. – Val

+1

Liên kết đã chết. 404. – luckydonald

8

Một ByteBuffer không thể thực sự hoạt động theo cách này, vì khái niệm thiết kế của nó chỉ là một khung nhìn của một mảng cụ thể mà bạn cũng có thể tham chiếu trực tiếp. Nó không thể cố gắng trao đổi mảng đó cho một mảng lớn hơn mà không có sự kỳ quặc xảy ra.

Điều bạn muốn sử dụng là DataOutput. Cách thuận tiện nhất là sử dụng (pre-release) Ổi thư viện:

ByteArrayDataOutput out = ByteStreams.newDataOutput(); 
out.write(someBytes); 
out.writeInt(someInt); 
// ... 
return out.toByteArray(); 

Nhưng bạn cũng có thể tạo ra một DataOutputStream từ một ByteArrayOutputStream bằng tay, và chỉ cần đối phó với IOExceptions giả mạo bằng cách kết nối chúng vào AssertionErrors.

+0

Không có 'ByteArrayDataOutput' và' ByteStreams' xuất hiện trong JDK, như của Java 8. Bạn đang đề cập đến điều gì? – EJP

+0

@EJP Đó là các lớp học từ [Google Guava] (https://code.google.com/p/guava-libraries/) như Kevin đã đề cập. – Jesper

4

Bạn cũng có thể xem xét số DynamicChannelBuffer của Netty. Những điều mà tôi tìm thấy có ích là:

  • slice(int index, int length)
  • hoạt động unsigned
  • tách viết và người đọc chỉ số
4

Một lựa chọn khác là sử dụng bộ nhớ trực tiếp với một bộ đệm lớn. Điều này tiêu thụ bộ nhớ ảo nhưng chỉ sử dụng nhiều bộ nhớ vật lý như bạn sử dụng (theo trang thường là 4K)

Vì vậy, nếu bạn cấp phát bộ đệm 1 MB, nó sẽ tính 1 MB bộ nhớ ảo. các trang đến ứng dụng thực sự sử dụng.

Hiệu ứng là bạn thấy ứng dụng của mình bằng rất nhiều bộ nhớ ảo nhưng một lượng bộ nhớ cư trú tương đối nhỏ.

+0

hãy thêm một số ví dụ mã – Alex

-2

Một Vector cho phép cho sự tăng trưởng liên tục

Vector<Byte> bFOO = new Vector<Byte>(); bFOO.thêm ((byte) 0x00); `

+5

Với phương pháp này, đối với mỗi byte bạn cần phải tạo một đối tượng Byte sẽ có tiêu đề 8 byte, +1 byte để lưu trữ giá trị bên trong đối tượng. Bây giờ, tất cả các đối tượng java mất nhiều 8 byte, do đó, làm cho 16 byte cho mỗi đối tượng. Cho phép nói rằng chúng tôi đang sử dụng một hệ thống 32 bit để tham chiếu đến các đối tượng trong vector là 4 byte mỗi. Vì vậy, để lưu trữ mỗi byte bạn cần 20 byte bộ nhớ. Thats không tốt lắm. – Numeron

+0

@Numeron Byte là một trọng tải, có chính xác 256 trường hợp trong JVM trừ khi bạn gọi 'mới' thay vì 'valueOf'. Auto-boxing làm thứ hai. Nhưng câu trả lời là người nghèo theo cách nào đó, vì sự chuyển hướng được đóng hộp sẽ lớn hơn và chậm hơn đáng kể ngay cả khi không có các đối tượng Byte được phân bổ. –

-6

Để tuần tự, bạn sẽ cần đối tượng trong mục nhập. Những gì bạn có thể làm là đặt đối tượng của bạn trong bộ sưu tập các đối tượng, và sau đó làm cho vòng lặp để có được iterator và đặt chúng trong mảng byte. Sau đó, gọi số ByteBuffer.allocate(byte[].length). Đó là những gì tôi đã làm và nó làm việc cho tôi.

Các vấn đề liên quan