mirror of
https://gitee.com/dromara/hutool.git
synced 2025-04-24 18:04:54 +08:00
add OpcZipOutputStream
This commit is contained in:
parent
3dc61bd27c
commit
191d6030ac
@ -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实现<br>
|
||||||
|
* 来自并见: https://github.com/rzymek/opczip
|
||||||
|
*
|
||||||
|
* @author rzymek
|
||||||
|
*/
|
||||||
|
public class OpcZipOutputStream extends ZipOutputStream {
|
||||||
|
|
||||||
|
private final Zip64 spec;
|
||||||
|
private final List<Zip64.Entry> 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();
|
||||||
|
}
|
||||||
|
}
|
@ -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 实现<br>
|
||||||
|
* 来自并见: 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -145,24 +145,26 @@ public class ByteUtil {
|
|||||||
* @return byte数组
|
* @return byte数组
|
||||||
*/
|
*/
|
||||||
public static byte[] toBytes(final int intValue, final ByteOrder byteOrder) {
|
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[]{ //
|
* 将int值转为bytes并填充到给定的bytes中
|
||||||
(byte) (intValue & 0xFF), //
|
*
|
||||||
(byte) ((intValue >> 8) & 0xFF), //
|
* @param intValue int值
|
||||||
(byte) ((intValue >> 16) & 0xFF), //
|
* @param start 开始位置(包含)
|
||||||
(byte) ((intValue >> 24) & 0xFF) //
|
* @param byteOrder 端续
|
||||||
};
|
* @param bytes 被填充的bytes
|
||||||
|
* @return 填充后的bytes
|
||||||
} else {
|
* @since 6.0.0
|
||||||
return new byte[]{ //
|
*/
|
||||||
(byte) ((intValue >> 24) & 0xFF), //
|
public static byte[] fill(int intValue, final int start, final ByteOrder byteOrder, final byte[] bytes) {
|
||||||
(byte) ((intValue >> 16) & 0xFF), //
|
final int offset = (ByteOrder.LITTLE_ENDIAN == byteOrder) ? 0 : (bytes.length - 1);
|
||||||
(byte) ((intValue >> 8) & 0xFF), //
|
for (int i = start; i < bytes.length; i++) {
|
||||||
(byte) (intValue & 0xFF) //
|
bytes[Math.abs(i - offset)] = (byte) (intValue & 0xFF);
|
||||||
};
|
intValue >>= Byte.SIZE;
|
||||||
}
|
}
|
||||||
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -202,16 +204,10 @@ public class ByteUtil {
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public static byte[] fill(long longValue, final int start, final ByteOrder byteOrder, final byte[] bytes) {
|
public static byte[] fill(long longValue, final int start, final ByteOrder byteOrder, final byte[] bytes) {
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
final int offset = (ByteOrder.LITTLE_ENDIAN == byteOrder) ? 0 : (bytes.length - 1);
|
||||||
for (int i = start; i < bytes.length; i++) {
|
for (int i = start; i < bytes.length; i++) {
|
||||||
bytes[i] = (byte) (longValue & 0xFF);
|
bytes[Math.abs(i - offset)] = (byte) (longValue & 0xFF);
|
||||||
longValue >>= Byte.SIZE;
|
longValue >>= Byte.SIZE;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = (bytes.length - 1); i >= start; i--) {
|
|
||||||
bytes[i] = (byte) (longValue & 0xFF);
|
|
||||||
longValue >>= Byte.SIZE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
@ -379,17 +375,23 @@ public class ByteUtil {
|
|||||||
* @since 5.7.21
|
* @since 5.7.21
|
||||||
*/
|
*/
|
||||||
public static int toInt(final byte[] bytes, final int start, final ByteOrder byteOrder) {
|
public static int toInt(final byte[] bytes, final int start, final ByteOrder byteOrder) {
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
if(bytes.length - start < Integer.BYTES){
|
||||||
return bytes[start] & 0xFF | //
|
throw new IllegalArgumentException("bytes length must be greater than or equal to " + Long.BYTES);
|
||||||
(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; //
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
* @since 5.7.21
|
||||||
*/
|
*/
|
||||||
public static long toLong(final byte[] bytes, final int start, final ByteOrder byteOrder) {
|
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;
|
long values = 0;
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
for (int i = (Long.BYTES - 1); i >= 0; i--) {
|
for (int i = (Long.BYTES - 1); i >= 0; i--) {
|
||||||
|
@ -28,6 +28,10 @@ import java.nio.charset.*;
|
|||||||
*/
|
*/
|
||||||
public class CharsetUtil {
|
public class CharsetUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* US_ASCII
|
||||||
|
*/
|
||||||
|
public static final String NAME_US_ASCII = "US_ASCII";
|
||||||
/**
|
/**
|
||||||
* ISO-8859-1
|
* ISO-8859-1
|
||||||
*/
|
*/
|
||||||
@ -41,6 +45,10 @@ public class CharsetUtil {
|
|||||||
*/
|
*/
|
||||||
public static final String NAME_GBK = "GBK";
|
public static final String NAME_GBK = "GBK";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* US_ASCII
|
||||||
|
*/
|
||||||
|
public static final Charset US_ASCII = StandardCharsets.US_ASCII;
|
||||||
/**
|
/**
|
||||||
* ISO-8859-1
|
* ISO-8859-1
|
||||||
*/
|
*/
|
||||||
|
@ -12,13 +12,15 @@
|
|||||||
|
|
||||||
package org.dromara.hutool.core.util;
|
package org.dromara.hutool.core.util;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class ByteUtilTest {
|
public class ByteUtilTest {
|
||||||
@Test
|
@Test
|
||||||
public void intAndBytesLittleEndianTest() {
|
public void intAndBytesLittleEndianTest() {
|
||||||
@ -31,18 +33,18 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytesIntFromBuffer = buffer.array();
|
final byte[] bytesIntFromBuffer = buffer.array();
|
||||||
|
|
||||||
final byte[] bytesInt = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN);
|
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);
|
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 byte[] bytesInt2 = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final int int3 = ByteUtil.toInt(bytesInt2, 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 byte[] bytesInt3 = ByteUtil.toBytes(int1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final int int4 = ByteUtil.toInt(bytesInt3, ByteOrder.LITTLE_ENDIAN);
|
final int int4 = ByteUtil.toInt(bytesInt3, ByteOrder.LITTLE_ENDIAN);
|
||||||
Assertions.assertEquals(int1, int4);
|
assertEquals(int1, int4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -55,11 +57,11 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytesIntFromBuffer = buffer.array();
|
final byte[] bytesIntFromBuffer = buffer.array();
|
||||||
|
|
||||||
final byte[] bytesInt = ByteUtil.toBytes(int2, ByteOrder.BIG_ENDIAN);
|
final byte[] bytesInt = ByteUtil.toBytes(int2, ByteOrder.BIG_ENDIAN);
|
||||||
Assertions.assertArrayEquals(bytesIntFromBuffer, bytesInt);
|
assertArrayEquals(bytesIntFromBuffer, bytesInt);
|
||||||
|
|
||||||
// 测试大端序 byte 数组转 int
|
// 测试大端序 byte 数组转 int
|
||||||
final int int3 = ByteUtil.toInt(bytesInt, ByteOrder.BIG_ENDIAN);
|
final int int3 = ByteUtil.toInt(bytesInt, ByteOrder.BIG_ENDIAN);
|
||||||
Assertions.assertEquals(int2, int3);
|
assertEquals(int2, int3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -73,18 +75,18 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytesLongFromBuffer = buffer.array();
|
final byte[] bytesLongFromBuffer = buffer.array();
|
||||||
|
|
||||||
final byte[] bytesLong = ByteUtil.toBytes(long1, ByteOrder.LITTLE_ENDIAN);
|
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);
|
final long long2 = ByteUtil.toLong(bytesLong, ByteOrder.LITTLE_ENDIAN);
|
||||||
Assertions.assertEquals(long1, long2);
|
assertEquals(long1, long2);
|
||||||
|
|
||||||
final byte[] bytesLong2 = ByteUtil.toBytes(long1);
|
final byte[] bytesLong2 = ByteUtil.toBytes(long1);
|
||||||
final long long3 = ByteUtil.toLong(bytesLong2, ByteOrder.LITTLE_ENDIAN);
|
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 byte[] bytesLong3 = ByteUtil.toBytes(long1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final long long4 = ByteUtil.toLong(bytesLong3);
|
final long long4 = ByteUtil.toLong(bytesLong3);
|
||||||
Assertions.assertEquals(long1, long4);
|
assertEquals(long1, long4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -97,10 +99,10 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytesLongFromBuffer = buffer.array();
|
final byte[] bytesLongFromBuffer = buffer.array();
|
||||||
|
|
||||||
final byte[] bytesLong = ByteUtil.toBytes(long1, ByteOrder.BIG_ENDIAN);
|
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);
|
final long long2 = ByteUtil.toLong(bytesLong, ByteOrder.BIG_ENDIAN);
|
||||||
Assertions.assertEquals(long1, long2);
|
assertEquals(long1, long2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -110,7 +112,7 @@ public class ByteUtilTest {
|
|||||||
|
|
||||||
final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.LITTLE_ENDIAN);
|
final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.LITTLE_ENDIAN);
|
final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.LITTLE_ENDIAN);
|
||||||
Assertions.assertEquals(f1, f2, 0);
|
assertEquals(f1, f2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -121,7 +123,7 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.BIG_ENDIAN);
|
final byte[] bytesLong = ByteUtil.toBytes(f1, ByteOrder.BIG_ENDIAN);
|
||||||
final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.BIG_ENDIAN);
|
final float f2 = ByteUtil.toFloat(bytesLong, ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
Assertions.assertEquals(f1, f2, 0);
|
assertEquals(f1, f2, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -130,15 +132,15 @@ public class ByteUtilTest {
|
|||||||
|
|
||||||
final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.LITTLE_ENDIAN);
|
final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final short short2 = ByteUtil.toShort(bytes, 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 byte[] bytes2 = ByteUtil.toBytes(short1);
|
||||||
final short short3 = ByteUtil.toShort(bytes2, ByteOrder.LITTLE_ENDIAN);
|
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 byte[] bytes3 = ByteUtil.toBytes(short1, ByteOrder.LITTLE_ENDIAN);
|
||||||
final short short4 = ByteUtil.toShort(bytes3);
|
final short short4 = ByteUtil.toShort(bytes3);
|
||||||
Assertions.assertEquals(short4, short1);
|
assertEquals(short4, short1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -147,7 +149,7 @@ public class ByteUtilTest {
|
|||||||
final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.BIG_ENDIAN);
|
final byte[] bytes = ByteUtil.toBytes(short1, ByteOrder.BIG_ENDIAN);
|
||||||
final short short2 = ByteUtil.toShort(bytes, ByteOrder.BIG_ENDIAN);
|
final short short2 = ByteUtil.toShort(bytes, ByteOrder.BIG_ENDIAN);
|
||||||
|
|
||||||
Assertions.assertEquals(short2, short1);
|
assertEquals(short2, short1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -156,12 +158,12 @@ public class ByteUtilTest {
|
|||||||
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
||||||
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
long aLong = wrap.getLong();
|
long aLong = wrap.getLong();
|
||||||
Assertions.assertEquals(a, aLong);
|
assertEquals(a, aLong);
|
||||||
|
|
||||||
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
||||||
wrap.order(ByteOrder.BIG_ENDIAN);
|
wrap.order(ByteOrder.BIG_ENDIAN);
|
||||||
aLong = wrap.getLong();
|
aLong = wrap.getLong();
|
||||||
Assertions.assertEquals(a, aLong);
|
assertEquals(a, aLong);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -170,12 +172,12 @@ public class ByteUtilTest {
|
|||||||
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
||||||
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
int aInt = wrap.getInt();
|
int aInt = wrap.getInt();
|
||||||
Assertions.assertEquals(a, aInt);
|
assertEquals(a, aInt);
|
||||||
|
|
||||||
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
||||||
wrap.order(ByteOrder.BIG_ENDIAN);
|
wrap.order(ByteOrder.BIG_ENDIAN);
|
||||||
aInt = wrap.getInt();
|
aInt = wrap.getInt();
|
||||||
Assertions.assertEquals(a, aInt);
|
assertEquals(a, aInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -185,25 +187,43 @@ public class ByteUtilTest {
|
|||||||
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
ByteBuffer wrap = ByteBuffer.wrap(ByteUtil.toBytes(a));
|
||||||
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
wrap.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
short aShort = wrap.getShort();
|
short aShort = wrap.getShort();
|
||||||
Assertions.assertEquals(a, aShort);
|
assertEquals(a, aShort);
|
||||||
|
|
||||||
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
wrap = ByteBuffer.wrap(ByteUtil.toBytes(a, ByteOrder.BIG_ENDIAN));
|
||||||
wrap.order(ByteOrder.BIG_ENDIAN);
|
wrap.order(ByteOrder.BIG_ENDIAN);
|
||||||
aShort = wrap.getShort();
|
aShort = wrap.getShort();
|
||||||
Assertions.assertEquals(a, aShort);
|
assertEquals(a, aShort);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void toUnsignedBitIndex() {
|
public void toUnsignedBitIndex() {
|
||||||
final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64};
|
final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64};
|
||||||
final List<Integer> list = ByteUtil.toUnsignedBitIndex(bytes);
|
final List<Integer> 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
|
@Test
|
||||||
public void bitCount() {
|
public void bitCount() {
|
||||||
final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64};
|
final byte[] bytes = {0, 13, -64, -31, 101, 88, 47, -64};
|
||||||
final int count = ByteUtil.bitCount(bytes);
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user