Tableau d’octets de longueur inconnue en Java

Je construis un tableau d’octets en Java et je ne sais pas combien de temps le tableau sera.

Je veux un outil comme le SsortingngBuffer de Java que vous pouvez simplement appeler .append (octet b) ou .append (byte [] buf) et le faire mettre en mémoire tampon tous mes octets et me renvoyer un tableau d’octets quand j’ai fini. Y a-t-il une classe qui fait pour les octets ce que SsortingngBuffer fait pour les chaînes? Cela ne ressemble pas à la classe ByteBuffer que je recherche.

Quelqu’un at-il une bonne solution?

Essayez ByteArrayOutputStream . Vous pouvez utiliser write( byte[] ) et cela grandira au besoin.

Juste pour étendre la réponse précédente, vous pouvez utiliser ByteArrayOutputStream et sa méthode public void write(byte[] b, int off, int len) , où les parameters sont:

b – les données

off – le décalage de départ dans les données

len – le nombre d’octets à écrire

Si vous voulez l’utiliser comme un “générateur d’octets” et insérer des octets par octet, vous pouvez utiliser ceci:

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

Vous pouvez ensuite utiliser la méthode baos.toSsortingng() pour convertir le tableau en chaîne. L’avantage est que lorsque vous devez configurer l’encodage des entrées, vous pouvez simplement utiliser:

 baos.toSsortingng("Windows-1250") 

J’en ai écrit un qui est vraiment facile à utiliser et évite beaucoup de copie de tampon de tableau d’octets.

Il a une méthode appelée add.

Vous pouvez y append des chaînes, octets, octets, long, int, double, float, short et caractères.

L’API est facile à utiliser et quelque peu en sécurité. Il ne vous permet pas de copier le tampon et ne favorise pas d’avoir deux lecteurs.

Il a un mode de vérification des limites et un JE SUIS CE QUE JE FAIS MODE sans vérification des limites.

Le mode de vérification des limites le fait croître automatiquement, il n’y a donc pas de problème.

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

Voici un guide complet étape par étape sur la façon de l’utiliser. C’est sur github.

Java Boon – Tampon ByteBuilder automatique

Avez-vous déjà voulu une masortingce de tampons facile à utiliser qui se développe automatiquement et / ou vous pouvez lui donner une taille de correction et y append des éléments? J’ai. J’en ai écrit un aussi.

Regardez .. je peux écrire des chaînes (il les convertit en 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"); 

Ensuite, je peux lire la chaîne du tampon:

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

Je n’ai jamais à définir la taille du tableau. Il va croître automatiquement au besoin de manière efficace.

Si je sais exactement quelle sera la taille de mes données, je peux sauvegarder certaines limites en utilisant 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()); 

Si j’utilise create exact, alors je dis … hé .. je sais exactement à quelle taille il peut grandir et il ne dépassera jamais ce nombre et si c’est le cas … vous pouvez me bash la tête avec un sac des rochers!

Ce qui suit vous frappe la tête avec un sac de roches! PENSEZ UNE EXCEPTION !!!!

  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"); 

Cela fonctionne avec des doubles.

  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"); 

Cela fonctionne avec 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"); 

Cela fonctionne avec 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"); 

Cela fonctionne avec char.

  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'"); 

Cela fonctionne avec le 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"); 

Il fonctionne même avec des octets.

  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"); 

Vous pouvez append toutes sortes de primitives à votre tableau d’octets.

  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; 

Nous vérifions maintenant que nous pouvons tout lire.

  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"); 

Une fois que vous appelez

  byte[] bytes = buf.readAndReset() 

alors vous dites que vous avez fini avec le ByteBuffer!

Une fois que vous demandez les octets, cela devient inutile car il définit le tableau d’octets interne sur rien.

Lorsque vous appelez readAndReset, il vous donne son tampon. Voici mon état interne, vous pouvez l’avoir, mais je vais le définir sur null pour que personne d’autre ne l’utilise.

C’est bon. Créez simplement un autre si vous êtes certain qu’une seule instance à la fois utilise le tampon (octet []).

Vous pouvez même utiliser le tampon que vous utilisiez comme dans

 ByteBuf buf2 = new ByteBuf.create(bytes); 

Ceci est dû au fait qu’aucun tampon n’est copié. ByteBuf écrit dans le tampon que vous lui donnez. Si vous souhaitez qu’une autre copie soit donnée à ByteBuf, procédez comme suit:

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

C’est une aubaine après tout. 🙂

Venez vérifier boon. Vous obtenez la classe ci-dessus et idx, et idxInt et idxLong gratuitement!

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

Voyons voir. Il y a la classe ByteBuffer en Java.

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

Il a des méthodes en bloc qui transfèrent des séquences contiguës d’octets d’un tableau d’octets à des tampons matériels. Ça ferait l’affaire.

Il dispose également de méthodes get et put absolues et relatives qui lisent et écrivent les octets [] et autres primitives dans / pour le tampon d’octets.

Il dispose également de méthodes pour compacter, dupliquer et découper un tampon d’octets.

 // 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) 

Il a également un gros volume pour placer un tableau, ce qui est assez proche de l’appendice que vous demandiez:

 public final ByteBuffer put(byte[] src) 

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

J’ai écrit ma propre petite lib pour manipuler des tableaux d’octets. 🙂

Vous pouvez les append comme ça

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

Cela vous donnerait tout le contenu de b et c après le contenu pour un.

Si vous souhaitez augmenter de 21%, vous pouvez effectuer les opérations suivantes:

 a = grow( letters, 21); 

Si vous souhaitez doubler la taille d’un, vous pouvez effectuer les opérations suivantes:

 a = grow( letters, 21); 

Voir…

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

  byte[] letters = arrayOfByte(500); assertEquals( 500, len(letters) ); 

Créer

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

Indice

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

Contient

  byte[] letters = array((byte)'a',(byte) 'b', (byte)'c', (byte)'d'); assertTrue( in((byte)'a', letters) ); assertFalse( in((byte)'z', letters) ); 

Tranche:

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

Croître

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

Rétrécir:

  letters = shrink ( letters, 23 ); assertArrayEquals( array((byte)'a', (byte)'b', (byte)'c'), letters ); 

Copie:

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

Ajouter:

  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') ); 

L’ajout les ajoute en utilisant System.arraycopy (en considérant Unsafe, mais pas encore).

Ajouter un tableau à un autre:

  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') ) ); 

Insérer:

  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' ) ); 

Voici un aperçu de quelques méthodes:

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

Plus....