2つのbyte
配列を連結する簡単な方法は何ですか?
いう、
byte a[];
byte b[];
2つのbyte
配列を連結して別のbyte
配列に格納するにはどうすればよいですか?
2つのbyte
配列を連結する簡単な方法は何ですか?
いう、
byte a[];
byte b[];
2つのbyte
配列を連結して別のbyte
配列に格納するにはどうすればよいですか?
回答:
これを行う最もエレガントな方法は、を使用すること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
方法は、メモリを浪費しない、近い候補と考えてください。
別の可能性はを使用すること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)
インスタンス化さjava.nio.HeapByteBuffer
れたのサブクラスを返す静的メソッドですByteBuffer
。方法-と、他の抽象ネス-の世話をしています。.put()
.compact()
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配列などの連結にも使用できます。
この方法でこれを行うと、読み取りと保守が非常に簡単な、高速のarraycopyコードの利点が得られます。
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のようにしたい場合は、次のように、2つbyte[]
(またはそれ以上)を1行で連結することが常に可能です。
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)
、後者は高速です。
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();
}
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();
配列のサイズを台無しにしたくない場合は、文字列連結の魔法を使用してください:
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バイトとしてエンコードする西ラテン1文字セットを示します。マルチバイト変換は実行されないため、文字列内の文字はバイトと同じ値になります(char
符号なしのように常に正の値として解釈されることを除いて)。したがって、少なくともOracle提供のランタイムでは、バイトは正しく「デコード」されてから、再度「エンコード」されます。
文字列はバイト配列をかなり拡張し、追加のメモリが必要になることに注意してください。文字列もインターンされる可能性があるため、簡単には削除できません。文字列も不変なので、文字列内の値は破棄できません。したがって、機密性の高い配列をこの方法で連結したり、大きなバイト配列にこのメソッドを使用したりしないでください。この配列の連結方法は一般的なソリューションではないため、実行していることを明確に示すことも必要になります。
これが私のやり方です!
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つ以上の回答が用意されています。これ以上の重複を投稿しないでください。