แปลงจำนวนเต็มเป็นไบต์อาร์เรย์ (Java)


137

เป็นวิธีที่รวดเร็วในการแปลงIntegerเป็นByte Array?

เช่น 0xAABBCCDD => {AA, BB, CC, DD}


1
ไม่ว่ารูปแบบอาร์เรย์ไบต์ที่เกิดขึ้นจะเป็นรูปแบบใด คุณจะทำอะไรกับมัน
skaffman

คำตอบ:


237

ดูที่คลาสByteBuffer

ByteBuffer b = ByteBuffer.allocate(4);
//b.order(ByteOrder.BIG_ENDIAN); // optional, the initial order of a byte buffer is always BIG_ENDIAN.
b.putInt(0xAABBCCDD);

byte[] result = b.array();

การตั้งค่าเพื่อให้แน่ใจว่าใบสั่งไบต์result[0] == 0xAA, result[1] == 0xBB, และresult[2] == 0xCCresult[3] == 0xDD

หรืออีกวิธีหนึ่งคุณสามารถทำได้ด้วยตนเอง:

byte[] toBytes(int i)
{
  byte[] result = new byte[4];

  result[0] = (byte) (i >> 24);
  result[1] = (byte) (i >> 16);
  result[2] = (byte) (i >> 8);
  result[3] = (byte) (i /*>> 0*/);

  return result;
}

ByteBufferระดับได้รับการออกแบบสำหรับงานมือสกปรกดังกล่าวแม้ว่า ในความเป็นจริงส่วนตัวjava.nio.Bitsกำหนดวิธีการช่วยเหลือที่ใช้โดยByteBuffer.putInt():

private static byte int3(int x) { return (byte)(x >> 24); }
private static byte int2(int x) { return (byte)(x >> 16); }
private static byte int1(int x) { return (byte)(x >>  8); }
private static byte int0(int x) { return (byte)(x >>  0); }

3
มันจะทำงานได้ดีถ้า bytebuffer อยู่ที่นั่นแล้ว ... ไม่อย่างนั้นดูเหมือนว่ามันจะใช้เวลานานกว่านี้ในการจัดสรรมากกว่าจะจัดสรรอาร์เรย์ไบต์ที่มีความยาว 4 และทำการเลื่อนด้วยตนเอง ... แต่เราอาจจะพูดถึง เกี่ยวกับความแตกต่างเล็กน้อย
เจสัน S

อินสแตนซ์ ByteBuffer สามารถแคช; และภายในก็มีการใช้งานอย่างแน่นอนด้วยการเลื่อนและปิดบัง
Gregory Pakosz

4
นี่คือคำตอบที่ดีอย่างสมบูรณ์แบบ โปรดทราบว่า big-endian เป็นค่าเริ่มต้นที่ระบุและวิธีการคือ "chainable" และอาร์กิวเมนต์ตำแหน่งเป็นทางเลือกดังนั้นจึงลดเป็น: byte [] result = ByteBuffer.allocate (4) .putInt (0xAABBCCDD) ); แน่นอนถ้าคุณทำสิ่งนี้ซ้ำ ๆ และเชื่อมผลลัพธ์ทั้งหมดเข้าด้วยกัน (ซึ่งเป็นเรื่องปกติเมื่อคุณกำลังทำสิ่งนี้) ให้จัดสรรบัฟเฟอร์เดี่ยวและใส่ putFoo () ทุกสิ่งที่คุณต้องการ - มันจะติดตามการชดเชยในขณะที่คุณไป มันเป็นคลาสที่มีประโยชน์มากจริงๆ
Kevin Bourrillion

สิ่งที่นำมาสู่ประเภทที่เซ็นชื่อ
เกรกอรี่ Pakosz

3
สำหรับใครที่ไม่รู้ putInt จะเขียน 4 ไบต์เสมอไม่ว่าขนาดของอินพุทจะเป็นเท่าใดก็ตาม หากคุณต้องการเพียง 2 ไบต์ใช้ putShort ฯลฯ ...
bvdb

36

การใช้BigInteger:

private byte[] bigIntToByteArray( final int i ) {
    BigInteger bigInt = BigInteger.valueOf(i);      
    return bigInt.toByteArray();
}

การใช้DataOutputStream:

private byte[] intToByteArray ( final int i ) throws IOException {      
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    dos.writeInt(i);
    dos.flush();
    return bos.toByteArray();
}

การใช้ByteBuffer:

public byte[] intToBytes( final int i ) {
    ByteBuffer bb = ByteBuffer.allocate(4); 
    bb.putInt(i); 
    return bb.array();
}

5
ใส่ใจกับการสั่งซื้อไบต์แม้ว่า
เกรกอรี่ Pakosz

1
ByteBuffer มอบ int ที่ไม่ได้ลงนามหรือไม่?
อรุณจอร์จ

@ ปาสกาลใช้ ByteBuffer ฉันลอง ByteBuffer bb = ByteBuffer.allocate (3); สำหรับสิ่งนี้มันจะให้ java.nio.BufferOverflowException ฉันไม่ได้รับสาเหตุที่มันไม่ทำงานสำหรับค่าน้อยกว่า 4? คุณช่วยอธิบายได้มั้ย
Sanjay Jain

@SanjayJain คุณได้รับข้อยกเว้นบัฟเฟอร์ล้นเนื่องจาก ints ใน Java มีขนาด 32- บิตหรือ 4 ไบต์ดังนั้นคุณต้องจัดสรรหน่วยความจำอย่างน้อย 4 ไบต์ใน ByteBuffer ของคุณ
น่าตกใจ

@GregoryPakosz ถูกต้องเกี่ยวกับการสั่งซื้อไบต์ การใช้คำตอบของเขาByteBufferนั้นง่ายกว่าหากคุณกำลังเผชิญกับ int ที่มากกว่า 2 ^ 31 - 1
ordonezalex

31

ใช้ฟังก์ชั่นนี้ใช้งานได้สำหรับฉัน

public byte[] toByteArray(int value) {
    return new byte[] {
            (byte)(value >> 24),
            (byte)(value >> 16),
            (byte)(value >> 8),
            (byte)value};
}

มันแปล int เป็นค่าไบต์


นอกจากนี้ยังไม่มีค่าอะไรที่มันจะทำงานโดยไม่คำนึงถึงบิตที่สำคัญที่สุดและมีประสิทธิภาพมากกว่าเมื่อเทียบกับคำตอบอื่น ๆ สามารถใช้ '>>' ได้เช่นกัน
algolicious

1
วิธีแก้ปัญหาโดยตรงเช่นนี้เร็วกว่าการเรียกวิธีการไลบรารีใด ๆ บางครั้งคุณต้องเล่นซอกับบิตโดยตรงด้วยโค้ดสองสามบรรทัดแทนที่จะเกิดโอเวอร์เฮดของการเรียกเมธอดไลบรารีทั้งหมด
David R Tribble

และนี่เป็นการแปลงระหว่างภาษาได้ดีดังนั้นจึงเป็นสิ่งที่ดีสำหรับการพัฒนาซอฟต์แวร์หลายภาษา
ผู้ประสานงาน

15

ถ้าคุณชอบGuavaคุณอาจใช้Intsคลาส:


สำหรับintbyte[]ให้ใช้toByteArray():

byte[] byteArray = Ints.toByteArray(0xAABBCCDD);

{0xAA, 0xBB, 0xCC, 0xDD}ผลคือ


มันกลับเป็นfromByteArray()หรือfromBytes():

int intValue = Ints.fromByteArray(new byte[]{(byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD});
int intValue = Ints.fromBytes((byte) 0xAA, (byte) 0xBB, (byte) 0xCC, (byte) 0xDD);

0xAABBCCDDผลคือ


8

คุณสามารถใช้BigInteger:

จากจำนวนเต็ม:

byte[] array = BigInteger.valueOf(0xAABBCCDD).toByteArray();
System.out.println(Arrays.toString(array))
// --> {-86, -69, -52, -35 }

อาร์เรย์ที่ส่งคืนมีขนาดที่ต้องการเพื่อแสดงตัวเลขดังนั้นจึงอาจมีขนาด 1 เพื่อเป็นตัวแทน 1 เช่น อย่างไรก็ตามขนาดต้องไม่เกินสี่ไบต์หากผ่าน int

จากสตริง:

BigInteger v = new BigInteger("AABBCCDD", 16);
byte[] array = v.toByteArray();

อย่างไรก็ตามคุณจะต้องระวังหากไบต์แรกสูงกว่า0x7F(เช่นในกรณีนี้) โดยที่ BigInteger จะแทรก 0x00 ไบต์ไปที่จุดเริ่มต้นของอาร์เรย์ สิ่งนี้จำเป็นเพื่อแยกความแตกต่างระหว่างค่าบวกและค่าลบ


ขอบคุณ! แต่เนื่องจากนี่คือ BigInteger ints จะล้อมรอบอย่างถูกต้องหรือไม่ นั่นคือจำนวนเต็มที่อยู่นอก Integer.MAX_VALUE แต่ยังสามารถแสดงด้วย 4 ไบต์เท่านั้น?
Buttercup

1
การดำเนินการนี้ไม่เร็วอย่างแน่นอน ;)
Peter Lawrey

นี่ไม่ใช่ตัวเลือกที่ดี ไม่เพียง แต่มันอาจเพิ่ม 0x00 ไบต์ แต่ยังอาจตัดศูนย์นำหน้าด้วย
ZZ Coder

1

วิธีแก้ปัญหาง่ายๆที่จัดการกับ ByteOrder ได้อย่างถูกต้อง:

ByteBuffer.allocate(4).order(ByteOrder.nativeOrder()).putInt(yourInt).array();



1

สิ่งนี้จะช่วยคุณ

import java.nio.ByteBuffer;
import java.util.Arrays;

public class MyClass
{
    public static void main(String args[]) {
        byte [] hbhbytes = ByteBuffer.allocate(4).putInt(16666666).array();

        System.out.println(Arrays.toString(hbhbytes));
    }
}

0

ยังสามารถเปลี่ยน -

byte[] ba = new byte[4];
int val = Integer.MAX_VALUE;

for(byte i=0;i<4;i++)
    ba[i] = (byte)(val >> i*8);
    //ba[3-i] = (byte)(val >> i*8); //Big-endian

0

นี่คือวิธีการที่ควรทำงานให้ถูกต้อง

public byte[] toByteArray(int value)
{
    final byte[] destination = new byte[Integer.BYTES];
    for(int index = Integer.BYTES - 1; index >= 0; index--)
    {
        destination[i] = (byte) value;
        value = value >> 8;
    };
    return destination;
};

0

มันเป็นทางออกของฉัน:

public void getBytes(int val) {
    byte[] bytes = new byte[Integer.BYTES];
    for (int i = 0;i < bytes.length; i ++) {
        int j = val % Byte.MAX_VALUE;
        bytes[i] = (j == 0 ? Byte.MAX_VALUE : j);
    }
}

ด้วยStringวิธี y:

public void getBytes(int val) {
    String hex = Integer.toHexString(val);
    byte[] val = new byte[hex.length()/2]; // because byte is 2 hex chars
    for (int i = 0; i < hex.length(); i+=2)
        val[i] = Byte.parseByte("0x" + hex.substring(i, i+2), 16);
    return val;
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.