Je construis un tableau d'octets en Java et je ne sais pas combien de temps le tableau sera.
Je veux un outil comme StringBuffer de Java que vous pouvez simplement appeler .append (octet b) ou .append (octet [] buf) et le mettre en mémoire tampon tous mes octets et me renvoyer un tableau d'octets lorsque j'ai terminé. Existe-t-il une classe qui fait pour les octets ce que StringBuffer fait pour les chaînes? Il ne semble pas que la classe ByteBuffer soit ce que je recherche.
Quelqu'un a une bonne solution?
Essayez ByteArrayOutputStream
. Vous pouvez utiliser write( byte[] )
et il s'agrandira 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 paramètres sont:
b - les données
off - le décalage de début dans les données
len - le nombre d'octets à écrire
Si vous souhaitez l'utiliser comme un "générateur d'octets" et insérer octet par octet, vous pouvez utiliser ceci:
byte byteToInsert = 100;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[]{byteToInsert}, 0, 1);
Ensuite, vous pouvez utiliser la méthode baos.toString()
pour convertir le tableau en chaîne. L'avantage est que lorsque vous devez configurer le codage de l'entrée, vous pouvez simplement utiliser, c'est-à-dire:
baos.toString("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 ajouter des chaînes, octets, octets, longs, int, doubles, flottants, courts et caractères.
L'API est facile à utiliser et quelque peu sûre. Il ne vous permet pas de copier le tampon et ne favorise pas la présence de deux lecteurs.
Il a un mode de vérification des limites et un mode JE SAIS CE QUE JE FAIS sans vérification des limites.
Le mode de vérification des limites l'agrandit automatiquement pour qu'il n'y ait pas de soucis.
https://github.com/RichardHightower/boon/wiki/Auto-Growable-Byte-Buffer-like-a-ByteBuilder
Voici un guide étape par étape complet sur la façon de l'utiliser. C'est sur github.
Avez-vous déjà voulu un tableau de tampons facile à utiliser qui grandit automatiquement et/ou vous pouvez lui donner une taille fixe et y ajouter simplement des éléments? J'ai. J'en ai aussi écrit un.
Regardez .. Je peux y é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, plus tard, je peux lire la chaîne dans le tampon:
String out = new String(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 se développera automatiquement au besoin de manière efficace.
Si je sais exactement la taille de mes données, je peux enregistrer certaines limites en vérifiant 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 à quel point il peut grandir et il ne dépassera jamais ce nombre et si c'est le cas ... vous pouvez me frapper la tête avec un sac de roches!
Ce qui suit vous frappe au-dessus de la tête avec un sac de pierres! LANCE 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");
Il 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");
Il 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 le caractère.
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 court.
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 ajouter 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;
Maintenant, nous vérifions simplement 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 terminé avec le ByteBuffer!
Une fois que vous avez demandé les octets, cela devient inutile car il ne définit rien dans le tableau d'octets interne.
Lorsque vous appelez readAndReset, il vous donne son tampon. Voici mon état interne, vous pouvez l'avoir, mais je vais le mettre à null pour que personne d'autre ne l'utilise.
C'est bon. Créez-en simplement une autre si vous êtes sûr 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);
En effet, aucun tampon n'est copié. ByteBuf écrit dans le tampon que vous lui donnez. Si vous souhaitez donner une autre copie à ByteBuf, procédez comme suit:
ByteBuf buf2 = new ByteBuf.create( copy(bytes) );
C'est une aubaine après tout. :)
Venez voir Boon. Vous obtenez la classe et idx ci-dessus, et idxInt et idxLong gratuitement!
Voyons voir. Il existe la classe ByteBuffer en Java.
http://docs.Oracle.com/javase/7/docs/api/Java/nio/ByteBuffer.html
Il a des méthodes en vrac qui transfèrent des séquences contiguës d'octets d'un tableau d'octets vers des tampons matériels. Ça ferait l'affaire.
Il possède également des méthodes get et put absolues et relatives qui lisent et écrivent les octets [] et d'autres primitives dans/pour le tampon d'octets.
Il dispose également de méthodes de compactage, de duplication et de découpage d'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 mettre un tableau, ce qui est assez proche de l'ajout que vous demandiez:
public final ByteBuffer put(byte[] src)
Voir: http://docs.Oracle.com/javase/7/docs/api/Java/nio/ByteBuffer.html#put (octet [])
J'ai écrit ma propre petite lib pour manipuler des tableaux d'octets. :)
Vous pouvez les ajouter 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 de a.
Si vous vouliez faire pousser un par 21, vous pouvez faire ce qui suit:
a = grow( letters, 21);
Si vous souhaitez doubler la taille d'un, vous pouvez procéder comme suit:
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'addition les ajoute en fait à l'aide de System.arraycopy (considérant dangereux, mais pas encore).
Ajoutez 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-unes des 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....