Domanda

Voglio scrivere un BigInteger in un file.
Qual è il modo migliore per farlo.
Certo che voglio leggere (con il programma, non da umani) da un InputStream.
Devo usare un ObjectOutputStream o sono modi ci migliori?

Lo scopo è quello di utilizzare come meno byte come possibile.

Grazie
Martijn

È stato utile?

Soluzione

Java serializzazione (ObjectOutputStream / ObjectInputStream) è un modo di uso generale, er, serializzazione oggetti in sequenze ottetto. Tuttavia, ci sono problema con la serializzazione.

Per essere super efficiente, BigInteger ha toByteArray e un costruttore che prende byte[]. Allora avete bisogno di qualche modo per rappresentare byte[] (compresa la lunghezza) in un flusso. Per esempio, si potrebbe usare per DataOutputStream writeInt la lunghezza, e seguire che con i dati grezzi.

Streams può, naturalmente, essere compressi con un adeguato decoratrice di vostra scelta.

Altri suggerimenti

Mi piacerebbe andare con ObjectOutputStream, questo è ciò che è stato progettato per (non BigInteger specifico, ma le classi).

Ecco alcuni esempi di codice veloce che mostra la testa per entrambe le ObjectOutpuStreams compresssed e non compressi.

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

L'output è:

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

Si potrebbe cambiare il "values.add (BigInteger.ZERO);" la linea per rendere il test più realistico -. Volevo solo una linea di base per esso

Modificato:. non mi rendevo conto la domanda era una di ottimizzazione

Si potrebbe comprimere l'oggetto serializzato in seguito per salvare alcuni byte. Provare a utilizzare il seguente.

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

Ecco un articolo di sole su di esso.

Sì, è possibile utilizzare ObjectOutputStream / ObjectInputStream per semplicità, oppure è possibile convertire il BigInteger ad un byte [], e serializzare il valore anziché l'intero oggetto. Quest'ultimo permetterebbe di risparmiare una notevole quantità di spazio di archiviazione sopra la serializzazione l'intero oggetto.

Inoltre, se si utilizza classi stream che non siano già sottoposti a buffering, ricordarsi di avvolgere le OutputStreams e InputStreams in BufferedOutputStream e BufferedInputStream per migliorare le prestazioni, e flush () dopo aver finito di scrivere (se non a filo () il BufferedOutputStream, InputStream potrebbe andare in stallo o appendere in attesa di input).

Se siete preoccupati per la larghezza di banda o la dimensione del file, si può anche avvolgere i flussi in GZIPOutputStream / GZipInputStream per la compressione automatica. Io non mi preoccuperei di compressione dei dati a meno che effettivamente osservate file povere prestazioni o enormi, tuttavia.

Vuoi leggere / scrivere l'intero Object o solo il suo Valore ? Nel primo caso, quindi fare uso di serializzazione . In quest'ultimo caso, poi basta fare uso di ByteArrayInputStream / ByteArrayOutputStream in cui si scrive il esito BigInteger#toByteArray() e costruire uno nuovo con l'aiuto di new BigInteger(byte[]) rispettivamente. L'ultimo modo genera, ovviamente, molto meno byte nel file.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top