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.