我想为文件写一个biginteger。
做这个的最好方式是什么。
我当然想读 (与该计划,不是人类) 它是从输入流。
我必须使用ObjectOutputStream还是有更好的方法?

目的是尽可能少地使用字节。

谢谢
martijn

有帮助吗?

解决方案

Java序列化(ObjectOutputStream/ObjectInputStream)是将对象序列化为八位位序列的通用方式。但是,序列化存在问题。

提高效率, BigIntegertoByteArray 和一个构造函数 byte[]. 。那么您需要某种方式来表示 byte[] (包括长度)在流中。例如,您可以使用 DataOutputStreamwriteInt 长度,并使用原始数据遵循。

当然,流可以通过您选择的合适装饰器来压缩流。

其他提示

我会选择ObjectOutputStream,这是它的设计(不是BigInteger,而是类)。

这是一些快速的示例代码,显示了压缩和未压缩的ObjectOutPustreams的开销。

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和BufferedInputStream中包装输出流和InputStreams来提高性能,并在完成写作后(如果不刷新(如果不刷新)(如果不刷新()bufferedOutputputstream,,,输入流可以失速或挂起等待输入)。

如果您担心带宽或文件大小,也可以将流中的流中包裹在GZIPOUTPUTSTREAM/GZIPINPUTSTREAM中,以进行自动压缩。但是,除非您实际观察到性能差或大量文件,否则我不会担心压缩数据。

你想读/写全部吗 Object 或只有它 价值?如果前者,请使用 序列化. 。如果是后者,那就使用 ByteArrayInputStream/ByteArrayOutputStream 在哪里写的结果 BigInteger#toByteArray() 并在帮助的帮助下建造一个新的 new BigInteger(byte[]) 分别。最后的方式显然会在文件中生成较少的字节。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top