我想将 BigInteger 写入文件。
做这个的最好方式是什么。
当然,我想从输入流中读取(使用程序,而不是人工)它。
我必须使用 ObjectOutputStream 还是有更好的方法?
目的是使用尽可能少的字节。
谢谢马丁
_
我想将 BigInteger 写入文件。
做这个的最好方式是什么。
当然,我想从输入流中读取(使用程序,而不是人工)它。
我必须使用 ObjectOutputStream 还是有更好的方法?
谢谢马丁
_
Java 序列化 ( ObjectOutputStream
/ ObjectInputStream
) 是一种通用方法,呃,将对象序列化为八位字节序列。但是,序列化存在问题。
为了超级高效,BigInteger
hastoByteArray
和一个构造函数需要byte[]
. 然后你需要某种方式byte[]
在流中表示(包括长度)。例如,您可以使用DataOutputStream
长度writeInt
,然后使用原始数据进行跟踪。
当然,可以使用您选择的合适的装饰器来压缩流。
我会选择 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);” 线以使测试更现实-我只是想要一个基线。
你想读/写整个值Object
还是只写它的值?如果是前者,则使用Serialization。如果是后者,那么只需使用ByteArrayInputStream
/ByteArrayOutputStream
在其中编写结果BigInteger#toByteArray()
并分别在 of 的帮助下构造一个新结果new BigInteger(byte[])
。最后一种方式显然在文件中生成的字节少得多。
是的,为了简单起见,您可以使用 ObjectOutputStream/ObjectInputStream,或者您可以将 BigInteger 转换为 byte[],并序列化该值而不是整个 Object。与序列化整个对象相比,后者将节省大量存储空间。
此外,如果您使用尚未缓冲的流类,请记住将 OutputStreams 和 InputStreams 包装在 BufferedOutputStream 和 BufferedInputStream 中以提高性能,并在完成写入后使用 flush()(如果您不 flush() BufferedOutputStream, InputStream 可能会停止或挂起等待输入)。
如果您担心带宽或文件大小,您还可以将流包装在 GZipOutputStream/GZipInputStream 中以进行自动压缩。但是,除非您实际观察到性能不佳或文件很大,否则我不会担心压缩数据。
编辑:我没有意识到这个问题是关于优化的。
之后您可以压缩序列化对象以节省一些字节。尝试使用以下内容。
FileOutputStream fos = new
FileOutputStream("db");
GZIPOutputStream gz = new GZIPOutputStream(fos);