web-dev-qa-db-ja.com

2バイト配列を連結する簡単な方法

2つのbyte配列を連結する簡単な方法は何ですか?

いう、

byte a[];
byte b[];

2つのbyte配列を連結して別のbyte配列に格納する方法を教えてください。

222
androidGuy

最も分かりやすい:

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);
293
Jonathan

これを行うための最もエレガントな方法はByteArrayOutputStreamを使うことです。

byte a[];
byte b[];

ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );

byte c[] = outputStream.toByteArray( );
333
Kevin

これが Guavacom.google.common.primitives.Bytesを使ったいい解決策です:

byte[] c = Bytes.concat(a, b);

このメソッドの素晴らしいところは、それが可変引数シグネチャを持っているということです。

public static byte[] concat(byte[]... arrays)

つまり、1回のメソッド呼び出しで任意の数の配列を連結できます。

60
Zoltán

他の可能性は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()は単にオフセット、位置、またはリミットを考慮せずに単に裏配列を返すため)配列は最初から適切なサイズにする必要があるため、割り当て行が必要です。

26
kalefranz

もう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配列などを連結するためにも動作します。

このようにすると、高速の配列コピーコードの利点が得られます。これも読み取りや保守が非常に簡単です。

13
Wayne Uroda

あなたは、Apache Commons Langのようなクリーンコード用のサードパーティのライブラリを使用することができます。

byte[] bytes = ArrayUtils.addAll(a, b);
10
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);
10
James.Xu

@kalefranzのようにByteBufferを好むのであれば、2つのbyte[](またはそれ以上)を1行に連結する可能性が常にあります。

byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
9
ZEuS

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();
}
5

配列のサイズを混乱させたくない場合は、単に文字列連結の魔法を使用してください。

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は符号なしのため、常に正の値として解釈されます)。したがって、少なくともオラクル社が提供するランタイムについては、どのバイトも正しく「デコード」されてから、「エンコード」されます。

文字列はバイト配列を慎重に拡張するため、追加のメモリが必要になります。文字列も入れ込まれる可能性があるため、簡単に削除することはできません。文字列も不変であるため、それらの中の値は破壊されません。したがって、機密配列をこのように連結したり、より大きなバイト配列にこの方法を使用したりしないでください。この配列連結方法は一般的な解決策ではないため、自分が何をしているのかを明確に示すことも必要です。

1
John McClane

これが私のやり方です!

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;
}

特長

  • 任意の数のbyte []で呼び出されるには、varargs(...)を使用します。
  • 高速動作を保証するために、マシン固有のネイティブコードで実装されたSystem.arraycopy()を使用してください。
  • 必要な正確なサイズで新しいbyte []を作成してください。
  • intおよびi変数を再利用して、少しだけlen変数を割り当てます。
  • 定数との高速比較.

覚えておいてください

これを行うより良い方法は、 @ Jonathan code をコピーすることです。このデータ型が別の関数に渡されるとJavaが新しい変数を作成するため、問題はネイティブ変数配列に由来します。

0
Daniel De León

2つのPDFバイト配列をマージ

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();
0
Bala Vignesh B