Java中的Byte Array和Int转换

我有这两个函数有一些困难: byteArrayToIntintToByteArray

问题是,如果我使用另一个来得到另一个结果,结果是不同的,你可以从我的下面的例子看到。

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

 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; } 

你在两种方法之间交换sorting 。 您有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 int byteArrayToInt(byte[] b) { return b[3] & 0xFF | (b[2] & 0xFF) << 8 | (b[1] & 0xFF) << 16 | (b[0] & 0xFF) << 24; } public static byte[] intToByteArray(int a) { return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF), (byte) (a & 0xFF) }; } 

这些方法用以下代码进行testing:

 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!"); 

这是很多工作:

 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.nio包中的Java ByteBufferByteOrderfunction。 在需要可读性的情况下,应该首选此代码。 它也应该很容易记住。

我已经在这里显示Little Endian字节顺序。 要创build一个Big Endian版本,您可以简单地忽略调用order(ByteOrder)


在性能比可读性更高的代码中(大约是速度的10倍):

 public static int byteArrayToLeInt(byte[] encodedValue) { int value = (encodedValue[3] << (Byte.SIZE * 3)); value |= (encodedValue[2] & 0xFF) << (Byte.SIZE * 2); value |= (encodedValue[1] & 0xFF) << (Byte.SIZE * 1); value |= (encodedValue[0] & 0xFF); return value; } public static byte[] leIntToByteArray(int value) { byte[] encodedValue = new byte[Integer.SIZE / Byte.SIZE]; encodedValue[3] = (byte) (value >> Byte.SIZE * 3); encodedValue[2] = (byte) (value >> Byte.SIZE * 2); encodedValue[1] = (byte) (value >> Byte.SIZE); encodedValue[0] = (byte) value; return encodedValue; } 

只需将字节数组索引从零计数到三就可以创build此代码的Big Endian版本。


笔记:

  • 在Java 8中,您还可以使用Integer.SIZE / Byte.SIZE更简洁的Integer.SIZE / Byte.SIZE

您也可以使用BigInteger获取可变长度的字节。 您可以将其转换为Long,Integer或Short,以适合您的需求。

 new BigInteger(bytes).intValue(); 

或表示极性:

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

只需要返回字节:

 new BigInteger(bytes).toByteArray() 

我喜欢owlstead的原始答案,如果您不喜欢在每个方法调用上创buildByteBuffer的想法,那么可以通过调用它的.clear().flip()方法来重用ByteBuffer

 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(); } 

我在com.google.common.primitives中find了一个简单的方法,它位于[Maven:com.google.guava:guava:12.0.1]

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

有一个不错的尝试:)

我花了很长时间看了很多这样的问题,并发现这个post …我不喜欢这样的事实,每个types的转换代码是重复的,所以我做了一个通用的方法来执行任务:

 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; } 

看完整的post 。

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

  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(); } 

而不是分配空间等,使用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} 

这里是我的实现

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