我试图制作一个十六进制文件转换器(输入文件 - >输出文件的十六进制字符串)
我提出的代码是
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),编译器在StringBuilder.append上输出OutOfMemoryError:Java堆空间。
为了创建这段代码,我遵循了http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly的一些提示,但是当我试图强制为StringBuilder sb强制空间分配时,我有一个疑问:" 2147483648对于int"来说太大了。
如果我想使用这个代码,即使是非常大的文件(如果我真的必须停在某处,请说高达2gb)输出十六进制字符串转换的更好方法文件的速度?
我现在正致力于将转换后的字符串复制到文件中。无论如何,我遇到了#34;在文件上写入空缓冲区的问题"在原来的那个之后。
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,那么它将是一个512文件,其中有很多" 000000"在末尾。 我知道我只需创建一个具有剪切长度的最后一个字节数组。
(我使用文件编写器,因为我想编写十六进制的字符串;否则它会按原样复制文件)
答案 0 :(得分:2)
为什么要加载完整的文件?
您可以从输入文件中加载缓冲区中的几个字节,在缓冲区中处理字节,然后将处理后的字节缓冲区写入输出文件。继续这个直到输入文件中的所有字节都不被处理。
FileInputStream fis = new FileInputStream("in file");
FileOutputStream fos = new FileOutputStream("out");
byte buffer [] = new byte[8192];
while(true){
int count = fis.read(buffer);
if(count == -1)
break;
byte[] processed = processBytesToConvert(buffer, count);
fos.write(processed);
}
fis.close();
fos.close();
所以只需读取缓冲区中的几个字节,将其转换为十六进制字符串,从转换后的十六进制字符串中获取字节,然后将这些字节写回文件,并继续接下来的几个输入字节。
答案 1 :(得分:0)
这里的问题是您尝试读取整个文件并将其存储在内存中。 您应该使用流,读取输入文件的某些行,转换它们并将它们写入输出文件中。这样,无论输入文件的大小如何,您的程序都可以扩展。
答案 2 :(得分:0)
关键是要以块的形式读取文件,而不是一次性读取所有文件。根据其用途,您可以改变块的大小。例如,如果您尝试使十六进制查看器/编辑器确定视口中显示的内容量,并且只读取文件中的数据量。或者,如果您只是将十六进制转换并转储到另一个文件,请使用足够小的块大小以适合内存但大到足以提高性能。这应该可以在某些运行中进行调整。也许在Java 7中使用文件系统NIO,以便您可以同时执行所有三个任务 - 读取,处理和写入。所包含的链接提供了阅读文件的良好入门。