Làm cách nào để khởi tạo một mảng byte trong Java?


138

Tôi phải lưu trữ một số giá trị không đổi (UUID) ở dạng mảng byte trong java và tôi tự hỏi cách tốt nhất để khởi tạo các mảng tĩnh đó là gì. Đây là cách tôi hiện đang làm, nhưng tôi cảm thấy như phải có một cách tốt hơn.

private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
    0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
    0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
    0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
    0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
    (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
    0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on

Có bất cứ điều gì tôi có thể sử dụng có thể kém hiệu quả hơn, nhưng sẽ trông sạch hơn? ví dụ:

private static final byte[] CDRIVES =
    new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };

Câu trả lời:


111

Sử dụng một hàm chuyển đổi một chuỗi hexa thành byte[], bạn có thể làm

byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");

Tôi muốn đề nghị bạn sử dụng hàm được xác định bởi Dave L trong Chuyển đổi biểu diễn chuỗi của kết xuất hex thành mảng byte bằng Java?

Tôi chèn nó ở đây để dễ đọc nhất:

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

Nếu bạn để CDRIVES staticfinal, hiệu suất giảm là không liên quan.


78
byte[] myvar = "Any String you want".getBytes();

Chuỗi ký tự có thể được thoát để cung cấp bất kỳ ký tự nào:

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();

50
Không phải điều đó biến chuỗi "0000"thành {0x30,0x30,0x30,0x30}(ASCII) chứ không phải {0x00,0x00,0x00,0x00}(nhị phân) như mong muốn của người đăng?
15:30

5
Nhìn vào tiêu đề của câu hỏi. Sau đó nhìn lại câu trả lời này. Bây giờ nói cho tôi biết, có gì sai về nó? Nó có thể không giải quyết vấn đề cụ thể của người gửi, nhưng nó chắc chắn đã giải quyết vấn đề của tôi. Tôi cần phải chuyển đổi một chuỗi thành một mảng byte để sử dụng làm hạt giống cho trình tạo số giả ngẫu nhiên và điều này hoạt động như một bùa mê.
e18r

@ e18r Nó đang tạo byte, vâng, nhưng bạn không biết điều này vì sự phụ thuộc này vào bộ ký tự mặc định. Ít nhất là sử dụng .getBytes (mong muốn Mã hóa).
lượng

@petmez câu hỏi ngớ ngẩn: trong JAVA, là một cái gì đó như "" .getBytes (UTF_8)); (getBytes trên một chuỗi trống) một điều an toàn để làm gì? nó có hợp pháp không? Hoặc tôi chỉ có thể làm: = new byte [0]; ?
Robert Achmann

1
@RobertAchmann "" .getbytes ("UTF-8") sẽ trả về một mảng trống và hoàn toàn hợp pháp.
Jazzepi

33

Trong Java 6, có một phương thức thực hiện chính xác những gì bạn muốn:

private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")

Ngoài ra, bạn có thể sử dụng Google Guava :

import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());

Phương pháp Guava là quá mức cần thiết, khi bạn đang sử dụng các mảng nhỏ. Nhưng Guava cũng có các phiên bản có thể phân tích luồng đầu vào. Đây là một tính năng hay khi xử lý các đầu vào thập lục phân lớn.


Ví dụ Guava không hoạt động hoàn toàn như được viết - nó cần phải có base16().lowerCase().decode(...)nếu bạn có các chữ số hex chữ thường. docs.guava-libraries.googlecode.com/git/javadoc/com/google/...
Peter DeGlopper

@PeterDeGlopper Tìm kiếm tốt, tôi đã cập nhật câu trả lời để mã hiện xử lý các chuỗi có cả ký tự chữ thường và chữ hoa.
stefan.schwetschke

1
javax.xml.bindđã bị xóa một cách đáng buồn trong Java 9.
Randomdude999

7

Bạn có thể sử dụng lớp Java UUID để lưu trữ các giá trị này, thay vì các mảng byte:

UUID

public UUID(long mostSigBits,
            long leastSigBits)

Xây dựng một UUID mới bằng cách sử dụng dữ liệu được chỉ định. mostSigBits được sử dụng cho 64 bit đáng kể nhất của UUID và lessSigBits trở thành 64 bit có ý nghĩa ít nhất của UUID.


2

Theo như một quy trình sạch, bạn có thể sử dụng đối tượng ByteArrayOutputStream ...

ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();

// ghi tất cả các giá trị vào bObj từng cái một

bObj.write(byte value)

// khi hoàn thành, bạn có thể lấy byte [] bằng cách sử dụng

CDRIVES = bObj.toByteArray();

// hơn bạn có thể lặp lại quy trình tương tự cho CMYDOCS và IEFRAME,

LƯU Ý Đây không phải là một giải pháp hiệu quả nếu bạn thực sự có mảng nhỏ.


2

Một giải pháp không có thư viện, trả về độ dài động, giải thích số nguyên không dấu (không phải bổ sung hai)

    public static byte[] numToBytes(int num){
    if(num == 0){
        return new byte[]{};
    }else if(num < 256){
        return new byte[]{ (byte)(num) };
    }else if(num < 65536){
        return new byte[]{ (byte)(num >>> 8),(byte)num };
    }else if(num < 16777216){
        return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }else{ // up to 2,147,483,647
        return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }
}

1

Tùy chọn ưa thích của tôi trong trường hợp này là sử dụng org.apache.commons.codec.binary.HexAPI có ích để chuyển đổi giữa Stringy hex và nhị phân. Ví dụ:

  1. Hex.decodeHex(char[] data)sẽ ném a DecoderExceptionnếu có các ký tự không phải là hex trong mảng hoặc nếu có một số ký tự lẻ.

  2. Hex.encodeHex(byte[] data)là đối tác của phương thức giải mã ở trên và phun ra char[].

  3. Hex.encodeHexString(byte[] data)mà chuyển đổi trở lại từ một bytemảng thành a String.

Sử dụng: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())


1

Bạn có thể sử dụng chức năng tiện ích này:

public static byte[] fromHexString(String src) {
    byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
    return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}

Không giống như các biến thể của Denys Séguret và stefan.schwetschke, nó cho phép chèn các ký hiệu dấu phân cách (dấu cách, tab, v.v.) vào chuỗi đầu vào, giúp dễ đọc hơn.

Ví dụ về cách sử dụng:

private static final byte[] CDRIVES
    = fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
    = fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
    = fromHexString("80531c87 a0426910 a2ea0800 2b30309d");

1

Loại nội bộ nhỏ nhất, tại thời điểm biên dịch có thể được chỉ định bởi các số hex là char , như

private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};

Để có một mảng byte tương đương, người ta có thể triển khai các chuyển đổi như

public static byte[] charToByteArray(char[] x)
{
    final byte[] res = new byte[x.length];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = (byte) x[i];
    }
    return res;
}

public static byte[][] charToByteArray(char[][] x)
{
    final byte[][] res = new byte[x.length][];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = charToByteArray(x[i]);
    }
    return res;
}

-2
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

và sau khi truy cập chuyển đổi thành byte.

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.