【问题标题】:Read tens of thousands of Files and write to millions of files in Java用Java读取数万个文件并写入数百万个文件
【发布时间】:2016-08-22 09:50:47
【问题描述】:

我正在做一些不寻常的数据操作。我有 36,000 个输入文件。更多则可以一次加载到内存中。我想获取每个文件的第一个字节并将其放入一个输出文件中,然后对第二个文件再次执行此操作,依此类推。它不需要以任何特定的顺序完成。因为输入文件是压缩的,加载它们需要更长的时间,并且一次不能读取 1 个字节。我最终得到每个输入文件的字节数组。

输入文件大约为 ~1-6MB 未压缩和 ~.3-1MB 压缩(有损压缩)。输出文件最终是输入文件的字节数。在我的示例中约为 36KB。

我知道 ulimit 可以在 Linux 操作系统上设置,等效的可以在 Windows 上完成。即使这个数字可以提高,我认为任何操作系统都不会喜欢同时写入数百万个文件。

我目前的解决方案是制作 3000 个左右的缓冲写入器流并依次加载每个输入文件并将 1 个字节写入 3000 个文件,然后关闭文件并加载下一个输入。使用这个系统,每个输入文件都需要打开大约 500 次。

整个操作需要 8 天才能完成,并且只是一个更实际的应用程序的测试用例,最终会产生更大的输入文件、更多的文件和更多的输出文件。

在内存中捕获所有压缩文件,然后根据需要解压缩它们听起来不切实际,并且不会扩展到更大的输入文件。

我认为解决方案是从输入文件中缓冲我可以缓冲的内容(因为内存限制不允许缓冲所有内容),然后按顺序写入文件,然后重新执行。

但是我不知道是否有更好的解决方案使用我没有读过的东西。

编辑 我很感谢您的快速反应。我知道我在应用我正在做的事情时含糊其辞,我会努力纠正它。我基本上有一个三维数组 [images][X][Y] 我想遍历每个图像并保存每个图像上特定像素的每种颜色,并对所有图像执行此操作。问题是内存限制。

byte[] 像素 = ((DataBufferByte) ImageIO.read( fileList.get(k) ).getRaster().getDataBuffer()).getData();

这是我用来加载图像的方法,因为它负责解压缩和跳过标题。

我没有将它作为视频进行编辑,因为我必须先获取一帧,然后将其转换为图像(代价高昂的色彩空间转换),然后再将其转换为字节 [] 以获得像素数据 int RGB色彩空间。

我可以加载每个图像并将其拆分为约 500 个部分(Y 大小)并写入我保持打开并为每个图像写入的单独文件。输出很容易在演出下。生成的文件可以完全加载到内存中,并变成一个数组用于顺序文件写入。

中间步骤确实意味着我可以在网络上分担负载,但我试图在具有 4gb 内存、没有 GPU 和低质量 i7 的低质量笔记本电脑上完成它。

在阅读 davidbak 的回复之前,我没有考虑将任何内容保存到文件中作为中间步骤。大小是唯一让这个问题变得不简单的因素,我现在看到大小可以分成更小更易于管理的块。

【问题讨论】:

  • 不确定第 3 部分是什么。您需要解压缩文件并将前几个字节附加到文件中吗?为什么要 3,000 个文件?如果你有超过 8 台服务器可以使用 hadoop
  • 对于给定的运行,输入的大小都相同,但运行之间的大小可能非常大,文件数量也非常多。如果它是每个 1MB 和 36000 个文件,那么它将是一个 36GB 的文件,这是低端的东西。然后我可以以一种非常可预测的方式读取该文件。我需要的每个字节恰好相隔 1MB(一个输入文件的大小),但请记住将其组装成一个大文件所需的时间,这真的快得多吗?它会将 36 个演出的每个字节加载然后卸载到内存中,以完成 1 个文件。它将执行 100 万次。

标签: java large-data-volumes


【解决方案1】:

三阶段操作:

第一阶段:读取所有输入文件,一次一个,然后写入单个输出文件。输出文件将是面向记录的——例如,8 字节记录、4 字节“字符偏移”和 4 字节“字符代码点”。当您读取文件时,字符偏移量当然从 0 开始,所以如果输入文件是“ABCD”,您正在编写 (0, A) (1, B) (2, C) (3, D) .每个输入文件打开一次,按顺序读取并关闭。输出文件打开一次,顺序写入,然后关闭。

第二阶段:使用外部排序,在4字节字符偏移字段上对中间文件的8字节记录进行排序。

第三阶段:打开已排序的中间文件并通过它。每次字符索引字段更改时打开一个新的输出文件,并将属于该索引的所有字符写入该输出文件。输入文件打开一次并按顺序读取。每个输出文件都会打开,顺序写入,然后关闭。

瞧!您需要用于中间文件的空间,以及良好的外部排序(以及用于其工作文件的空间)。

正如@Jorge 建议的那样,阶段 1 和阶段 2 都可以并行化,事实上,概述的这类工作(阶段 1 到 3)正是 mapreduce/hadoop 的最佳选择。

【讨论】:

    【解决方案2】:

    你在那里很模糊,但是,也许看看 mapreduce 会有所帮助。这似乎是一种可以分配的工作。

    根据您提供的其他信息,我真的不知道如何在您提到的 4GB i7 等常见硬件上执行该任务。你的问题看起来像是一个图像堆叠算法,可以从很多不太好的图像中得到一个像样的图像,这是天文图像处理中的一个典型问题,我相信它也适用于其他领域。好好查找天文成像处理可能会很好地利用您的时间,有一个名为 registax 的软件(不确定它是否仍然存在)可以做类似的事情,但会处理视频文件。

    如果你花 1 秒钟打开一个文件,你会得到 10 小时的文件打开时间。

    一种方法是获取一些 FAST 磁盘 (SSD),我会将所有文件解压缩为某种原始格式并将它们存储在磁盘上,从那里您将不得不使用文件指针直接从文件而不将它们放入内存并将输出写入文件,直接在磁盘上。

    【讨论】:

    • 感谢指向 RegiStax(still exists)的指针 - 我完全不知道该类别的图像处理软件。
    猜你喜欢
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2015-06-02
    相关资源
    最近更新 更多