我正在将某种文件查看器/文件浏览器实现为Web应用程序。因此,我需要从系统的硬盘中读取文件。当然,我必须处理小文件和大文件,并且我想要最快,最高效的方法。
现在,我有以下代码,如果我使用正确的方法,想问那些对有效读取(大)文件有很多了解的“大佬”:
RandomAccessFile fis = new RandomAccessFile(filename, "r");
FileChannel fileChannel = fis.getChannel();
// Don't load the whole file into the memory, therefore read 4096 bytes from position on
MappedByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, position, 4096);
byte[] buf = new byte[4096];
StringBuilder sb = new StringBuilder();
while (mappedByteBuffer.hasRemaining()) {
// Math.min(..) to avoid BufferUnderflowException
mappedByteBuffer.get(buf, 0, Math.min(4096, map1.remaining()));
sb.append(new String(buf));
}
LOGGER.debug(sb.toString()); // Debug purposes
希望您能帮助我并给我一些建议。
答案 0 :(得分:-1)
当您查看任意文件时,包括潜在的大文件,我认为这些文件实际上不是文本文件,或者您可能会遇到编码不同的文件。
因此,当您尽最大努力查看诸如文本之类的文件时,应考虑要使用哪种编码,并确保失败不会损害您的操作。与new String(buf)
一起使用的构造函数确实会替换无效字符,但是多余的是构造一个新的String
实例,然后将其附加到StringBuilder
上。
通常,您不应该走很多弯路。从Java 7开始,您不需要RandomAccessFile
(或FileInputStream
)即可获得FileChannel
。简单的解决方案看起来像
// Instead of StandardCharsets.ISO_8859_1 you could also use Charset.defaultCharset()
CharsetDecoder decoder = StandardCharsets.ISO_8859_1.newDecoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE)
.replaceWith(".");
try(FileChannel fileChannel=FileChannel.open(Paths.get(filename),StandardOpenOption.READ)) {
//Don't load the whole file into the memory, therefore read 4096 bytes from position on
ByteBuffer mappedByteBuffer = fileChannel.map(MapMode.READ_ONLY, position, 4096);
CharBuffer cb = decoder.decode(mappedByteBuffer);
LOGGER.debug(cb.toString()); // Debug purposes
}
您可以直接对生成的CharBuffer
进行操作,也可以在其上调用toString()
来获取String
实例(但当然,请避免多次执行)。 CharsetDecoder
还允许重复使用CharBuffer
,但是,这可能不会对性能产生太大影响。您绝对应该避免的是将所有这些块连接成一个大字符串。