使用 RandomAccessFile 的最佳方式是 Java
Posted
技术标签:
【中文标题】使用 RandomAccessFile 的最佳方式是 Java【英文标题】:Best way to use RandomAccessFile is Java 【发布时间】:2019-02-11 07:00:24 【问题描述】:我正在创建一个实用程序,它使用 RandomAccessFile 将 MSSQL 表 blob 写入数据磁盘文件。它太慢了,因为我们需要始终寻找最后一个位置并写入流内容..请让我知道任何其他替代方法来加速随机访问文件的写入。
我有超过 5000 万条记录,按照目前的逻辑大约需要 10 个小时。
我的代码块是这样的:
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
InputStream inputStream = null;
while (rows.hasNext())
Row row = rows.next();
inputStream = (InputStream) row.getValues()[0];
offset = randomAccessFile.length();
byte[] buffer = new byte[8196];
int count;
randomAccessFile.seek(offset);
randomAccessFile.setLength(offset);
while ((count = inputStream.read(buffer)) != -1)
randomAccessFile.write(buffer, 0, count);
randomAccessFile.close();
【问题讨论】:
您需要从特定位置写入文件吗?只是想了解您选择 RandomAccessFile 的原因。你也可以使用 BufferedWriter。 写入 50 MB 的数据需要一秒钟。您可以通过仅写入此大小的空白数据来进行测试。如果超过这个,是时候从数据库中提取数据了。 Btw setLength 在 Java 9 和 10 中非常慢。这在 Java 8 和 11 中很好。 【参考方案1】:根据您发布的代码,您只需附加到现有文件即可。在追加模式下使用缓冲写入器可以更轻松、更高效地完成此操作。
因此,使用
BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardOpenOptions.CREATE, StandardOpenOptions.APPEND);
改为。
彼得评论后更新:对于输出流,整个事情基本相同,只是Files
没有“缓冲”部分的便利功能。因此:
OutputStream outputStream = new BufferedOutputStream(Files.newOutputStream(file.toPath(), StandardOpenOption.CREATE, StandardOpenOption.APPEND));
【讨论】:
Writers 用于编写文本。 OP 可能想要一个 BufferedOutputStream。 我们也需要写入二进制数据,我们不知道表中的数据是什么。【参考方案2】:目前,您在每次迭代中写入大约 8 Kb (8196 / 1024) 的数据,并且每次迭代都会执行 I/O 操作,这会阻塞且需要时间。尝试将其增加到至少 1 Mb 大约(10,000,000)。
byte[] buffer = new byte[10000000];
【讨论】:
大于 32KB 的缓冲区可能会变慢,因为它们不适合 L1 数据缓存。 是的..我有一行内容为 1KB 数据,所以我认为当前大小还可以。以上是关于使用 RandomAccessFile 的最佳方式是 Java的主要内容,如果未能解决你的问题,请参考以下文章