74 Stimmen

Byte-Array mit unbekannter Länge in Java

Ich bin ein Array von Bytes in Java konstruieren und ich weiß nicht, wie lang das Array sein wird.

Ich möchte ein Tool wie Java's StringBuffer, die Sie einfach aufrufen können .append(byte b) oder .append(byte[] buf) und haben es Puffer alle meine Bytes und zurück zu mir ein byte[], wenn ich fertig bin. Gibt es eine Klasse, die für Bytes tut, was StringBuffer für Strings tut? Es sieht nicht so aus, als ob die ByteBuffer-Klasse das ist, was ich suche.

Hat jemand eine gute Lösung?

125voto

Clint Punkte 8832

トライ ByteArrayOutputStream . Sie können verwenden write( byte[] ) und sie wird nach Bedarf wachsen.

6 Stimmen

+1 Hat sich als nützlich erwiesen, um Daten über einen Socket zu empfangen, ohne sich mit einem Array herumzuschlagen.

6 Stimmen

Sie müssen nicht 'write(byte[], int, int)' verwenden. Es gibt zwei weitere write()-Methoden.

9voto

Micer Punkte 8088

Um die vorherige Antwort zu erweitern, können Sie Folgendes verwenden ByteArrayOutputStream und seine Methode public void write(byte[] b, int off, int len) , wobei die Parameter sind:

b - die Daten

off - der Startoffset in den Daten

len - die Anzahl der zu schreibenden Bytes

Wenn Sie es als "Byte-Builder" verwenden und Byte für Byte einfügen möchten, können Sie dies tun:

byte byteToInsert = 100;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[]{byteToInsert}, 0, 1);

Dann können Sie baos.toString() Methode, um das Array in eine Zeichenkette umzuwandeln. Der Vorteil ist, wenn Sie die Kodierung der Eingabe einrichten müssen, können Sie einfach i.e. verwenden:

baos.toString("Windows-1250")

5 Stimmen

Es gibt zwei weitere write()-Methoden, die Sie aufrufen können. Sie müssen diese ganze Gymnastik nicht mitmachen.

0 Stimmen

Danke für den Hinweis, Sie haben Recht, baos.write(byteToInsert) erledigt die gleiche Aufgabe :-)

3voto

RickHigh Punkte 1708

Ich habe eine geschrieben, die wirklich einfach zu benutzen ist und eine Menge Byte-Array-Puffer-Kopien vermeidet.

Sie hat eine Methode namens add.

Sie können Strings, Bytes, Byte, Long, Int, Double, Float, Short und Chars hinzufügen.

Die API ist einfach zu bedienen und einigermaßen ausfallsicher. Sie erlaubt es nicht, den Puffer herumzukopieren und fördert nicht die Verwendung von zwei Lesern.

Es gibt einen Modus zur Überprüfung der Grenzen und einen I KNOW WHAT I AM DOING MODE ohne Überprüfung der Grenzen.

Der Modus "Bounds Check" erweitert sie automatisch, so dass es keine Probleme gibt.

https://github.com/RichardHightower/boon/wiki/Auto-Growable-Byte-Buffer-like-a-ByteBuilder

Hier finden Sie eine vollständige Schritt-für-Schritt-Anleitung zur Verwendung. Sie befindet sich auf Github.

Java Boon - Automatisch erweiterbarer Byte-Puffer wie ein ByteBuilder

Wollten Sie schon immer ein einfach zu bedienendes Puffer-Array, das automatisch wächst und/oder dem Sie eine feste Größe geben und einfach etwas hinzufügen können? Ich schon. Ich habe auch eins geschrieben.

Sehen Sie. Ich kann Strings darauf schreiben (es konvertiert sie in UTF-8).

    ByteBuf buf = new ByteBuf();
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");

Später kann ich dann den String aus dem Puffer lesen:

    String out = new String(buf.readAndReset(), 0, buf.len());
    assertEquals(66, buf.len());
    assertTrue(out.endsWith("END\n"));

Ich muss nie die Größe des Arrays festlegen. Es wächst automatisch nach Bedarf und auf effiziente Weise.

Wenn ich genau weiß, wie groß meine Daten sein werden, kann ich mir die Überprüfung von Grenzen sparen, indem ich createExact .

    ByteBuf buf = ByteBuf.createExact(66);
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");
    assertEquals(66, buf.len());

Wenn ich create exact verwende, dann sage ich damit... hey... ich weiß genau, wie groß es werden kann und es wird nie über diese Zahl hinausgehen und wenn doch... kannst du mir einen Sack Steine über den Kopf ziehen!

Das Folgende trifft Sie wie ein Sack Steine auf den Kopf! WIRFT EINE AUSNAHME!!!!

    ByteBuf buf = ByteBuf.createExact(22);
    buf.add(bytes("0123456789\n"));
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456789\n");
    buf.add("0123456END\n");

Es funktioniert mit Doppelgängern.

    ByteBuf buf = ByteBuf.createExact(8);

    //add the double
    buf.add(10.0000000000001);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    worked |= idxDouble(bytes, 0) == 10.0000000000001 || die("Double worked");

Es funktioniert mit Float.

    ByteBuf buf = ByteBuf.createExact(8);

    //add the float
    buf.add(10.001f);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    worked |= buf.len() == 4 || die("Float worked");

    //read the float
    float flt = idxFloat(bytes, 0);

    worked |= flt == 10.001f || die("Float worked");

Es funktioniert mit int.

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the int to the array
    buf.add(99);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    //Read the int back
    int value = idxInt(bytes, 0);

    worked |= buf.len() == 4 || die("Int worked length = 4");
    worked |= value == 99 || die("Int worked value was 99");

Es funktioniert mit Saibling.

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the char to the array
    buf.add('c');

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    //Read the char back
    int value = idxChar(bytes, 0);

    worked |= buf.len() == 2 || die("char worked length = 4");
    worked |= value == 'c' || die("char worked value was 'c'");

Es funktioniert mit Short.

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the short to the array
    buf.add((short)77);

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    //Read the short back
    int value = idxShort(bytes, 0);

    worked |= buf.len() == 2 || die("short worked length = 2");
    worked |= value == 77 || die("short worked value was 77");

Es funktioniert sogar mit Bytes.

    ByteBuf buf = ByteBuf.createExact(8);

    //Add the byte to the array
    buf.add( (byte)33 );

    byte[] bytes = buf.readAndReset();
    boolean worked = true;

    //Read the byte back
    int value = idx(bytes, 0);

    worked |= buf.len() == 1 || die("byte worked length = 1");
    worked |= value == 33 || die("byte worked value was 33");

Sie können alle Arten von Primitiven zu Ihrem Byte-Array hinzufügen.

    boolean worked = true;
    ByteBuf buf = ByteBuf.create(1);

    //Add the various to the array
    buf.add( (byte)  1 );
    buf.add( (short) 2 );
    buf.add( (char)  3 );
    buf.add(         4 );
    buf.add( (float) 5 );
    buf.add( (long)  6 );
    buf.add( (double)7 );

    worked |= buf.len() == 29 || die("length = 29");

    byte[] bytes = buf.readAndReset();

    byte myByte;
    short myShort;
    char myChar;
    int myInt;
    float myFloat;
    long myLong;
    double myDouble;

Jetzt müssen wir nur noch überprüfen, ob wir alles zurücklesen können.

    myByte    =   idx       ( bytes, 0 );
    myShort   =   idxShort  ( bytes, 1 );
    myChar    =   idxChar   ( bytes, 3 );
    myInt     =   idxInt    ( bytes, 5 );
    myFloat   =   idxFloat  ( bytes, 9 );
    myLong   =    idxLong   ( bytes, 13 );
    myDouble  =   idxDouble ( bytes, 21 );

    worked |= myByte   == 1 || die("value was 1");
    worked |= myShort  == 2 || die("value was 2");
    worked |= myChar   == 3 || die("value was 3");
    worked |= myInt    == 4 || die("value was 4");
    worked |= myFloat  == 5 || die("value was 5");
    worked |= myLong   == 6 || die("value was 6");
    worked |= myDouble == 7 || die("value was 7");

Sobald Sie anrufen

 byte[] bytes = buf.readAndReset() 

dann sagen Sie, dass Sie mit dem ByteBuffer fertig sind!

Sobald Sie nach den Bytes fragen, wird es nutzlos, da es das interne Byte-Array auf nichts setzt.

Wenn Sie readAndReset aufrufen, gibt er Ihnen seinen Puffer. Hier ist mein interner Zustand, Sie können ihn haben, aber ich werde ihn auf null setzen, damit niemand sonst ihn benutzt.

Das ist in Ordnung. Legen Sie einfach eine weitere an, wenn Sie sicher sind, dass nur jeweils eine Instanz den Puffer (Byte []) verwendet.

Sie können sogar den Puffer verwenden, den Sie gerade benutzt haben, wie in

ByteBuf buf2 = new ByteBuf.create(bytes); 

Dies liegt daran, dass kein Puffer kopiert wird. ByteBuf schreibt in den Puffer, den Sie ihm geben. Wenn Sie möchten, dass eine weitere Kopie an ByteBuf übergeben wird, dann tun Sie dies:

ByteBuf buf2 = new ByteBuf.create( copy(bytes) ); 

Das ist doch ein Segen :)

Komm und sieh dir boon an. Sie erhalten die obige Klasse und idx, und idxInt und idxLong kostenlos!

https://github.com/RichardHightower/boon/

0 Stimmen

Die erste Url (zum Wiki) wird nicht gefunden.

1voto

RickHigh Punkte 1708

Schauen wir mal. In Java gibt es die Klasse ByteBuffer.

http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html

Es verfügt über Bulk-Methoden, die zusammenhängende Sequenzen von Bytes aus einem Byte-Array in Hardware-Puffer übertragen. Das würde den Zweck erfüllen.

Außerdem verfügt es über absolute und relative Get- und Put-Methoden, mit denen Byte[]s und andere Primitive in/für den Byte-Puffer gelesen und geschrieben werden können.

Außerdem verfügt es über Methoden zur Verdichtung, Duplizierung und Aufteilung eines Byte-Puffers.

// Creates an empty ByteBuffer with a 1024 byte capacity
ByteBuffer buf = ByteBuffer.allocate(1024);

// Get the buffer's capacity
int capacity = buf.capacity(); // 10

buf.put((byte)0xAA); // position=0

// Set the position
buf.position(500);

buf.put((byte)0xFF);

// Read the position 501
int pos = buf.position(); 

// Get remaining byte count
int remaining = buf.remaining(); (capacity - position)

Es hat auch eine Bulk-Put, um ein Array zu setzen, die ziemlich nah an der append Sie für gefragt wurden:

public final ByteBuffer put(byte[] src)

Siehe: http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#put(byte[])

Ich habe meine eigene kleine Lib zur Manipulation von Byte-Arrays geschrieben :)

Sie können sie folgendermaßen hinzufügen

byte [] a = ...
byte [] b = ...
byte [] c = ...

a = add(a, b);
a = add(a, c);

Dies würde Ihnen den gesamten Inhalt von b und c nach dem Inhalt von a liefern.

Wenn Sie bis 21 wachsen wollten, könnten Sie Folgendes tun:

a = grow( letters,  21);

Wenn Sie die Größe von a verdoppeln wollten, könnten Sie Folgendes tun:

a = grow( letters,  21);

Siehe...

https://github.com/RichardHightower/boon/blob/master/src/main/java/org/boon/core/primitive/Byt.java

    byte[] letters =
            arrayOfByte(500);

    assertEquals(
            500,
            len(letters)
    );

erstellen.

    byte[] letters =
            array((byte)0, (byte)1, (byte)2, (byte)3);

    assertEquals(
            4,
            len(letters)
    );

Index

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d');

    assertEquals(
            'a',
            idx(letters, 0)
    );

    assertEquals(
            'd',
            idx(letters, -1)
    );

    assertEquals(
            'd',
            idx(letters, letters.length - 1)
    );

    idx(letters, 1, (byte)'z');

    assertEquals(
            (byte)'z',
            idx(letters, 1)
    );

Enthält

    byte[] letters =
            array((byte)'a',(byte) 'b', (byte)'c', (byte)'d');

    assertTrue(
            in((byte)'a', letters)
    );

    assertFalse(
            in((byte)'z', letters)
    );

Slice:

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d');

    assertArrayEquals(
            array((byte)'a', (byte)'b'),
            slc(letters, 0, 2)
    );

    assertArrayEquals(
            array((byte)'b', (byte)'c'),
            slc(letters, 1, -1)
    );

    //>>> letters[2:]
    //['c', 'd']
    //>>> letters[-2:]
    //['c', 'd']

    assertArrayEquals(
            array((byte)'c', (byte)'d'),
            slc(letters, -2)
    );

    assertArrayEquals(
            array((byte)'c', (byte)'d'),
            slc(letters, 2)
    );

    //>>> letters[:-2]
    //     ['a', 'b']
    assertArrayEquals(
            array((byte)'a', (byte)'b'),
            slcEnd(letters, -2)
    );

    //>>> letters[:-2]
    //     ['a', 'b']
    assertArrayEquals(
            array((byte)'a',(byte) 'b'),
            slcEnd(letters, 2)
    );

Wachsen

    byte[] letters =
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e');

    letters = grow( letters,  21);

    assertEquals(
            'e',
            idx(letters, 4)
    );

    assertEquals(
            'a',
            idx(letters, 0)
    );

    assertEquals(
            len(letters),
            26
    );

    assertEquals(
            '\0',
            idx(letters, 20)
    );

Schrumpfen:

    letters =  shrink ( letters, 23 );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c'),
            letters

    );

Kopieren:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'),
            copy(array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'))

    );

Hinzufügen:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'),
            add(array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e'), (byte)'f') );

Das add fügt sie tatsächlich zusammen, indem es System.arraycopy verwendet (was als unsicher gilt, aber noch nicht).

Ein Array zu einem anderen hinzufügen:

    assertArrayEquals(
            array(     (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'),
            add( array((byte)'a', (byte)'b', (byte)'c', (byte)'d'), array((byte)'e', (byte)'f') )

    );

Einfügen:

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'a', (byte)'b', (byte)'d', (byte)'e', (byte)'f', (byte)'g'), 2, (byte)'c' )

    );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'), 0, (byte)'a' )

    );

    assertArrayEquals(
            array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g'),
            insert( array((byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'g'), 5, (byte)'f' )

    );

Hier ein kleiner Einblick in einige der Methoden:

public static byte[] grow(byte [] array, final int size) {
    Objects.requireNonNull(array);

    byte [] newArray  = new byte[array.length + size];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}

public static byte[] grow(byte [] array) {
    Objects.requireNonNull(array);

    byte [] newArray  = new byte[array.length *2];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}

public static byte[] shrink(byte[] array, int size) {
    Objects.requireNonNull(array);

    byte[] newArray = new byte[array.length - size];

    System.arraycopy(array, 0, newArray, 0, array.length-size);
    return newArray;
}

public static byte[] copy(byte[] array) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length];
    System.arraycopy(array, 0, newArray, 0, array.length);
    return newArray;
}

public static byte[] add(byte[] array, byte v) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length + 1];
    System.arraycopy(array, 0, newArray, 0, array.length);
    newArray[array.length] = v;
    return newArray;
}

public static byte[] add(byte[] array, byte[] array2) {
    Objects.requireNonNull(array);
    byte[] newArray = new byte[array.length + array2.length];
    System.arraycopy(array, 0, newArray, 0, array.length);
    System.arraycopy(array2, 0, newArray, array.length, array2.length);
    return newArray;
}

public static byte[] insert(final byte[] array, final int idx, final byte v) {
    Objects.requireNonNull(array);

    if (idx >= array.length) {
        return add(array, v);
    }

    final int index = calculateIndex(array, idx);

    //Object newArray = Array.newInstance(array.getClass().getComponentType(), array.length+1);
    byte [] newArray = new byte[array.length+1];

    if (index != 0) {
        /* Copy up to the location in the array before the index. */
        /*                 src     sbegin  dst       dbegin   length of copy */
        System.arraycopy( array,   0,      newArray, 0,       index );
    }

    boolean lastIndex = index == array.length -1;
    int remainingIndex = array.length - index;

    if (lastIndex ) {
        /* Copy the area after the insert. Make sure we don't write over the end. */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + 1, remainingIndex );

    } else {
        /* Copy the area after the insert.  */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + 1, remainingIndex );

    }

    newArray[index] = v;
    return  newArray;
}

public static byte[] insert(final byte[] array, final int fromIndex, final byte[] values) {
    Objects.requireNonNull(array);

    if (fromIndex >= array.length) {
        return add(array, values);
    }

    final int index = calculateIndex(array, fromIndex);

    //Object newArray = Array.newInstance(array.getClass().getComponentType(), array.length+1);
    byte [] newArray = new byte[array.length +  values.length];

    if (index != 0) {
        /* Copy up to the location in the array before the index. */
        /*                 src     sbegin  dst       dbegin   length of copy */
        System.arraycopy( array,   0,      newArray, 0,       index );
    }

    boolean lastIndex = index == array.length -1;

    int toIndex = index + values.length;
    int remainingIndex = newArray.length - toIndex;

    if (lastIndex ) {
        /* Copy the area after the insert. Make sure we don't write over the end. */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + values.length, remainingIndex );

    } else {
        /* Copy the area after the insert.  */
        /*                 src  sbegin   dst       dbegin     length of copy */
        System.arraycopy(array, index,   newArray, index + values.length, remainingIndex );

    }

    for (int i = index, j=0; i < toIndex; i++, j++) {
        newArray[ i ] = values[ j ];
    }
    return  newArray;
}

Mehr....

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X