วิธีง่าย ๆ ในการเชื่อมสองbyte
อาร์เรย์คืออะไร?
พูด,
byte a[];
byte b[];
ฉันจะต่อกันสองbyte
อาร์เรย์และเก็บในbyte
อาร์เรย์อื่นได้อย่างไร
วิธีง่าย ๆ ในการเชื่อมสองbyte
อาร์เรย์คืออะไร?
พูด,
byte a[];
byte b[];
ฉันจะต่อกันสองbyte
อาร์เรย์และเก็บในbyte
อาร์เรย์อื่นได้อย่างไร
คำตอบ:
ตรงไปตรงมามากที่สุด:
byte[] c = new byte[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
ByteArrayOutputStream
วิธีที่สง่างามที่สุดที่จะทำนี้ด้วย
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
- คุณไม่ต้องย้อนกลับและแก้ไขบรรทัดที่คุณสร้างอาร์เรย์ไบต์ผลลัพธ์ นอกจากนี้การสั่งซื้ออาร์เรย์ใหม่ก็ง่ายเหมือนการใช้วิธี arraycopy
a.length + b.length
เป็นอาร์กิวเมนต์สำหรับตัวByteArrayOutputStream
สร้าง โปรดทราบว่าวิธีนี้จะยังคงคัดลอกไบต์ทั้งหมดไปยังอาร์เรย์ใหม่เพื่อกำหนดให้c[]
! พิจารณาByteBuffer
วิธีการแข่งขันอย่างใกล้ชิดที่ไม่เสียหน่วยความจำ
นี่คือทางออกที่ดีโดยใช้ฝรั่ง 's com.google.common.primitives.Bytes
:
byte[] c = Bytes.concat(a, b);
สิ่งที่ดีเกี่ยวกับวิธีนี้คือมันมีลายเซ็น varargs:
public static byte[] concat(byte[]... arrays)
ซึ่งหมายความว่าคุณสามารถเชื่อมต่อจำนวนอาร์เรย์โดยพลการในการเรียกใช้เมธอดเดียว
java.nio.ByteBuffer
เป็นไปได้ก็คือการใช้
สิ่งที่ต้องการ
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();
โปรดทราบว่าอาร์เรย์ต้องมีขนาดที่เหมาะสมเพื่อเริ่มต้นด้วยดังนั้นจึงจำเป็นต้องมีบรรทัดการจัดสรร ( array()
เพียงแค่ส่งคืนอาร์เรย์สำรองโดยไม่คำนึงถึงออฟเซ็ตตำแหน่งหรือข้อ จำกัด ในการพิจารณา)
ByteBuffer.allocate(int)
เป็นวิธีการที่คงที่ส่งกลับ instantiated java.nio.HeapByteBuffer
, subclass ByteBuffer
ของ .put()
และ.compact()
วิธีการ - และอื่น ๆ ที่เป็นนามธรรม-Ness - ได้รับการดูแล
compact()
บรรทัดเนื่องจากไม่ถูกต้อง
bb.flip(); bb.get(result);
แทนbyte[] result = bb.array();
สาย
allocate
วิธีการเปิดเผยต่อไปนี้: "ตำแหน่งบัฟเฟอร์ใหม่จะเป็นศูนย์ขีด จำกัด ของมันจะเป็นความจุเครื่องหมายของมันจะไม่ได้กำหนดและองค์ประกอบแต่ละอย่างจะเริ่มต้นเป็นศูนย์ มันจะมีอาเรย์สำรองและอาเรย์ออฟของมันจะเป็นศูนย์ " ดังนั้นสำหรับรหัสเฉพาะส่วนนี้ซึ่งการByteBuffer
จัดสรรภายในนั้นไม่ใช่ปัญหา
อีกวิธีหนึ่งคือการใช้ฟังก์ชั่นยูทิลิตี้ (คุณสามารถทำให้เป็นวิธีการคงที่ของคลาสยูทิลิตี้ทั่วไปถ้าคุณต้องการ):
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;
}
วิงวอนอย่างนั้น
byte[] a;
byte[] b;
byte[] result = concat(a, b);
มันจะทำงานสำหรับการเชื่อมต่อ 3, 4, 5 อาร์เรย์ ฯลฯ
การทำเช่นนี้จะช่วยให้คุณได้รับประโยชน์จากรหัสอาเรย์โค้ดอย่างรวดเร็วซึ่งง่ายต่อการอ่านและบำรุงรักษา
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);
หากคุณต้องการByteBuffer
เช่น @kalefranz มีความเป็นไปได้ที่จะเชื่อมสองbyte[]
(หรือมากกว่า) เข้าด้วยกันในบรรทัดเดียวเช่นนี้:
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
คุณสามารถใช้ห้องสมุดบุคคลที่สามสำหรับรหัสสะอาดเช่น Apache Commons Lang และใช้เช่น:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)
และbyte[] c = Bytes.concat(a, b)
แต่หลังเป็นได้เร็วขึ้น
สำหรับสองหรือหลายอาร์เรย์วิธียูทิลิตี้ที่เรียบง่ายและสะอาดนี้สามารถใช้ได้:
/**
* 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();
}
หากคุณกำลังรวมอาร์เรย์สองไบต์ซึ่งมี PDF ตรรกะนี้จะไม่ทำงาน เราจำเป็นต้องใช้เครื่องมือของบุคคลที่สามเช่น PDFbox จาก Apache:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();
หากคุณไม่ต้องการยุ่งกับขนาดของอาร์เรย์เพียงใช้เวทย์มนตร์ของการต่อสตริง:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
หรือกำหนดบางแห่งในรหัสของคุณ
// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
และการใช้งาน
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
แน่นอนว่ายังใช้งานได้กับการต่อสตริงมากกว่าสองรายการโดยใช้ตัว+
ดำเนินการเพิ่ม
ทั้งสอง"l1"
และISO_8859_1
ระบุชุดอักขระ Western Latin 1 ที่เข้ารหัสอักขระแต่ละตัวเป็นไบต์เดียว เนื่องจากไม่มีการแปลแบบหลายไบต์อักขระในสตริงจะมีค่าเหมือนกับไบต์ (ยกเว้นว่าพวกเขาจะถูกตีความว่าเป็นค่าบวกเสมอเช่นchar
ไม่ได้ลงนาม) อย่างน้อยสำหรับรันไทม์ที่ Oracle จัดเตรียมไว้ไบต์ใด ๆ จะถูก "ถอดรหัส" อย่างถูกต้องแล้วจึง "เข้ารหัส" อีกครั้ง
ระวังว่าสตริงจะขยายอาร์เรย์ไบต์อย่างมากต้องใช้หน่วยความจำเพิ่มเติม เงื่อนไขอาจถูก interned และจะไม่ถูกลบออกง่าย สตริงนั้นไม่สามารถเปลี่ยนแปลงได้ดังนั้นค่าภายในจึงไม่สามารถถูกทำลายได้ คุณจึงไม่ควรเชื่อมต่ออาร์เรย์ที่มีความละเอียดอ่อนด้วยวิธีนี้และคุณไม่ควรใช้วิธีนี้สำหรับอาร์เรย์ขนาดใหญ่ การบอกสิ่งที่คุณกำลังทำอย่างชัดเจนก็เป็นสิ่งจำเป็นเช่นกันเนื่องจากวิธีการเรียงต่อกันของอาเรย์นี้ไม่ใช่วิธีการทั่วไป
นี่คือวิธีของฉันที่จะทำ!
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;
}
คุณสมบัติ :
...
) เพื่อเรียกด้วยจำนวนไบต์ใด ๆ []System.arraycopy()
ที่ได้รับการติดตั้งมาพร้อมกับรหัสเนทีฟเฉพาะเครื่องเพื่อให้มั่นใจถึงการทำงานด้วยความเร็วสูงint
ตัวแปรให้น้อยลงโดยการใช้ซ้ำi
และlen
ตัวแปรโปรดทราบ :
วิธีที่ดีกว่าที่จะทำเช่นนี้โดยการคัดลอกรหัส @ Jonathan ปัญหามาจากอาร์เรย์ตัวแปรเนทีฟเนื่องจาก Java สร้างตัวแปรใหม่เมื่อชนิดข้อมูลนี้ถูกส่งผ่านไปยังฟังก์ชันอื่น
System.arrayCopy
,ByteBuffer
และ - ไม่ได้มีประสิทธิภาพ แต่อ่าน -ByteArrayOutputStream
ทุกคนได้รับการคุ้มครอง เรามีคำตอบมากกว่า 7 ข้อที่ให้ไว้ที่นี่ โปรดอย่าโพสต์การหลอกอีกต่อไป