Pregunta

Quiero escribir un biginteger en un archivo.
Cuál es la mejor manera de hacer esto.
Por supuesto que quiero leer (con el programa, no por humano) de un inputstream.
¿Tengo que usar un ObjectOutputStream o hay mejores formas?

El propósito es usar la menor cantidad de bytes posible.

Gracias
Martijn

¿Fue útil?

Solución

Serialización de Java (ObjectOutputStream/ObjectInputStream) es una forma de propósito general de, er, serializar objetos en secuencias de octetos. Sin embargo, hay problemas con la serialización.

Ser súper eficiente, BigInteger posee toByteArray y un constructor que toma byte[]. Entonces necesitas alguna forma de representar byte[] (incluyendo longitud) en una corriente. Por ejemplo, podrías usar DataOutputStream a writeInt la longitud, y siga eso con los datos sin procesar.

Las corrientes, por supuesto, pueden comprimirse con un decorador adecuado de su elección.

Otros consejos

Yo iría con ObjectOutputStream, para eso fue diseñado (no Biginteger específicamente, sino clases).

Aquí hay un código de muestra rápido que muestra la sobrecarga para ObjectOutPustreams comprimidos y sin comprimir.

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;


public class Main
{
    public static void main(String[] args)
        throws IOException
    {
        run(1);
        run(10);
        run(100);
        run(1000);
        run(10000);
        run(100000);
        run(1000000);
    }

    private static void run(final int size)
        throws IOException
    {
        final List<BigInteger> values;
        final int              uncompressedSize;
        final int              compressedSize;

        values           = createValues(size);
        uncompressedSize = storeUncompressed(values);
        compressedSize   = storeCompressed(values);

        System.out.println(size + " uncompressed is " + uncompressedSize + " ratio is: " + ((float)uncompressedSize / size));
        System.out.println(size + " compressed   is " + compressedSize   + " ratio is: " + ((float)compressedSize   / size));
    }

    private static List<BigInteger> createValues(final int size)
    {
        final List<BigInteger> values;

        values = new ArrayList<BigInteger>(size);

        for(int i = 0; i < size; i++)
        {
            values.add(BigInteger.ZERO);
        }

        return (values);
    }

    private static int storeUncompressed(final List<BigInteger> values)
        throws IOException
    {
        final ByteArrayOutputStream bytes;

        bytes = new ByteArrayOutputStream();
        store(values, bytes);

        return (bytes.size());
    }


    private static int storeCompressed(final List<BigInteger> values)
        throws IOException
    {
        final ByteArrayOutputStream bytes;
        final GZIPOutputStream      zip;

        bytes = new ByteArrayOutputStream();
        zip   = new GZIPOutputStream(bytes);
        store(values, zip);

        return (bytes.size());
    }

    private static void store(final List<BigInteger> values,
                              final OutputStream     sink)
        throws IOException
    {
        ObjectOutputStream stream;

        stream = null;

        try
        {
            stream = new ObjectOutputStream(sink);

            for(final BigInteger value : values)
            {
                stream.writeObject(value);
            }
        }
        finally
        {
            if(stream != null)
            {
                stream.close();
            }
        }
    }
}

La salida es:

1 uncompressed is 202 ratio is: 202.0
1 compressed   is 198 ratio is: 198.0
10 uncompressed is 247 ratio is: 24.7
10 compressed   is 205 ratio is: 20.5
100 uncompressed is 697 ratio is: 6.97
100 compressed   is 207 ratio is: 2.07
1000 uncompressed is 5197 ratio is: 5.197
1000 compressed   is 234 ratio is: 0.234
10000 uncompressed is 50197 ratio is: 5.0197
10000 compressed   is 308 ratio is: 0.0308
100000 uncompressed is 500197 ratio is: 5.00197
100000 compressed   is 962 ratio is: 0.00962
1000000 uncompressed is 5000197 ratio is: 5.000197
1000000 compressed   is 7516 ratio is: 0.007516

Cambiaría el "value.add (bigInteger.zero);" Línea para hacer que la prueba sea más realista: solo quería una línea de base para ello.

Editado: No me di cuenta de que la pregunta era sobre optimización.

Puede comprimir el objeto serializado luego para guardar algunos bytes. Intente usar lo siguiente.

FileOutputStream fos = new 
    FileOutputStream("db");
  GZIPOutputStream gz = new GZIPOutputStream(fos);

Aquí hay un artículo de Sun al respecto.

Sí, puede usar ObjectOutputStream/ObjectInputStream para simplificar, o puede convertir el biginteger en un byte [] y serializar ese valor en lugar de todo el objeto. Este último ahorraría una cantidad significativa de espacio de almacenamiento sobre la serialización de todo el objeto.

Además, si usa clases de transmisión que aún no están buffadas, recuerde envolver sus salidas de salida e InputStreams en BufferedOutputStream y BufferedInputStream para mejorar el rendimiento, y FLUSH () después de que haya terminado de escribir (si no está enjuagando () el BufferDoutputStream, El InputStream puede detenerse o colgar esperando la entrada).

Si le preocupa el ancho de banda o el tamaño del archivo, también puede envolver sus transmisiones en GzipoutputStream/GzipinputStream para compresión automática. Sin embargo, no me preocuparía por comprimir los datos a menos que realmente observe un bajo rendimiento o enormes archivos.

¿Quieres leer/escribir todo Object o solo su valor? Si el primero, haga uso de Publicación por entregas. Si es este último, entonces simplemente use ByteArrayInputStream/ByteArrayOutputStream donde escribes el resultado de BigInteger#toByteArray() y construir uno nuevo con ayuda de new BigInteger(byte[]) respectivamente. La última forma obviamente genera mucho menos bytes en el archivo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top