ファイルの 16 進数コンバーターを作成しようとしています (入力ファイル -> ファイルの 16 進文字列を出力)
私が思いついたコードは
static String open2(String path) throws FileNotFoundException, IOException,OutOfMemoryError {
System.out.println("BEGIN LOADING FILE");
StringBuilder sb = new StringBuilder();
//sb.ensureCapacity(2147483648);
int size = 262144;
FileInputStream f = new FileInputStream(path);
FileChannel ch = f.getChannel( );
byte[] barray = new byte[size];
ByteBuffer bb = ByteBuffer.wrap( barray );
while (ch.read(bb) != -1)
{
//System.out.println(sb.capacity());
sb.append(bytesToHex(barray));
bb.clear();
}
System.out.println("FILE LOADED; BRING IT BACK");
return sb.toString();
}
「パス」が有効なファイル名であると確信しています。問題は大きなファイル (>= 500mb) にあり、コンパイラは OutOfMemoryError: Java Heap Space を StringBuilder.append に出力します。
このコードを作成するために、http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quicklyのいくつかのヒントに従いましたが、StringBuilder sb にスペースを強制的に割り当てようとしたときに疑問が生じました:「2147483648 は int には大きすぎます」 "。
非常に大きなファイルでもこのコードを使用したい場合 (本当にどこかで停止する必要がある場合は最大 2 GB としましょう) 、ファイルの 16 進文字列変換を出力するより良い方法は速度の点で何ですか?
現在、変換された文字列をファイルにコピーする作業を行っています。とにかく、元のファイルの eof の後に「ファイルに空のバッファを書き込む」という問題があります。
static String open3(String path) throws FileNotFoundException, IOException {
System.out.println("BEGIN LOADING FILE (Hope this is the last change)");
FileWriter fos = new FileWriter("HEXTMP");
int size = 262144;
FileInputStream f = new FileInputStream(path);
FileChannel ch = f.getChannel( );
byte[] barray = new byte[size];
ByteBuffer bb = ByteBuffer.wrap( barray );
while (ch.read(bb) != -1)
{
fos.write(bytesToHex(barray));
bb.clear();
}
System.out.println("FILE LOADED; BRING IT BACK");
return "HEXTMP";
}
明らかに、作成された HEXTMP ファイルのサイズは 256k の倍数ですが、ファイルが 257k の場合、末尾に「000000」の LOT を持つ 512 ファイルになります。カットされた長さの最後のバイト配列を作成する必要があることはわかっています。
(16進数の文字列を書きたかったので、ファイルライターを使用しました。そうしないと、ファイルをそのままコピーしただけです)