Вопрос

Я хочу написать Biginteger в файл.
Какой лучший способ сделать это.
Конечно я хочу прочитать (С программой, а не человеком) это от входного потока.
Должен ли я использовать objectOutputStream или есть лучшие способы?

Цель состоит в том, чтобы использовать как можно меньше байтов.

Спасибо
Martijn

Это было полезно?

Решение

Сериализация Java (ObjectOutputStream/ObjectInputStream) - это общий способ, который, er, сериализация объектов в октет -последовательности. Тем не менее, есть проблемы с сериализацией.

Быть эффективным, BigInteger имеет toByteArray и конструктор, который берет byte[]. Анкет Тогда вам нужен способ представить byte[] (включая длину) в потоке. Например, вы можете использовать DataOutputStream к writeInt Длина и следуйте этому с помощью необработанных данных.

Потоки, конечно, могут быть сжаты с подходящим декоратором по вашему выбору.

Другие советы

Я бы пошел с ObjectOutputStream, это то, для чего он был разработан (не BigInteger конкретно, а классы).

Вот какой -то быстрый пример кода, который показывает накладные расходы как для сжатых, так и несжатых объектов.

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

Вывод:

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

Вы бы изменили «values.add (biginteger.zero);»; Линия, чтобы сделать тест более реалистичным - я просто хотел для этого базового уровня.

Отредактировано: Я не понимал, что вопрос был об оптимизации.

После этого вы можете сжать сериализованный объект, чтобы сохранить несколько байтов. Попробуйте использовать следующее.

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

Вот статья Sun об этом.

Да, вы можете использовать ObjectOutputStream/ObjectInputStream для простоты, или вы можете преобразовать BigInteger в байт [] и сериализовать это значение вместо всего объекта. Последний сэкономит значительное количество места для хранения над сериализацией всего объекта.

Кроме того, если вы используете классы потоков, которые еще не буферизированы, не забудьте обернуть свои выходные потоки и входные потоки в BufferedOutputStream и BufferedInptream для повышения производительности и промывки () после того, как вы закончите написание (если вы не промываете () BufferedOutputStream, Входная сеть может задержать или повесить в ожидании ввода).

Если вы беспокоитесь о пропускной способности или размере файла, вы также можете обернуть свои потоки в GzipoutputStream/GzipinputStream для автоматического сжатия. Однако я бы не стал беспокоиться о сжатии данных, если вы на самом деле не наблюдаете плохую производительность или огромные файлы.

Вы хотите прочитать/написать целое Object или только его ценность? Если первое, то используйте Сериализация. Анкет Если последнее, просто используйте ByteArrayInputStream/ByteArrayOutputStream где вы пишете результат BigInteger#toByteArray() и построить новый с помощью new BigInteger(byte[]) соответственно. Последний путь, очевидно, генерирует гораздо меньше байтов в файле.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top