จะแปลงอาร์เรย์ไบต์เป็นค่าตัวเลข (Java) ได้อย่างไร?


91

ฉันมีอาร์เรย์ 8 ไบต์และต้องการแปลงเป็นค่าตัวเลขที่สอดคล้องกัน

เช่น

byte[] by = new byte[8];  // the byte array is stored in 'by'

// CONVERSION OPERATION
// return the numeric value

ฉันต้องการวิธีที่จะดำเนินการแปลงข้างต้น


4
"ค่าตัวเลข" หมายความว่าอย่างไร ไบต์แทนจำนวนเต็ม (long) หรือจำนวนทศนิยม (double) ในไบนารีหรือไม่? พวกเขาเป็นตัวแทนสตริงของตัวเลขหรือไม่? หรือเป็นตัวแทนอื่น?
starblue

1
สิ่งนี้มีประโยชน์: stackoverflow.com/questions/5399798/…
TacB0sS

หมายเหตุ: ลิงค์ของ TacB0sS คือสิ่งที่ฉันกำลังมองหาจริงๆ - ทั้งการแปลงไปข้างหน้าและข้างหลัง
Jay Taylor

new BigInteger(by).longValue()
user207421

คำตอบ:


108

สมมติว่าไบต์แรกเป็นไบต์ที่มีนัยสำคัญน้อยที่สุด:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value += ((long) by[i] & 0xffL) << (8 * i);
}

เป็นไบต์แรกที่สำคัญที่สุดจากนั้นจึงแตกต่างกันเล็กน้อย:

long value = 0;
for (int i = 0; i < by.length; i++)
{
   value = (value << 8) + (by[i] & 0xff);
}

แทนที่แบบยาวด้วยBigIntegerหากคุณมีมากกว่า 8 ไบต์

ขอบคุณ Aaron Digulla สำหรับการแก้ไขข้อผิดพลาดของฉัน


8
-1 ไบต์เป็นค่าที่ลงนาม! และแทนที่ pow () ด้วย shift (<<)! "value = (ค่า << 8) + (โดย [i] & 0xff)"
Aaron Digulla

ตัวดำเนินการ shift (<<) มีลำดับความสำคัญจากขวาไปซ้ายหรือไม่? โค้ดด้านบนทำงานอย่างไร มันทำงานได้ดีสำหรับฉัน แค่อยากรู้ว่าการทำงาน Thanx ล่วงหน้า
suraj

@Mnementh: ตัวดำเนินการ shift (<<) มีลำดับความสำคัญจากขวาไปซ้ายหรือไม่? โค้ดด้านบนทำงานอย่างไร มันทำงานได้ดีสำหรับฉัน แค่อยากรู้ว่าการทำงาน Thanx ล่วงหน้า
suraj

5
ในกรณีที่ใครก็ตามมีปัญหาเดียวกันกับฉันในตัวอย่างแรกโดย [i] จะต้องร่ายยาวมิฉะนั้นจะใช้ได้กับค่าที่น้อยกว่า 2 ^ 32 เท่านั้น นั่นคือvalue += ((long)by[i] & 0xffL) << (8 * i);
ลูกา

115

หนึ่งสามารถใช้Buffers ที่มีให้เป็นส่วนหนึ่งของjava.nioแพ็คเกจเพื่อทำการแปลง

ที่นี่byte[]อาร์เรย์ต้นทางมีความยาว 8 ซึ่งเป็นขนาดที่สอดคล้องกับlongค่า

ขั้นแรกbyte[]อาร์เรย์จะถูกรวมไว้ใน a ByteBufferจากนั้นByteBuffer.getLongจึงเรียกเมธอดเพื่อรับlongค่า:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 0, 0, 0, 0, 4});
long l = bb.getLong();

System.out.println(l);

ผลลัพธ์

4

ฉันขอขอบคุณ dfa ที่ชี้ให้เห็นByteBuffer.getLongวิธีการในความคิดเห็น


แม้ว่าอาจใช้ไม่ได้ในสถานการณ์นี้ แต่ความสวยงามของBuffers มาพร้อมกับการดูอาร์เรย์ที่มีค่าหลายค่า

ตัวอย่างเช่นถ้าเรามีอาร์เรย์ 8 ไบต์และเราต้องการดูเป็นสองintค่าเราสามารถรวมbyte[]อาร์เรย์ไว้ใน an ByteBufferซึ่งดูเป็น a IntBufferและรับค่าโดยIntBuffer.get:

ByteBuffer bb = ByteBuffer.wrap(new byte[] {0, 0, 0, 1, 0, 0, 0, 4});
IntBuffer ib = bb.asIntBuffer();
int i0 = ib.get(0);
int i1 = ib.get(1);

System.out.println(i0);
System.out.println(i1);

ผลลัพธ์:

1
4

แล้ว ByteBuffer.wrap (ไบต์ใหม่ [] {0, 0, 0, 1, 0, 0, 0, 4}) ล่ะ getLong () ล่ะ? วิธีนี้ควรอ่าน 8 ไบต์ถัดไปและแปลงเป็น long
dfa

@dfa: ขอบคุณที่ชี้ให้เห็นว่ามันใช้ได้ผล - ฉันจะแก้ไขคำตอบ :)
coobird

16

หากเป็นค่าตัวเลข 8 ไบต์คุณสามารถลอง:

BigInteger n = new BigInteger(byteArray);

หากนี่เป็นบัฟเฟอร์อักขระ UTF-8 คุณสามารถลอง:

BigInteger n = new BigInteger(new String(byteArray, "UTF-8"));

ฉันจะโหวตให้สำหรับคำตอบนี้หากคำตอบนั้นจบลงทันทีหลังจากข้อมูลโค้ดแรกหรือหากรวมโค้ดบางส่วนเพื่อแปลงสตริงเป็น "ค่าตัวเลข" ตามที่เป็นอยู่ครึ่งหลังของคำตอบของคุณดูเหมือนจะไม่ใช่คำตอบ
Laurence Gonsalves

ไม่ใช่สิ่งที่ฉันหมายถึงในตอนแรกฉันเปลี่ยนคำตอบ
Vincent Robert

15

เพียงแค่คุณสามารถใช้หรืออ้างถึงguava lib ที่ Google จัดหาให้ซึ่งมีวิธีการใช้ประโยชน์สำหรับการแปลงระหว่างอาร์เรย์แบบยาวและไบต์ รหัสลูกค้าของฉัน:

    long content = 212000607777l;
    byte[] numberByte = Longs.toByteArray(content);
    logger.info(Longs.fromByteArray(numberByte));


9

คุณยังสามารถใช้ BigInteger สำหรับไบต์ที่มีความยาวผันแปรได้ คุณสามารถแปลงเป็นแบบยาวจำนวนเต็มหรือแบบสั้นก็ได้ตามความต้องการของคุณ

new BigInteger(bytes).intValue();

หรือเพื่อแสดงถึงขั้ว:

new BigInteger(1, bytes).intValue();


1

แต่ละเซลล์ในอาร์เรย์จะถือว่าเป็น int ที่ไม่ได้ลงนาม:

private int unsignedIntFromByteArray(byte[] bytes) {
int res = 0;
if (bytes == null)
    return res;


for (int i=0;i<bytes.length;i++){
    res = res | ((bytes[i] & 0xff) << i*8);
}
return res;
}

เพียงแค่ทราบว่าฉันต้องใช้ 0xFFL มิฉะนั้นการร่ายจาก int 0xFF ถึง long จะมีการตั้งค่า 1 บิตที่ไม่ถูกต้องทั้งหมดเมื่อฉันพิมพ์ Long.toHexString (l)
ลุค

คุณต้องใช้ 0xFFL มิฉะนั้นคุณจะได้รับส่วนขยายเครื่องหมาย
สีเทา

0
public static long byteArrayToLong(byte[] bytes) {
    return ((long) (bytes[0]) << 56)
            + (((long) bytes[1] & 0xFF) << 48)
            + ((long) (bytes[2] & 0xFF) << 40)
            + ((long) (bytes[3] & 0xFF) << 32)
            + ((long) (bytes[4] & 0xFF) << 24)
            + ((bytes[5] & 0xFF) << 16)
            + ((bytes[6] & 0xFF) << 8)
            + (bytes[7] & 0xFF);
}

แปลงอาร์เรย์ไบต์ (ยาว 8 ไบต์) เป็นยาว

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