Java:biginteger、outputStreamを通してそれを書きます
-
19-09-2019 - |
質問
ファイルにbigintegerを書きたいです。
これを行うための最良の方法は何ですか。
もちろん読みたいです (人間ではなくプログラムで) 入力ストリームから。
ObjectOutputStreamを使用する必要がありますか、それともより良い方法はありますか?
目的は、できるだけ少ないバイトを使用することです。
ありがとう
マルティン
解決
Javaシリアル化(ObjectOutputStream
/ObjectInputStream
)オブジェクトをオクテットシーケンスにシリア化する汎用的な方法です。ただし、シリアル化には問題があります。
Uber効率を上げるために、 BigInteger
もっている toByteArray
そして、取るコンストラクター byte[]
. 。次に、表現する方法が必要です byte[]
(長さを含む)ストリーム内。たとえば、使用できます DataOutputStream
に writeInt
長さ、そして生データを使用してそれに従います。
もちろん、ストリームは、選択した適切なデコレーターで圧縮できます。
他のヒント
私はObjectOutputStreamを使用します。それが設計されたものです(特にBigintegerではなく、クラス)。
ここに、圧縮されたObjectoutPustemsと非圧縮されていない両方の両方のオーバーヘッドを示すクイックサンプルコードがいくつかあります。
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);
はい、ObjectOutputStream/ObjectInputStreamを使用して簡単にするか、BigIntegerをバイト[]に変換して、オブジェクト全体ではなくその値をシリアル化することもできます。後者は、オブジェクト全体をシリアル化する上でかなりの量のストレージスペースを節約します。
また、まだバッファリングされていないストリームクラスを使用している場合は、BufferedOutputStreamとBufferedInputStreamで出力ストリームと入力ストリームを包み、パフォーマンスを向上させ、Flush()を書き終えた後(BufferedOutputStream() inputstreamは、入力を待って停止または吊るすことがあります)。
帯域幅やファイルサイズが心配な場合は、自動圧縮のためにgzipoutputStream/gzipinputStreamでストリームをラップすることもできます。ただし、実際にパフォーマンスの低下や巨大なファイルが観察されない限り、データを圧縮することを心配することはありません。
全体を読み取り/書きたいですか Object
またはそのみ 価値?前者の場合、それを使用します シリアル化. 。後者の場合は、使用するだけです ByteArrayInputStream
/ByteArrayOutputStream
あなたがの結果を書く場所 BigInteger#toByteArray()
そして、の助けを借りて新しいものを構築します new BigInteger(byte[])
それぞれ。最後の方法では、ファイル内のバイトがはるかに少なくなります。