diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/compress/OpcZipOutputStream.java b/hutool-core/src/main/java/org/dromara/hutool/core/compress/OpcZipOutputStream.java new file mode 100644 index 000000000..4792f4727 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/compress/OpcZipOutputStream.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.compress; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.zip.*; + +/** + * Excel兼容的ZIP64 OutputStream实现
+ * 来自并见: https://github.com/rzymek/opczip + * + * @author rzymek + */ +public class OpcZipOutputStream extends ZipOutputStream { + + private final Zip64 spec; + private final List entries = new ArrayList<>(); + private final CRC32 crc = new CRC32(); + private Zip64.Entry current; + private int written = 0; + private boolean finished = false; + + /** + * 构造 + * + * @param out 写出压缩数据额输出流 + */ + public OpcZipOutputStream(final OutputStream out) { + super(out); + this.spec = new Zip64(out); + } + + @Override + public void putNextEntry(final ZipEntry e) throws IOException { + if (current != null) { + closeEntry(); + } + current = new Zip64.Entry(e.getName()); + current.offset = written; + written += spec.writeLFH(current); + entries.add(current); + } + + @Override + public void closeEntry() throws IOException { + if (current == null) { + throw new IllegalStateException("not current zip current"); + } + def.finish(); + while (!def.finished()) { + deflate(); + } + + current.size = def.getBytesRead(); + current.compressedSize = (int) def.getBytesWritten(); + current.crc = crc.getValue(); + + written += current.compressedSize; + written += spec.writeDAT(current); + current = null; + def.reset(); + crc.reset(); + } + + @Override + public void finish() throws IOException { + if (finished) { + return; + } + if (current != null) { + closeEntry(); + } + final int offset = written; + for (final Zip64.Entry entry : entries) { + written += spec.writeCEN(entry); + } + written += spec.writeEND(entries.size(), offset, written - offset); + finished = true; + } + + /** + * @see ZipOutputStream#write(byte[], int, int) + */ + @Override + public synchronized void write(final byte[] b, final int off, final int len) throws IOException { + if (off < 0 || len < 0 || off > b.length - len) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return; + } + super.write(b, off, len); + crc.update(b, off, len); + } + + @Override + public void close() throws IOException { + finish(); + out.close(); + } +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/compress/Zip64.java b/hutool-core/src/main/java/org/dromara/hutool/core/compress/Zip64.java new file mode 100644 index 000000000..6cada80c4 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/compress/Zip64.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2024. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.compress; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.zip.ZipEntry; + +import static java.nio.charset.StandardCharsets.US_ASCII; + +/** + * Excel 兼容的 Zip64 实现
+ * 来自并见: https://github.com/rzymek/opczip + * + * @author rzymek + */ +class Zip64 { + private static final long PK0102 = 0x02014b50L; + private static final long PK0304 = 0x04034b50L; + private static final long PK0506 = 0x06054b50L; + private static final long PK0708 = 0x08074b50L; + + private static final int VERSION_20 = 20; + private static final int VERSION_45 = 45; + private static final int DATA_DESCRIPTOR_USED = 0x08; + private static final int ZIP64_FIELD = 0x0001; + private static final long MAX32 = 0xffffffffL; + + private final OutputStream out; + private int written = 0; + + static class Entry { + final String filename; + long crc; + long size; + int compressedSize; + int offset; + + Entry(final String filename) { + this.filename = filename; + } + } + + /** + * 构造 + * + * @param out 输出流 + */ + Zip64(final OutputStream out) { + this.out = out; + } + + /** + * Write Local File Header + */ + int writeLFH(final Entry entry) throws IOException { + written = 0; + writeInt(PK0304); // "PK\003\004" + writeShort(VERSION_45); // version required: 4.5 + writeShort(DATA_DESCRIPTOR_USED); // flags: 8 = data descriptor used + writeShort(ZipEntry.DEFLATED); // compression method: 8 = deflate + writeInt(0); // file modification time & date + writeInt(entry.crc); // CRC-32 + writeInt(0); // compressed file size + writeInt(0); // uncompressed file size + writeShort(entry.filename.length()); // filename length + writeShort(0); // extra flags size + final byte[] filenameBytes = entry.filename.getBytes(US_ASCII); + out.write(filenameBytes); // filename characters + return written + filenameBytes.length; + } + + /** + * Write Data Descriptor + */ + int writeDAT(final Entry entry) throws IOException { + written = 0; + writeInt(PK0708); // data descriptor signature "PK\007\008" + writeInt(entry.crc); // crc-32 + writeLong(entry.compressedSize); // compressed size (zip64) + writeLong(entry.size); // uncompressed size (zip64) + return written; + } + + /** + * Write Central directory file header + */ + int writeCEN(final Entry entry) throws IOException { + written = 0; + final boolean useZip64 = entry.size > MAX32; + writeInt(PK0102); // "PK\001\002" + writeShort(VERSION_45); // version made by: 4.5 + writeShort(useZip64 ? VERSION_45 : VERSION_20);// version required: 4.5 + writeShort(DATA_DESCRIPTOR_USED); // flags: 8 = data descriptor used + writeShort(ZipEntry.DEFLATED); // compression method: 8 = deflate + writeInt(0); // file modification time & date + writeInt(entry.crc); // CRC-32 + writeInt(entry.compressedSize); // compressed size + writeInt(useZip64 ? MAX32 : entry.size); // uncompressed size + writeShort(entry.filename.length()); // filename length + writeShort(useZip64 + ? (2 + 2 + 8) /* short + short + long*/ + : 0); // extra field len + writeShort(0); // comment length + writeShort(0); // disk number where file starts + writeShort(0); // internal file attributes (unused) + writeInt(0); // external file attributes (unused) + writeInt(entry.offset); // LFH offset + final byte[] filenameBytes = entry.filename.getBytes(US_ASCII); + out.write(filenameBytes); // filename characters + if (useZip64) { + // Extra field: + writeShort(ZIP64_FIELD); // ZIP64 field signature + writeShort(8); // size of extra field (below) + writeLong(entry.size); // uncompressed size + } + return written + filenameBytes.length; + } + + /** + * Write End of central directory record (EOCD) + */ + int writeEND(final int entriesCount, final int offset, final int length) throws IOException { + written = 0; + writeInt(PK0506); // "PK\005\006" + writeShort(0); // number of this disk + writeShort(0); // central directory start disk + writeShort(entriesCount); // number of directory entries on disk + writeShort(entriesCount); // total number of directory entries + writeInt(length); // length of central directory + writeInt(offset); // offset of central directory + writeShort(0); // comment length + return written; + } + + /** + * Writes a 16-bit short to the output stream in little-endian byte order. + */ + private void writeShort(final int v) throws IOException { + final OutputStream out = this.out; + out.write((v) & 0xff); + out.write((v >>> 8) & 0xff); + written += 2; + } + + /** + * Writes a 32-bit int to the output stream in little-endian byte order. + */ + private void writeInt(final long v) throws IOException { + final OutputStream out = this.out; + out.write((int) ((v) & 0xff)); + out.write((int) ((v >>> 8) & 0xff)); + out.write((int) ((v >>> 16) & 0xff)); + out.write((int) ((v >>> 24) & 0xff)); + written += 4; + } + + /** + * Writes a 64-bit int to the output stream in little-endian byte order. + */ + private void writeLong(final long v) throws IOException { + final OutputStream out = this.out; + out.write((int) ((v) & 0xff)); + out.write((int) ((v >>> 8) & 0xff)); + out.write((int) ((v >>> 16) & 0xff)); + out.write((int) ((v >>> 24) & 0xff)); + out.write((int) ((v >>> 32) & 0xff)); + out.write((int) ((v >>> 40) & 0xff)); + out.write((int) ((v >>> 48) & 0xff)); + out.write((int) ((v >>> 56) & 0xff)); + written += 8; + } + +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/ByteUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/util/ByteUtil.java index 8238a2a82..1798bb6f9 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/util/ByteUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/util/ByteUtil.java @@ -145,24 +145,26 @@ public class ByteUtil { * @return byte数组 */ public static byte[] toBytes(final int intValue, final ByteOrder byteOrder) { + return fill(intValue, 0, byteOrder, new byte[Integer.BYTES]); + } - if (ByteOrder.LITTLE_ENDIAN == byteOrder) { - return new byte[]{ // - (byte) (intValue & 0xFF), // - (byte) ((intValue >> 8) & 0xFF), // - (byte) ((intValue >> 16) & 0xFF), // - (byte) ((intValue >> 24) & 0xFF) // - }; - - } else { - return new byte[]{ // - (byte) ((intValue >> 24) & 0xFF), // - (byte) ((intValue >> 16) & 0xFF), // - (byte) ((intValue >> 8) & 0xFF), // - (byte) (intValue & 0xFF) // - }; + /** + * 将int值转为bytes并填充到给定的bytes中 + * + * @param intValue int值 + * @param start 开始位置(包含) + * @param byteOrder 端续 + * @param bytes 被填充的bytes + * @return 填充后的bytes + * @since 6.0.0 + */ + public static byte[] fill(int intValue, final int start, final ByteOrder byteOrder, final byte[] bytes) { + final int offset = (ByteOrder.LITTLE_ENDIAN == byteOrder) ? 0 : (bytes.length - 1); + for (int i = start; i < bytes.length; i++) { + bytes[Math.abs(i - offset)] = (byte) (intValue & 0xFF); + intValue >>= Byte.SIZE; } - + return bytes; } /** @@ -202,16 +204,10 @@ public class ByteUtil { * @since 6.0.0 */ public static byte[] fill(long longValue, final int start, final ByteOrder byteOrder, final byte[] bytes) { - if (ByteOrder.LITTLE_ENDIAN == byteOrder) { - for (int i = start; i < bytes.length; i++) { - bytes[i] = (byte) (longValue & 0xFF); - longValue >>= Byte.SIZE; - } - } else { - for (int i = (bytes.length - 1); i >= start; i--) { - bytes[i] = (byte) (longValue & 0xFF); - longValue >>= Byte.SIZE; - } + final int offset = (ByteOrder.LITTLE_ENDIAN == byteOrder) ? 0 : (bytes.length - 1); + for (int i = start; i < bytes.length; i++) { + bytes[Math.abs(i - offset)] = (byte) (longValue & 0xFF); + longValue >>= Byte.SIZE; } return bytes; } @@ -379,17 +375,23 @@ public class ByteUtil { * @since 5.7.21 */ public static int toInt(final byte[] bytes, final int start, final ByteOrder byteOrder) { - if (ByteOrder.LITTLE_ENDIAN == byteOrder) { - return bytes[start] & 0xFF | // - (bytes[1 + start] & 0xFF) << 8 | // - (bytes[2 + start] & 0xFF) << 16 | // - (bytes[3 + start] & 0xFF) << 24; // - } else { - return bytes[3 + start] & 0xFF | // - (bytes[2 + start] & 0xFF) << 8 | // - (bytes[1 + start] & 0xFF) << 16 | // - (bytes[start] & 0xFF) << 24; // + if(bytes.length - start < Integer.BYTES){ + throw new IllegalArgumentException("bytes length must be greater than or equal to " + Long.BYTES); } + + int values = 0; + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + for (int i = (Integer.BYTES - 1); i >= 0; i--) { + values <<= Byte.SIZE; + values |= (bytes[i + start] & 0xFF); + } + } else { + for (int i = 0; i < Integer.BYTES; i++) { + values <<= Byte.SIZE; + values |= (bytes[i + start] & 0xFF); + } + } + return values; } /** @@ -443,6 +445,9 @@ public class ByteUtil { * @since 5.7.21 */ public static long toLong(final byte[] bytes, final int start, final ByteOrder byteOrder) { + if(bytes.length - start < Long.BYTES){ + throw new IllegalArgumentException("bytes length must be greater than or equal to " + Long.BYTES); + } long values = 0; if (ByteOrder.LITTLE_ENDIAN == byteOrder) { for (int i = (Long.BYTES - 1); i >= 0; i--) { diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/util/CharsetUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/util/CharsetUtil.java index 93de61356..829cbf447 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/util/CharsetUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/util/CharsetUtil.java @@ -28,6 +28,10 @@ import java.nio.charset.*; */ public class CharsetUtil { + /** + * US_ASCII + */ + public static final String NAME_US_ASCII = "US_ASCII"; /** * ISO-8859-1 */ @@ -41,6 +45,10 @@ public class CharsetUtil { */ public static final String NAME_GBK = "GBK"; + /** + * US_ASCII + */ + public static final Charset US_ASCII = StandardCharsets.US_ASCII; /** * ISO-8859-1 */ diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/util/ByteUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/util/ByteUtilTest.java index d611c9ea5..aaf34398a 100644 --- a/hutool-core/src/test/java/org/dromara/hutool/core/util/ByteUtilTest.java +++ b/hutool-core/src/test/java/org/dromara/hutool/core/util/ByteUtilTest.java @@ -12,13 +12,15 @@ package org.dromara.hutool.core.util; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.List; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ByteUtilTest { @Test public void intAndBytesLittleEndianTest() { @@ -31,18 +33,18 @@ public class ByteUtilTest { final byte[] bytesIntFromBuffer = buffer.array(); final byte[] bytesInt = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN); - Assertions.assertArrayEquals(bytesIntFromBuffer, bytesInt); + assertArrayEquals(bytesIntFromBuffer, bytesInt); final int int2 = ByteUtil.toInt(bytesInt, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(int1, int2); + assertEquals(int1, int2); final byte[] bytesInt2 = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN); final int int3 = ByteUtil.toInt(bytesInt2, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(int1, int3); + assertEquals(int1, int3); final byte[] bytesInt3 = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN); final int int4 = ByteUtil.toInt(bytesInt3, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(int1, int4); + assertEquals(int1, int4); } @Test @@ -55,11 +57,11 @@ public class ByteUtilTest { final byte[] bytesIntFromBuffer = buffer.array(); final byte[] bytesInt = ByteUtil.toBytes(int2, ByteOrder.BIG_ENDIAN); - Assertions.assertArrayEquals(bytesIntFromBuffer, bytesInt); + assertArrayEquals(bytesIntFromBuffer, bytesInt); // 测试大端序 byte 数组转 int final int int3 = ByteUtil.toInt(bytesInt, ByteOrder.BIG_ENDIAN); - Assertions.assertEquals(int2, int3); + assertEquals(int2, int3); } @Test @@ -73,18 +75,18 @@ public class ByteUtilTest { final byte[] bytesLongFromBuffer = buffer.array(); final byte[] bytesLong = ByteUtil.toBytes(long1, ByteOrder.LITTLE_ENDIAN); - Assertions.assertArrayEquals(bytesLongFromBuffer, bytesLong); + assertArrayEquals(bytesLongFromBuffer, bytesLong); final long long2 = ByteUtil.toLong(bytesLong, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(long1, long2); + assertEquals(long1, long2); final byte[] bytesLong2 = ByteUtil.toBytes(long1); final long long3 = ByteUtil.toLong(bytesLong2, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(long1, long3); + assertEquals(long1, long3); final byte[] bytesLong3 = ByteUtil.toBytes(long1, ByteOrder.LITTLE_ENDIAN); final long long4 = ByteUtil.toLong(bytesLong3); - Assertions.assertEquals(long1, long4); + assertEquals(long1, long4); } @Test @@ -97,10 +99,10 @@ public class ByteUtilTest { final byte[] bytesLongFromBuffer = buffer.array(); final byte[] bytesLong = ByteUtil.toBytes(long1, ByteOrder.BIG_ENDIAN); - Assertions.assertArrayEquals(bytesLongFromBuffer, bytesLong); + assertArrayEquals(bytesLongFromBuffer, bytesLong); final long long2 = ByteUtil.toLong(bytesLong, ByteOrder.BIG_ENDIAN); - Assertions.assertEquals(long1, long2); + assertEquals(long1, long2); } @Test @@ -110,7 +112,7 @@ public class ByteUtilTest { final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.LITTLE_ENDIAN); final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(f1, f2, 0); + assertEquals(f1, f2, 0); } @Test @@ -121,7 +123,7 @@ public class ByteUtilTest { final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.BIG_ENDIAN); final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.BIG_ENDIAN); - Assertions.assertEquals(f1, f2, 0); + assertEquals(f1, f2, 0); } @Test @@ -130,15 +132,15 @@ public class ByteUtilTest { final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.LITTLE_ENDIAN); final short short2 = ByteUtil.toShort(bytes, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(short2, short1); + assertEquals(short2, short1); final byte[] bytes2 = ByteUtil.toBytes(short1); final short short3 = ByteUtil.toShort(bytes2, ByteOrder.LITTLE_ENDIAN); - Assertions.assertEquals(short3, short1); + assertEquals(short3, short1); final byte[] bytes3 = ByteUtil.toBytes(short1, ByteOrder.LITTLE_ENDIAN); final short short4 = ByteUtil.toShort(bytes3); - Assertions.assertEquals(short4, short1); + assertEquals(short4, short1); } @Test @@ -147,7 +149,7 @@ public class ByteUtilTest { final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.BIG_ENDIAN); final short short2 = ByteUtil.toShort(bytes, ByteOrder.BIG_ENDIAN); - Assertions.assertEquals(short2, short1); + assertEquals(short2, short1); } @Test @@ -156,12 +158,12 @@ public class ByteUtilTest { ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a)); wrap.order(ByteOrder.LITTLE_ENDIAN); long aLong = wrap.getLong(); - Assertions.assertEquals(a, aLong); + assertEquals(a, aLong); wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN)); wrap.order(ByteOrder.BIG_ENDIAN); aLong = wrap.getLong(); - Assertions.assertEquals(a, aLong); + assertEquals(a, aLong); } @Test @@ -170,12 +172,12 @@ public class ByteUtilTest { ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a)); wrap.order(ByteOrder.LITTLE_ENDIAN); int aInt = wrap.getInt(); - Assertions.assertEquals(a, aInt); + assertEquals(a, aInt); wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN)); wrap.order(ByteOrder.BIG_ENDIAN); aInt = wrap.getInt(); - Assertions.assertEquals(a, aInt); + assertEquals(a, aInt); } @Test @@ -185,25 +187,43 @@ public class ByteUtilTest { ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a)); wrap.order(ByteOrder.LITTLE_ENDIAN); short aShort = wrap.getShort(); - Assertions.assertEquals(a, aShort); + assertEquals(a, aShort); wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN)); wrap.order(ByteOrder.BIG_ENDIAN); aShort = wrap.getShort(); - Assertions.assertEquals(a, aShort); + assertEquals(a, aShort); } @Test public void toUnsignedBitIndex() { final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64}; final List list = ByteUtil.toUnsignedBitIndex(bytes); - Assertions.assertEquals("[12, 13, 15, 16, 17, 24, 25, 26, 31, 33, 34, 37, 39, 41, 43, 44, 50, 52, 53, 54, 55, 56, 57]", list.toString()); + assertEquals("[12, 13, 15, 16, 17, 24, 25, 26, 31, 33, 34, 37, 39, 41, 43, 44, 50, 52, 53, 54, 55, 56, 57]", list.toString()); } @Test public void bitCount() { final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64}; final int count = ByteUtil.bitCount(bytes); - Assertions.assertEquals(count, ByteUtil.toUnsignedBitIndex(bytes).size()); + assertEquals(count, ByteUtil.toUnsignedBitIndex(bytes).size()); + } + + @Test + public void testToIntWithLittleEndian() { + // 小端序:低位字节在前,高位字节在后 + final byte[] bytes = new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0x01, (byte) 0x00}; + final int expectedValue = 130815; + final int actualValue = ByteUtil.toInt(bytes, 0, ByteOrder.LITTLE_ENDIAN); + assertEquals(expectedValue, actualValue, "Failed to convert bytes to int using LITTLE_ENDIAN"); + } + + @Test + public void testToIntWithBigEndian() { + // 大端序:高位字节在前,低位字节在后 + final byte[] bytes = new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0x01, (byte) 0x00}; + final int expectedValue = -130816; + final int actualValue = ByteUtil.toInt(bytes, 0, ByteOrder.BIG_ENDIAN); + assertEquals(expectedValue, actualValue, "Failed to convert bytes to int using BIG_ENDIAN"); } }