Java:BigInteger,如何通过 OutputStream 编写它

发布于 2024-08-14 15:53:58 字数 176 浏览 4 评论 0原文

我想将 BigInteger 写入文件。
执行此操作的最佳方法是什么。
当然,我想从输入流读取(通过程序,而不是人类)它。
我是否必须使用 ObjectOutputStream 还是有更好的方法?

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

谢谢
马丁

I want to write a BigInteger to a file.
What is the best way to do this.
Of course I want to read (with the program, not by human) it from an inputstream.
Do I have to use an ObjectOutputStream or are there better ways?

The purpose is to use as less bytes as possible.

Thanks
Martijn

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

鹿! 2024-08-21 15:53:59

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

为了提高效率,BigInteger 具有 toByteArray 和一个采用 byte[] 的构造函数。然后您需要某种方法来表示流中的字节[](包括长度)。例如,您可以使用 DataOutputStreamwriteInt 长度,然后使用原始数据。

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

Java serialisation (ObjectOutputStream/ObjectInputStream) is a general purpose way of, er, serialising objects into octet sequences. However, there are issue with serialisation.

To be uber efficient, BigInteger has toByteArray and a constructor that takes byte[]. Then you need some way to represent byte[] (including length) in a stream. For instance, you could use DataOutputStream to writeInt the length, and follow that with the raw data.

Streams can, of course, be compressed with a suitable decorator of your choice.

哭了丶谁疼 2024-08-21 15:53:59

我会选择 ObjectOutputStream,这就是它的设计目的(不是专门针对 BigInteger,而是类)。

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

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);”线以使测试更加真实 - 我只是想要一个基线。

I'd go with ObjectOutputStream, that is what it was designed for (not BigInteger specifically, but classes).

Here is some quick sample code that shows the overhead for both compresssed and uncompressed 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();
            }
        }
    }
}

The output is:

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

You would change the " values.add(BigInteger.ZERO);" line to make the test more realistic - I just wanted a baseline for it.

清醇 2024-08-21 15:53:59

编辑:我没有意识到这个问题是关于优化的。

您可以随后压缩序列化对象以节省一些字节。尝试使用以下内容。

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

这是 Sun 的一篇关于它的文章。

Edited: I didn't realize the question was a about optimization.

You could compress the serialized object afterwards to save some bytes. Try using the following.

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

Here is an article by sun about it.

小草泠泠 2024-08-21 15:53:59

是的,为了简单起见,您可以使用 ObjectOutputStream/ObjectInputStream,或者您可以将 BigInteger 转换为 byte[],并序列化该值而不是整个 Object。与序列化整个对象相比,后者可以节省大量存储空间。

另外,如果您使用尚未缓冲的流类,请记住将 OutputStreams 和 InputStreams 包装在 BufferedOutputStream 和 BufferedInputStream 中以提高性能,并在完成写入后刷新()(如果您不刷新() BufferedOutputStream,输入流可能会停止或挂起等待输入)。

如果您担心带宽或文件大小,您还可以将流包装在 GZipOutputStream/GZipInputStream 中以进行自动压缩。不过,除非您确实观察到性能不佳或文件巨大,否则我不会担心压缩数据。

Yes, you can use ObjectOutputStream/ObjectInputStream for simplicity, or you can convert the BigInteger to a byte[], and serialize that value instead of the entire Object. The latter would save a significant amount of storage space over serializing the entire Object.

Also, if you use stream classes that are not already buffered, remember to wrap your OutputStreams and InputStreams in BufferedOutputStream and BufferedInputStream to improve performance, and flush() after you're done writing (if you don't flush() the BufferedOutputStream, the InputStream may stall or hang waiting for input).

If you're worried about bandwidth or file size, you can also wrap your streams in GZipOutputStream/GZipInputStream for automatic compression. I wouldn't worry about compressing the data unless you actually observe poor performance or huge files, however.

許願樹丅啲祈禱 2024-08-21 15:53:59

您想读取/写入整个对象还是仅读取/写入其?如果是前者,则使用序列化。如果是后者,则只需使用 ByteArrayInputStream/ByteArrayOutputStream 其中写入 BigInteger#toByteArray() 并在 new BigInteger(byte[]) 分别。最后一种方法显然在文件中生成的字节少得多。

Do you want to read/write the whole Object or only its value? If the former, then make use of Serialization. If the latter, then just make use of ByteArrayInputStream/ByteArrayOutputStream wherein you write the outcome of BigInteger#toByteArray() and construct a new one with help of new BigInteger(byte[]) respectively. The last way obviously generates much less bytes in the file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文