2つのbyte
配列を連結する簡単な方法は何ですか?
いう、
byte a[];
byte b[];
2つの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( );
これが Guava のcom.google.common.primitives.Bytes
を使ったいい解決策です:
byte[] c = Bytes.concat(a, b);
このメソッドの素晴らしいところは、それが可変引数シグネチャを持っているということです。
public static byte[] concat(byte[]... arrays)
つまり、1回のメソッド呼び出しで任意の数の配列を連結できます。
他の可能性は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()
は単にオフセット、位置、またはリミットを考慮せずに単に裏配列を返すため)配列は最初から適切なサイズにする必要があるため、割り当て行が必要です。
もう1つの方法は、効用関数を使用することです(必要に応じて、これを総称効用クラスの静的メソッドにすることができます)。
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配列などを連結するためにも動作します。
このようにすると、高速の配列コピーコードの利点が得られます。これも読み取りや保守が非常に簡単です。
あなたは、Apache Commons Langのようなクリーンコード用のサードパーティのライブラリを使用することができます。
byte[] bytes = ArrayUtils.addAll(a, b);
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);
@kalefranzのようにByteBuffer
を好むのであれば、2つのbyte[]
(またはそれ以上)を1行に連結する可能性が常にあります。
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
2つ以上のアレイでは、このシンプルでクリーンなユーティリティメソッドを使用できます。
/**
* 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();
}
配列のサイズを混乱させたくない場合は、単に文字列連結の魔法を使用してください。
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);
もちろん、これは+
の加算演算子を使用した3つ以上の文字列連結でも機能します。
"l1"
とISO_8859_1
はどちらも、各文字を1バイトとしてエンコードするWestern Latin 1文字セットを示します。マルチバイト変換は実行されないため、文字列内の文字はバイトと同じ値になります(ただし、char
は符号なしのため、常に正の値として解釈されます)。したがって、少なくともオラクル社が提供するランタイムについては、どのバイトも正しく「デコード」されてから、「エンコード」されます。
文字列はバイト配列を慎重に拡張するため、追加のメモリが必要になります。文字列も入れ込まれる可能性があるため、簡単に削除することはできません。文字列も不変であるため、それらの中の値は破壊されません。したがって、機密配列をこのように連結したり、より大きなバイト配列にこの方法を使用したりしないでください。この配列連結方法は一般的な解決策ではないため、自分が何をしているのかを明確に示すことも必要です。
これが私のやり方です!
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 code をコピーすることです。このデータ型が別の関数に渡されるとJavaが新しい変数を作成するため、問題はネイティブ変数配列に由来します。
PDFを含む2バイト配列をマージしている場合、このロジックは機能しません。 ApacheのPDFboxのようなサードパーティ製のツールを使う必要があります。
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();