Question

Je veux écrire un BigInteger dans un fichier.
Quelle est la meilleure façon de procéder.
Bien sûr, je veux lire (avec le programme, pas par humain) it à partir d'un introutStream.
Dois-je utiliser un objetTutputStream ou y a-t-il de meilleures façons?

Le but est d'utiliser aussi moins d'octets que possible.

Merci
Martijn

Était-ce utile?

La solution

Sérialisation java (ObjectOutputStream/ObjectInputStream) est un moyen d'objectif général de, ER, sérialiser les objets en séquences d'octets. Cependant, il y a un problème avec la sérialisation.

Être uber efficace, BigInteger a toByteArray Et un constructeur qui prend byte[]. Alors vous avez besoin d'un moyen de représenter byte[] (y compris la longueur) dans un flux. Par exemple, vous pouvez utiliser DataOutputStream à writeInt la longueur, et suivez cela avec les données brutes.

Les flux peuvent, bien sûr, être comprimés avec un décorateur approprié de votre choix.

Autres conseils

J'irais avec ObjectOutputStream, c'est pour cela qu'il a été conçu (pas BigInteger spécifiquement, mais les classes).

Voici un exemple de code rapide qui montre la surcharge pour les objets compresses et non compressés.

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 sortie est:

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

Vous modifieriez "les valeurs.add (bigInteger.zero);" ligne pour rendre le test plus réaliste - je voulais juste une base de référence pour cela.

Édité: Je ne savais pas que la question était une question d'optimisation.

Vous pouvez compresser l'objet sérialisé par la suite pour enregistrer quelques octets. Essayez d'utiliser ce qui suit.

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

Voici un article de Sun à ce sujet.

Oui, vous pouvez utiliser ObjectOutStream / ObjectInputStream pour la simplicité, ou vous pouvez convertir le BigInteger en un octet [], et sérialiser cette valeur au lieu de l'objet entier. Ce dernier permettrait d'économiser une quantité importante d'espace de stockage par rapport à la sérialisation de l'ensemble de l'objet.

De plus, si vous utilisez des classes de flux qui ne sont pas déjà tamponnées, n'oubliez pas d'envelopper vos sorties de sortie et vos intrants dans BufferedOutputStream et BufferedInputStream pour améliorer les performances, et Flush () après avoir terminé d'écrire (si vous ne trouvez pas () le tampon de tampon, Le SputStream peut décrocher ou suspendre l'entrée en attente).

Si vous vous inquiétez de la bande passante ou de la taille du fichier, vous pouvez également envelopper vos flux dans gzipOutputStream / gzipinputStream pour une compression automatique. Je ne m'inquiéterais pas de compresser les données à moins que vous n'observez réellement de mauvaises performances ou d'énormes fichiers.

Voulez-vous lire / écrire le tout Object ou seulement c'est évaluer? Si le premier, utilisez alors Sérialisation. Si ce dernier, alors utilisez simplement ByteArrayInputStream/ByteArrayOutputStream où vous écrivez le résultat de BigInteger#toByteArray() et en construire un nouveau avec l'aide de new BigInteger(byte[]) respectivement. La dernière voie génère évidemment beaucoup moins d'octets dans le fichier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top