读取数以万计的文件并写入Java中的数百万个文件

时间:2016-04-27 21:12:39

标签: java large-data-volumes

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

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

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

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

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

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

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

但是我不知道是否有更好的解决方案使用我没有阅读的内容。

修改 我很感激快速反应。我知道我在应用我正在做的事情时模糊不清,我会尽力纠正这一点。我基本上有一个三维数组[图像] [X] [Y]我想迭代每个图像并从每个图像上的特定像素保存每种颜色,并为所有图像执行此操作。问题是内存限制。

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

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

我不是将其编辑为视频,因为我必须得到一个帧,然后将其转换为图像(昂贵的色彩空间转换),然后将其转换为byte []以获取像素数据RGB RGB色彩空间。

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

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

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

2 个答案:

答案 0 :(得分:5)

三阶段操作:

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

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

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

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

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

答案 1 :(得分:2)

你在那里非常模糊,但是,看看mapreduce可能有所帮助。这似乎是一种可以分发的工作。

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

如果你花1秒钟打开一个文件就可以回收一些餐巾纸数据,你只需要10小时的文件打开。

一种方法是获得一些FAST磁盘(SSD),我将所有文件解压缩成一些原始格式并将它们存储在磁盘上,从那里你必须使用文件指针直接从文件没有进入内存,直接在磁盘上将输出写入文件。