Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的字节数组与Int转换_Java - Fatal编程技术网

Java中的字节数组与Int转换

Java中的字节数组与Int转换,java,Java,我在使用这两个函数时遇到了一些困难:byteArrayToInt和intToByteArray 问题是,如果我用一个去得到另一个,然后用这个结果去得到前者,结果是不同的,正如我下面的例子所示 我在代码中找不到错误。任何想法都是非常受欢迎的。谢谢 public static void main(String[] args) { int a = 123; byte[] aBytes = intToByteArray(a); int a2 = byteArrayToInt(aB

我在使用这两个函数时遇到了一些困难:
byteArrayToInt
intToByteArray

问题是,如果我用一个去得到另一个,然后用这个结果去得到前者,结果是不同的,正如我下面的例子所示

我在代码中找不到错误。任何想法都是非常受欢迎的。谢谢

public static void main(String[] args)
{
    int a = 123;
    byte[] aBytes = intToByteArray(a);
    int a2 = byteArrayToInt(aBytes);

    System.out.println(a);         // prints '123'
    System.out.println(aBytes);    // prints '[B@459189e1'
    System.out.println(a2);        // prints '2063597568
            System.out.println(intToByteArray(a2));  // prints '[B@459189e1'
}

public static int byteArrayToInt(byte[] b) 
{
    int value = 0;
    for (int i = 0; i < 4; i++) {
        int shift = (4 - 1 - i) * 8;
        value += (b[i] & 0x000000FF) << shift;
    }
    return value;
}

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[0] = (byte) (a & 0xFF);   
    ret[1] = (byte) ((a >> 8) & 0xFF);   
    ret[2] = (byte) ((a >> 16) & 0xFF);   
    ret[3] = (byte) ((a >> 24) & 0xFF);
    return ret;
}
publicstaticvoidmain(字符串[]args)
{
INTA=123;
字节[]aBytes=intToByteArray(a);
int a2=字节数(aBytes);
System.out.println(a);//打印'123'
System.out.println(aBytes);//prints'[B@459189e1'
System.out.println(a2);//打印'2063597568
System.out.println(intToByteArray(a2));//prints'[B@459189e1'
}
公共静态int byteArrayToInt(字节[]b)
{
int值=0;
对于(int i=0;i<4;i++){
整数移位=(4-1-i)*8;
值+=(b[i]&0x000000FF)>8)和0xFF);
ret[2]=(字节)((a>>16)和0xFF);
ret[3]=(字节)((a>>24)和0xFF);
返回ret;
}
您的方法应该是(类似)

public static int byteArrayToInt(字节[]b)
{
返回b[3]&0xFF|
(b[2]和0xFF)>16)和0xFF),
(字节)((a>>8)和0xFF),
(字节)(a和0xFF)
};
}
使用以下代码对这些方法进行了测试:

Random rand = new Random(System.currentTimeMillis());
byte[] b;
int a, v;
for (int i=0; i<10000000; i++) {
    a = rand.nextInt();
    b = intToByteArray(a);
    v = byteArrayToInt(b);
    if (a != v) {
        System.out.println("ERR! " + a + " != " + Arrays.toString(b) + " != " + v);
    }
}
System.out.println("Done!");
Random rand=new Random(System.currentTimeMillis());
字节[]b;
int a,v;
对于(int i=0;i您正在两种方法之间进行交换。您需要
intToByteArray(int a)
将低阶位分配到
ret[0]
,但是
byteArrayToInt(byte[]b)
b[0]
分配给结果的高阶位。您需要反转其中一个,如:

public static byte[] intToByteArray(int a)
{
    byte[] ret = new byte[4];
    ret[3] = (byte) (a & 0xFF);   
    ret[2] = (byte) ((a >> 8) & 0xFF);   
    ret[1] = (byte) ((a >> 16) & 0xFF);   
    ret[0] = (byte) ((a >> 24) & 0xFF);
    return ret;
}

这是我的实现

public static byte[] intToByteArray(int a) {
    return BigInteger.valueOf(a).toByteArray();
}

public static int byteArrayToInt(byte[] b) {
    return new BigInteger(b).intValue();
}

我仔细研究了许多类似的问题,发现……我不喜欢每种类型的转换代码都是重复的,因此我制定了一个通用方法来执行这项任务:

public static byte[] toByteArray(long value, int n)
{
    byte[] ret = new byte[n];
    ret[n-1] = (byte) ((value >> (0*8) & 0xFF);   
    ret[n-2] = (byte) ((value >> (1*8) & 0xFF);   
    ...
    ret[1] = (byte) ((value >> ((n-2)*8) & 0xFF);   
    ret[0] = (byte) ((value >> ((n-1)*8) & 0xFF);   
    return ret;
}

请参阅。

这需要做大量工作:

public static int byteArrayToLeInt(byte[] b) {
    final ByteBuffer bb = ByteBuffer.wrap(b);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    return bb.getInt();
}

public static byte[] leIntToByteArray(int i) {
    final ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE);
    bb.order(ByteOrder.LITTLE_ENDIAN);
    bb.putInt(i);
    return bb.array();
}
此方法使用包中的Java和功能。在需要可读性的地方,应首选此代码。它还应非常容易记住

我在这里展示了小端字节顺序。要创建一个大端字节版本,您只需省去对的调用


在性能高于可读性的代码中(大约是可读性的10倍):

public static int byteArrayToLeInt(字节[]encodedValue){
int value=(encodedValue[3]>Byte.SIZE*2);
encodedValue[1]=(字节)(值>>字节大小);
encodedValue[0]=(字节)值;
返回编码值;
}
只需将字节数组索引从0反转为3,即可创建此代码的大端版本


注:

  • 在Java8中,还可以使用常量,它比
    Integer.SIZE/Byte.SIZE
    更简洁

您也可以将biginger用于可变长度字节。您可以将其转换为Long、Integer或Short,以适合您的需要为准

new BigInteger(bytes).intValue();
或表示极性:

new BigInteger(1, bytes).intValue();
要返回字节,请执行以下操作:

new BigInteger(bytes).toByteArray()

我喜欢owlstead最初的答案,如果您不喜欢在每次方法调用中创建
ByteBuffer
的想法,那么您可以通过调用
ByteBuffer
方法来重用
ByteBuffer
,方法是
.clear()
.flip()

ByteBuffer _intShifter = ByteBuffer.allocate(Integer.SIZE / Byte.SIZE)
                                   .order(ByteOrder.LITTLE_ENDIAN);

public byte[] intToByte(int value) {
    _intShifter.clear();
    _intShifter.putInt(value);      
    return _intShifter.array();
}

public int byteToInt(byte[] data)
{
    _intShifter.clear();
    _intShifter.put(data, 0, Integer.SIZE / Byte.SIZE);
    _intShifter.flip();
    return _intShifter.getInt();
}

/*对不起,这是正确的*/

     public byte[] IntArrayToByteArray(int[] iarray , int sizeofintarray)
     {
       final ByteBuffer bb ;
       bb = ByteBuffer.allocate( sizeofintarray * 4);
       for(int k = 0; k < sizeofintarray ; k++)
       bb.putInt(k * 4, iar[k]);
       return bb.array();
     }
IntArrayToByteArray中的公共字节[](int[]iarray,int-sizeofintarray)
{
最终ByteBuffer bb;
bb=字节缓冲区分配(sizeofintarray*4);
对于(int k=0;k
我在[Maven:com.google.guava:guava:12.0.1]中的com.google.common.primitives中找到了一种简单的方法

long newLong = Longs.fromByteArray(oldLongByteArray);
int newInt = Ints.fromByteArray(oldIntByteArray);

尝试一下:)

而不是分配空间,等等,使用
java.nio
中的
ByteBuffer
的方法

byte[] arr = { 0x01, 0x00, 0x00, 0x00, 0x48, 0x01};

// say we want to consider indices 1, 2, 3, 4 {0x00, 0x00, 0x00, 0x48};
ByteBuffer bf = ByteBuffer.wrap(arr, 1, 4); // big endian by default
int num = bf.getInt();    // 72
现在,我要走另一条路

ByteBuffer newBuf = ByteBuffer.allocate(4);
newBuf.putInt(num);
byte[] bytes = newBuf.array();  // [0, 0, 0, 72] {0x48 = 72}

尝试删除
byteArrayToInt
中的循环。显然,它会循环…不是手工制作的:)-1,这将返回与要求不同的结果(它返回的是最小字节数,而不是4个字节)。此外,使用BigInteger对于这种用途来说有点重。虽然没有我预期的那么糟糕,但比优化版本只慢20倍:),我必须承认,我的速度并没有那么快。一行代码:
byte[]result=ByteBuffer.allocate(Integer.SIZE/byte.SIZE).order(ByteOrder.LITTLE_ENDIAN.putInt(I).array()
好的,与Yanick就性能进行了一次有趣的讨论,因此我使用Yanick的答案(向上投票)添加了一个性能增强版作为基础。最重要的变化当然是删除了
for循环,因为当前CPU上的分支速度很慢。因此它的速度至少是当前CPU的两倍。短版本和性能版本之间是否存在不一致?排序版本适用于小端,性能版本适用于大端?@RenniePet啊,是的,应该说得更清楚。我稍后会添加性能版本的LE版本。从
byteArrayToLeInt
的性能版本中,您为什么不和
encodedValue[3]
by
0xff
?看看
ByteBuffer类
,我已经围绕它创建了一个示例。@owlstead,是的,您的代码最好将
字节[]
转换为
int[]
,但是对于
字节
int
的独立转换,使用直接位操作(尤其是当您知道并期望正确形成定义的数据时)比创建一个类的实例来为每个调用执行完全相同的操作快得多。即使缓存一个
ByteBuffer
的实例,您仍然需要将传递的字节复制到缓冲区的数组中,因此在任何情况下都会给您带来一些开销。@owlstead,也许,但是如果您可以从一开始就优化一个方法,并且
byte[] arr = { 0x01, 0x00, 0x00, 0x00, 0x48, 0x01};

// say we want to consider indices 1, 2, 3, 4 {0x00, 0x00, 0x00, 0x48};
ByteBuffer bf = ByteBuffer.wrap(arr, 1, 4); // big endian by default
int num = bf.getInt();    // 72
ByteBuffer newBuf = ByteBuffer.allocate(4);
newBuf.putInt(num);
byte[] bytes = newBuf.array();  // [0, 0, 0, 72] {0x48 = 72}