Số nguyên Java thành mảng byte


190

Tôi có một số nguyên: 1695609641

khi tôi sử dụng phương pháp:

String hex = Integer.toHexString(1695609641);
system.out.println(hex); 

cho:

6510f329

nhưng tôi muốn một mảng byte:

byte[] bytearray = new byte[] { (byte) 0x65, (byte)0x10, (byte)0xf3, (byte)0x29};

Làm thế nào tôi có thể làm điều này?



Câu trả lời:


293

sử dụng ByteBuffer của Java NIO rất đơn giản:

byte[] bytes = ByteBuffer.allocate(4).putInt(1695609641).array();

for (byte b : bytes) {
   System.out.format("0x%x ", b);
}

đầu ra:

0x65 0x10 0xf3 0x29 

4
Hoặc sử dụng định dạng "0x%02X"nếu bạn luôn muốn hai ký tự thập lục phân cũng như các thập lục phân chữ hoa, ví dụ: System.out.format("0x%02X", (byte) 10)hiển thị 0x0A.
Maarten Bodewes

12
Bạn có thể sử dụng Integer.SIZE / 8 để tránh mã hóa số 4, đây là mẫu hoạt động tốt cho các loại khác như Long.
davenpcj

3
@davenpcj Thậm chí bạn có thể sử dụng Integer.SIZE / Byte.SIZE
rkosegi

11
@rkosegi Hoặc thậm chí là Integer.BYTES kể từ Java 8 :)
drvdijk

1
Chủ đề @MaartenBodewes không có gì để định dạng có thể nhìn thấy, nhưng hoạt động kiểu gốc
Jacek Cz

146

Làm thế nào về:

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

Ý tưởng không phải của tôi . Tôi đã lấy nó từ một số bài đăng trên dzone.com .


44
Tôi thấy quan điểm của bạn, nhưng đối với nhiệm vụ cụ thể này, mã của tôi mang tính khai báo và rõ ràng hơn một số 'ma thuật' ByteBuffer, người ta phải kiểm tra xem nó làm gì.
Grzegorz Oledzki

24
@Kevin - điều đó rất khắc nghiệt - có rất nhiều trường hợp loại mã này phù hợp, ví dụ như trong xử lý hình ảnh. Các thư viện JDK nói chung là tuyệt vời, nhưng chúng không bao gồm và / hoặc không được tối ưu hóa cho tất cả các trường hợp sử dụng.
mikera

14
đã đồng ý; chi phí hoạt động và độ phức tạp của ByteBuffer có thể không phù hợp so với một số thao tác byte đơn giản và nổi tiếng.
swdunlop

6
Một điểm khác tôi muốn nói thêm là bạn đã sử dụng toán tử dịch chuyển bên phải chưa ký thay >>>vì toán tử dịch chuyển bên phải >>( docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html ) để hành vi có thể không được như mong muốn / như mong đợi với các số đã ký và không dấu
RobV

4
Cách tiếp cận này dường như nhanh hơn các phương thức ByteBuffer hoặc BigInteger đã đề cập. Một cái gì đó khác để xem xét nếu bạn sẽ thực hiện rất nhiều chuyển đổi.
người tìm kiếm

45

BigInteger.valueOf(1695609641).toByteArray()


2
bạn có đảm bảo gì sẽ tạo ra một mảng 4 byte?
MeBigFatGuy

2
Chính xác những gì MeBigFatGuy đã viết. Javadoc của các BigInteger.toByteArray()trạng thái: "Mảng sẽ chứa số byte tối thiểu cần thiết để đại diện cho BigInteger này ..."
icza

2
Trường hợp trong câu hỏi nó yêu cầu mảng byte có độ dài cố định 4? Tùy thuộc vào thuật toán, điều này có nghĩa là một phần của bạn có thể sử dụng độ dài của mảng
vmpn

Điều này là năng động hơn nhiều và nên là câu trả lời đúng. Bạn có thể chỉ cần thực hiện nối thêm Array để tạo kích thước mong muốn nếu muốn. Đặc biệt khi bạn phải xem xét các giá trị int đã ký Java.
Droid Chris

2
Điều này dường như tạo ra một byte cho 0x7f và hai byte cho 0x80 (hai byte là: 0x0 0x80).
Scot

26
byte[] IntToByteArray( int data ) {    
    byte[] result = new byte[4];
    result[0] = (byte) ((data & 0xFF000000) >> 24);
    result[1] = (byte) ((data & 0x00FF0000) >> 16);
    result[2] = (byte) ((data & 0x0000FF00) >> 8);
    result[3] = (byte) ((data & 0x000000FF) >> 0);
    return result;        
}


7
byte[] conv = new byte[4];
conv[3] = (byte) input & 0xff;
input >>= 8;
conv[2] = (byte) input & 0xff;
input >>= 8;
conv[1] = (byte) input & 0xff;
input >>= 8;
conv[0] = (byte) input;

2
Điều đó trích xuất 8 byte đáng kể nhất. Nó cũng tránh kéo dấu của số đầu vào vào octet đã chuyển đổi.
Carl Smotricz

stackoverflow.com/questions/35305634/ - bạn có thể giải C # này thành Java không?

5
public static byte[] intToBytes(int x) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream out = new DataOutputStream(bos);
    out.writeInt(x);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

4

Các đoạn bên dưới hoạt động ít nhất để gửi một int qua UDP.

int đến mảng byte:

public byte[] intToBytes(int my_int) throws IOException {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = new ObjectOutputStream(bos);
    out.writeInt(my_int);
    out.close();
    byte[] int_bytes = bos.toByteArray();
    bos.close();
    return int_bytes;
}

mảng byte đến int:

public int bytesToInt(byte[] int_bytes) throws IOException {
    ByteArrayInputStream bis = new ByteArrayInputStream(int_bytes);
    ObjectInputStream ois = new ObjectInputStream(bis);
    int my_int = ois.readInt();
    ois.close();
    return my_int;
}

4
việc sử dụng ObjectOutputStream là không chính xác. Sử dụng DataOutputStream, việc sử dụng OOS làm cho nó để mảng byte không phải là 4 byte.
MeBigFatGuy

2

Bởi vì nhìn chung bạn sẽ muốn chuyển đổi mảng này trở lại một int tại một điểm sau, đây là các phương thức để chuyển đổi một mảng int thành một mảng byte và ngược lại:

public static byte[] convertToByteArray(final int[] pIntArray)
{
    final byte[] array = new byte[pIntArray.length * 4];
    for (int j = 0; j < pIntArray.length; j++)
    {
        final int c = pIntArray[j];
        array[j * 4] = (byte)((c & 0xFF000000) >> 24);
        array[j * 4 + 1] = (byte)((c & 0xFF0000) >> 16);
        array[j * 4 + 2] = (byte)((c & 0xFF00) >> 8);
        array[j * 4 + 3] = (byte)(c & 0xFF);
    }
    return array;
}

public static int[] convertToIntArray(final byte[] pByteArray)
{
    final int[] array = new int[pByteArray.length / 4];
    for (int i = 0; i < array.length; i++)
        array[i] = (((int)(pByteArray[i * 4]) << 24) & 0xFF000000) |
                (((int)(pByteArray[i * 4 + 1]) << 16) & 0xFF0000) |
                (((int)(pByteArray[i * 4 + 2]) << 8) & 0xFF00) |
                ((int)(pByteArray[i * 4 + 3]) & 0xFF);
    return array;
}

Lưu ý rằng vì việc truyền dấu hiệu và như vậy, "& 0xFF ..." là cần thiết khi chuyển đổi trở lại int.


1
integer & 0xFF

cho byte đầu tiên

(integer >> 8) & 0xFF

cho lần thứ hai và vòng lặp, v.v., viết vào một mảng byte được sắp xếp trước. Một chút lộn xộn, không may.


1

Lớp org.apache.hadoop.hbase.util.Bytes có một loạt các phương thức chuyển đổi byte [] tiện dụng, nhưng bạn có thể không muốn thêm toàn bộ bình HBase vào dự án của mình cho mục đích này. Thật đáng ngạc nhiên khi không chỉ có phương thức như vậy thiếu AFAIK từ JDK, mà còn từ các lib rõ ràng như commons io.


1

Tôi thử

public static byte[] toBytes(final int intVal, final int... intArray) {
    if (intArray == null || (intArray.length == 0)) {
        return ByteBuffer.allocate(4).putInt(intVal).array();
    } else {
        final ByteBuffer bb = ByteBuffer.allocate(4 + (intArray.length * 4)).putInt(intVal);
        for (final int val : intArray) {
            bb.putInt(val);
        }
        return bb.array();
    }
}

Với nó, bạn có thể làm điều này:

byte[] fourBytes = toBytes(0x01020304);
byte[] eightBytes = toBytes(0x01020304, 0x05060708);

Lớp đầy đủ có tại đây: https://gist.github.com/superbob/6548493 , nó hỗ trợ khởi tạo từ quần short hoặc dài

byte[] eightBytesAgain = toBytes(0x0102030405060708L);

1

Nếu bạn đang sử dụng apache-commons

public static byte[] toByteArray(int value) {
    byte result[] = new byte[4];
    return Conversion.intToByteArray(value, 0, result, 0, 4);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.