read - ¿Cómo convertir una matriz booleana a binaria y viceversa en Java?
read file java (2)
¿Cuál es la forma más eficiente de generar una matriz booleana (e ingresar desde) un archivo en Java? Iba a usar una cadena con cada carácter siendo ''t'' o ''f'' y luego pensé, ¿por qué no tomar ocho veces menos espacio?
NOTA
De hecho, no tengo idea de qué respuesta es el mejor método. Acabo de elegir el de Peter porque lo entiendo. ¡Gracias a ambos respondedores!
Digamos que tienes un booleano []
boolean[] ar = {true,false,false,true,false,true,true,true,false,true,false,false,false,true,true};
y desea escribir esto en un disco, y no le importa cómo se implementa en la memoria.
public static void main(String... args) throws IOException {
boolean[] ar = {true, false, false, true, false, true, true, true, false, true, false, false, false, true, true};
FileOutputStream out = new FileOutputStream("test.dat");
writeBooleans(out, ar);
out.close();
FileInputStream in = new FileInputStream("test.dat");
boolean[] ar2 = new boolean[ar.length];
readBooleans(in, ar2);
in.close();
System.out.println(Arrays.toString(ar));
System.out.println(Arrays.toString(ar2));
System.out.println("The file size was "+new File("test.dat").length()+" bytes.");
}
private static void writeBooleans(OutputStream out, boolean[] ar) throws IOException {
for (int i = 0; i < ar.length; i += 8) {
int b = 0;
for (int j = Math.min(i + 7, ar.length-1); j >= i; j--) {
b = (b << 1) | (ar[j] ? 1 : 0);
}
out.write(b);
}
}
private static void readBooleans(InputStream in, boolean[] ar) throws IOException {
for (int i = 0; i < ar.length; i += 8) {
int b = in.read();
if (b < 0) throw new EOFException();
for (int j = i; j < i + 8 && j < ar.length; j++) {
ar[j] = (b & 1) != 0;
b >>>= 1;
}
}
}
huellas dactilares
[true, false, false, true, false, true, true, true, false, true, false, false, false, true, true]
[true, false, false, true, false, true, true, true, false, true, false, false, false, true, true]
The file size was 2 bytes.
pero si miro lo grande que es realmente el archivo
$ ls -l test.dat
-rw-rw-r-- 1 peter peter 2 2012-02-19 14:04 test.dat
$ du -h test.dat
4.0K test.dat
Dice que la longitud es de 2 bytes, pero el espacio de disco utilizado es en realidad 4 KB.
Nota: Aproximadamente 1 minuto de su tiempo vale lo mismo que 80 MB de SSD (disco caro, más para HDD) Entonces, si no cree que va a ahorrar al menos 80 MB al usar esto, podría estar desperdiciando su hora. ;)
Puede usar BitSet, que puede ocupar 16 veces menos espacio ya que cada carácter es de 16 bits.
Recién creado, solo para ti. BooleanInputStream
como un ejercicio. Tenga en cuenta que el primer bit ahora es el bit más a la derecha (MSB) en el archivo (eliminar Byte.SIZE - 1 -
en el ejemplo para otro orden de bytes, lo que prefiera). Simplemente use, por ejemplo, DataOutputStream para escribir primero el tamaño de la cosa en el archivo. 10K debe caber en un número entero.
Tenga en cuenta que almacenar una matriz booleana de elementos de 10K es una memoria muy ineficiente, sin duda debe usar BitSet
para eso (¡finalmente, alguien que necesita BitSet
)!
public final class BooleanOutputStream extends FilterOutputStream {
private int bitIndex;
private byte buffer;
public BooleanOutputStream(final OutputStream out) {
super(out);
}
public void writeBoolean(final boolean value) throws IOException {
buffer ^= (value ? 1 : 0) << (Byte.SIZE - 1 - bitIndex++);
if (bitIndex == Byte.SIZE) {
write(buffer & 0xFF);
buffer = 0;
bitIndex = 0;
}
}
/**
* This is an encoder and does therefore not close the underlying stream.
* Please close underlying stream separately.
*/
public void close() throws IOException {
if (bitIndex != 0) {
out.write(buffer);
buffer = 0;
bitIndex = 0;
}
}
}
public class BooleanInputStream extends FilterInputStream {
private int bitIndex;
private byte buffer;
public BooleanInputStream(final InputStream in) {
super(in);
}
public boolean readBoolean() throws IOException {
if (bitIndex == 0) {
int b = read();
if (b == -1) {
throw new EOFException();
}
buffer = (byte) b;
}
boolean value = (buffer & (1 << (Byte.SIZE - 1 - bitIndex++))) != 0;
if (bitIndex == Byte.SIZE) {
bitIndex = 0;
}
return value;
}
/**
* This is a decoder and therefore does not close the underlying stream.
* Please close underlying stream separately.
*/
public void close() throws IOException {
buffer = 0;
bitIndex = 0;
}
}