รับอาร์เรย์ไบต์จาก ByteBuffer ใน java


96

นี่เป็นวิธีที่แนะนำในการรับไบต์จาก ByteBuffer หรือไม่

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()]
bb.get(b, 0, b.length);

คำตอบ:


108

ขึ้นอยู่กับสิ่งที่คุณต้องการจะทำ.

หากสิ่งที่คุณต้องการคือการดึงข้อมูลไบต์ที่เหลืออยู่ (ระหว่างตำแหน่งและขีด จำกัด ) สิ่งที่คุณมีจะได้ผล คุณสามารถทำได้:

ByteBuffer bb =..

byte[] b = new byte[bb.remaining()];
bb.get(b);

ซึ่งเทียบเท่ากับByteBuffer javadocs


6
แก้ไข. และโปรดทราบว่าbb.capacity() อาจเท่ากันbb.remaining()แม้ว่าอาร์เรย์สำรองจะยาวกว่าดังนั้นคุณต้องไม่ใช้ความเท่าเทียมกันเป็นการทดสอบว่าเมื่อbb.array()ใดถูกต้อง ดูByteBuffer.slice().
cdunn2001

1
bb.slice().remaining()โปรดทราบว่าเพื่อหลีกเลี่ยงการเปลี่ยนตำแหน่งของบัฟเฟอร์ที่ฉันใช้ วิธีนี้จะดูเหมือนการถ่ายโอนข้อมูลที่สะอาดโดยไม่ต้องสัมผัสกับบัฟเฟอร์เดิม
Kyll

วิธีนี้ทำให้ฉันได้รับการลงชื่อไบต์ แต่ฉันต้องการยกเลิกการลงชื่อ ... มีความคิดอย่างไร
H Raval

Java ไม่มีแนวคิดของจำนวนเต็มที่ไม่ได้ลงนามมี แต่คนเซ็น หากคุณต้องการ "ไบต์ที่ไม่ได้ลงชื่อ" คุณต้องแคสต์เป็นintและใช้ bitmask: int unsigned_byte = b[k] & 0xff;สำหรับค่าบางอย่างของk.
Jason S

ถ้าคุณต้องการรับบัฟเฟอร์ทั้งหมดในอาร์เรย์ไบต์คุณจะโทรหาByteBuffer#clearก่อนหรือไม่?
Kenny Worden

21

โปรดทราบว่า bb.array () ไม่ให้เกียรติตำแหน่งไบต์ - บัฟเฟอร์และอาจแย่กว่านั้นหาก bytebuffer ที่คุณกำลังทำงานอยู่นั้นเป็นส่วนของบัฟเฟอร์อื่น ๆ

ได้แก่

byte[] test = "Hello World".getBytes("Latin1");
ByteBuffer b1 = ByteBuffer.wrap(test);
byte[] hello = new byte[6];
b1.get(hello); // "Hello "
ByteBuffer b2 = b1.slice(); // position = 0, string = "World"
byte[] tooLong = b2.array(); // Will NOT be "World", but will be "Hello World".
byte[] world = new byte[5];
b2.get(world); // world = "World"

ซึ่งอาจไม่ใช่สิ่งที่คุณตั้งใจจะทำ

หากคุณไม่ต้องการคัดลอกไบต์อาร์เรย์จริงๆวิธีแก้ปัญหาอาจเป็นการใช้ arrayOffset ของไบต์บัฟเฟอร์ () + ที่เหลือ () แต่จะใช้ได้เฉพาะเมื่อแอปพลิเคชันรองรับดัชนี + ความยาวของไบต์ - บัฟเฟอร์ ความต้องการ


"bb.array () ไม่เป็นไปตามตำแหน่งไบต์บัฟเฟอร์" คุณสามารถให้รายละเอียดเพิ่มเติมเกี่ยวกับส่วนนี้กับเราได้ ฉันเข้าใจตัวอย่างของ slice แต่ต้องการรายละเอียดเพิ่มเติมว่าทำไม bb.array () ถึงเลอะ
kkrishnaai

5

ง่ายๆแค่นั้นเอง

  private static byte[] getByteArrayFromByteBuffer(ByteBuffer byteBuffer) {
    byte[] bytesArray = new byte[byteBuffer.remaining()];
    byteBuffer.get(bytesArray, 0, bytesArray.length);
    return bytesArray;
}

4
final ByteBuffer buffer;
if (buffer.hasArray()) {
    final byte[] array = buffer.array();
    final int arrayOffset = buffer.arrayOffset();
    return Arrays.copyOfRange(array, arrayOffset + buffer.position(),
                              arrayOffset + buffer.limit());
}
// do something else

4

หากไม่มีใครรู้อะไรเกี่ยวกับสถานะภายในของ ByteBuffer (โดยตรง) ที่กำหนดและต้องการดึงเนื้อหาทั้งหมดของบัฟเฟอร์สิ่งนี้สามารถใช้ได้:

ByteBuffer byteBuffer = ...;
byte[] data = new byte[byteBuffer.capacity()];
((ByteBuffer) byteBuffer.duplicate().clear()).get(data);

ByteBuffer.get(byte[])ส่งกลับ aByteBuffer
pyb

และ...? ไม่แน่ใจว่าคุณหมายถึงอะไรขออภัย
TomášMyšík

คำถามคือจะเปลี่ยนจาก ByteBuffer เป็น byte [] ได้อย่างไร
pyb

2
เมื่อเรียกแล้วพวกเขาจะอยู่ในdataตัวแปร getter กลับthisมาดู Javadoc ของมัน
TomášMyšík

ขอบคุณฉันไม่เข้าใจ เนื่องจากเมธอด get ส่งคืนค่าฉันไม่ได้คาดหวังว่ามันจะมีผลข้างเคียงเช่นกัน
pyb

1

นี่เป็นวิธีง่ายๆในการหาไบต์ [] แต่ส่วนหนึ่งของการใช้ ByteBuffer คือการหลีกเลี่ยงการสร้างไบต์ [] บางทีคุณอาจได้รับสิ่งที่คุณต้องการจากไบต์ [] โดยตรงจาก ByteBuffer


15
แต่บ่อยครั้งคุณจะต้องเรียกบางสิ่งบางอย่าง (ไม่ใช่ในรหัสของคุณเอง) ที่ใช้ไบต์ [] ดังนั้นการแปลงจึงไม่ใช่ทางเลือก
James Moore
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.