Cách dễ dàng để nối hai byte
mảng là gì?
Nói,
byte a[];
byte b[];
Làm thế nào để tôi ghép hai byte
mảng và lưu trữ nó trong một byte
mảng khác ?
Cách dễ dàng để nối hai byte
mảng là gì?
Nói,
byte a[];
byte b[];
Làm thế nào để tôi ghép hai byte
mảng và lưu trữ nó trong một byte
mảng khác ?
Câu trả lời:
Cách thanh lịch nhất để làm điều này là với a ByteArrayOutputStream
.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
- bạn không phải quay lại và chỉnh sửa dòng nơi bạn tạo mảng byte kết quả. Ngoài ra, việc sắp xếp lại các mảng rất đơn giản, không giống như sử dụng phương pháp mảng.
a.length + b.length
làm đối số cho hàm ByteArrayOutputStream
tạo. Lưu ý rằng phương thức này vẫn sẽ sao chép tất cả các byte sang một mảng mới để gán cho c[]
! Xem xét ByteBuffer
phương pháp một ứng cử viên gần gũi, điều đó không lãng phí bộ nhớ.
Dưới đây là một giải pháp tốt đẹp sử dụng ổi 's com.google.common.primitives.Bytes
:
byte[] c = Bytes.concat(a, b);
Điều tuyệt vời của phương pháp này là nó có chữ ký varargs:
public static byte[] concat(byte[]... arrays)
điều đó có nghĩa là bạn có thể nối một số mảng tùy ý trong một lệnh gọi phương thức.
Một khả năng khác là sử dụng java.nio.ByteBuffer
.
Cái gì đó như
ByteBuffer bb = ByteBuffer.allocate(a.length + b.length + c.length);
bb.put(a);
bb.put(b);
bb.put(c);
byte[] result = bb.array();
// or using method chaining:
byte[] result = ByteBuffer
.allocate(a.length + b.length + c.length)
.put(a).put(b).put(c)
.array();
Lưu ý rằng mảng phải có kích thước phù hợp để bắt đầu, do đó, dòng phân bổ là bắt buộc (vì array()
chỉ cần trả về mảng sao lưu, mà không lấy phần bù, vị trí hoặc giới hạn vào tài khoản).
ByteBuffer.allocate(int)
là một phương thức tĩnh trả về một khởi tạo java.nio.HeapByteBuffer
, một lớp con của ByteBuffer
. Các phương thức .put()
và .compact()
- và bất kỳ tính trừu tượng nào khác - được quan tâm.
compact()
dòng vì nó không chính xác.
bb.flip(); bb.get(result);
thay cho byte[] result = bb.array();
dòng.
allocate
phương pháp cho thấy như sau: "Vị trí của bộ đệm mới sẽ bằng 0, giới hạn của nó sẽ là khả năng của nó, dấu của nó sẽ không được xác định và mỗi phần tử của nó sẽ được khởi tạo thành 0 Nó sẽ có một mảng sao lưu và bù mảng của nó sẽ bằng không. " Vì vậy, đối với đoạn mã đặc biệt này , nơi ByteBuffer
phân bổ nội bộ, đó không phải là vấn đề.
Một cách khác là sử dụng một hàm tiện ích (bạn có thể biến nó thành một phương thức tĩnh của một lớp tiện ích chung nếu bạn muốn):
byte[] concat(byte[]...arrays)
{
// Determine the length of the result array
int totalLength = 0;
for (int i = 0; i < arrays.length; i++)
{
totalLength += arrays[i].length;
}
// create the result array
byte[] result = new byte[totalLength];
// copy the source arrays into the result array
int currentIndex = 0;
for (int i = 0; i < arrays.length; i++)
{
System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
currentIndex += arrays[i].length;
}
return result;
}
Gọi như vậy:
byte[] a;
byte[] b;
byte[] result = concat(a, b);
Nó cũng sẽ làm việc để ghép 3, 4, 5 mảng, v.v.
Làm theo cách này cung cấp cho bạn lợi thế của mã mảng nhanh, cũng rất dễ đọc và duy trì.
byte[] result = new byte[a.length + b.length];
// copy a to result
System.arraycopy(a, 0, result, 0, a.length);
// copy b to result
System.arraycopy(b, 0, result, a.length, b.length);
Nếu bạn thích ByteBuffer
như @kalefranz, luôn có khả năng ghép hai byte[]
(hoặc thậm chí nhiều hơn) trong một dòng, như sau:
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
Bạn có thể sử dụng các thư viện của bên thứ ba cho Clean Code như Apache Commons Lang và sử dụng nó như sau:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)
và byte[] c = Bytes.concat(a, b)
, nhưng cái sau nhanh hơn.
Đối với hai hoặc nhiều mảng, phương pháp tiện ích đơn giản và sạch sẽ này có thể được sử dụng:
/**
* Append the given byte arrays to one big array
*
* @param arrays The arrays to append
* @return The complete array containing the appended data
*/
public static final byte[] append(final byte[]... arrays) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
if (arrays != null) {
for (final byte[] array : arrays) {
if (array != null) {
out.write(array, 0, array.length);
}
}
}
return out.toByteArray();
}
Nếu bạn hợp nhất hai mảng byte chứa PDF, logic này sẽ không hoạt động. Chúng tôi cần sử dụng một công cụ của bên thứ ba như PDFbox từ Apache:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();
Nếu bạn không muốn gây rối với kích thước của mảng, chỉ cần sử dụng phép thuật nối chuỗi:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
Hoặc xác định một nơi nào đó trong mã của bạn
// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
Và sử dụng
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
Tất nhiên, điều này cũng hoạt động với hơn hai chuỗi nối bằng cách sử dụng +
toán tử cộng.
Cả hai "l1"
và ISO_8859_1
chỉ ra bộ ký tự Western Latin 1 mã hóa mỗi ký tự dưới dạng một byte. Vì không có bản dịch nhiều byte được thực hiện, các ký tự trong chuỗi sẽ có cùng giá trị với byte (ngoại trừ việc chúng sẽ luôn được hiểu là giá trị dương, nhưchar
không dấu). Ít nhất là đối với thời gian chạy do Oracle cung cấp, do đó, bất kỳ byte nào cũng sẽ được "giải mã" chính xác và sau đó "được mã hóa" lại.
Coi chừng các chuỗi mở rộng mảng byte một cách thận trọng, đòi hỏi bộ nhớ bổ sung. Chuỗi cũng có thể được thực tập và do đó sẽ không dễ dàng bị loại bỏ. Chuỗi cũng bất biến, vì vậy các giá trị bên trong chúng không thể bị phá hủy. Do đó, bạn không nên ghép các mảng nhạy cảm theo cách này cũng như không nên sử dụng phương thức này cho các mảng byte lớn hơn. Đưa ra một dấu hiệu rõ ràng về những gì bạn đang làm cũng sẽ được yêu cầu, vì phương pháp nối mảng này không phải là một giải pháp phổ biến.
Đây là cách của tôi để làm điều đó!
public static byte[] concatByteArrays(byte[]... inputs) {
int i = inputs.length - 1, len = 0;
for (; i >= 0; i--) {
len += inputs[i].length;
}
byte[] r = new byte[len];
for (i = inputs.length - 1; i >= 0; i--) {
System.arraycopy(inputs[i], 0, r, len -= inputs[i].length, inputs[i].length);
}
return r;
}
Các tính năng :
...
) để được gọi với bất kỳ số byte [] nào.System.arraycopy()
được thực hiện với mã gốc cụ thể của máy, để đảm bảo hoạt động tốc độ cao.int
các biến ít hơn bằng cách sử dụng lại i
và len
các biến.Hãy ghi nhớ :
Cách tốt hơn để làm điều này là bằng cách sao chép mã @Jonathan . Vấn đề xuất phát từ các mảng biến tự nhiên, bởi vì Java tạo các biến mới khi kiểu dữ liệu này được truyền cho hàm khác.
System.arrayCopy
,ByteBuffer
và - không quá hiệu quả nhưng có thể đọc được -ByteArrayOutputStream
tất cả đều được bao phủ. Chúng tôi đã nhận được hơn 7 bản sao của các câu trả lời được đưa ra ở đây. Xin vui lòng không đăng bất kỳ bản sao nào nữa.