将内存超出切片的Java读取和拆分文件

时间:2016-08-26 20:00:24

标签: java split

我有代码读取文件并将其拆分成碎片。这段代码效果很好(我实际上使用了这个真棒网站的先前帖子来制作代码,谢谢大家!)但我想改变这段代码来做两件新事。

  • 首先:我希望代码检查即将拆分的文件是否超出内存。 在这种情况下,我的内存限制为2 GB
  • 第二:如果文件超出内存我想将文件拆分成更小的片段 并按顺序读取和刷新每个切片,直到整个文件被读取并刷新为新的拆分文件。

这是成功运行的代码,它需要一个.txt文件并将其分成10个相等的部分。

package tyler_test;
import java.io.*;

public class testFileSplit 
{
    public static void main(String[] args) throws Exception
{
    RandomAccessFile raf = new RandomAccessFile("File", "r");
    long numSplits = 10; //how many file splits we want
    long sourceSize = raf.length();
    long bytesPerSplit = sourceSize/numSplits ;
    long remainingBytes = sourceSize % numSplits;

    int maxReadBufferSize = 8 * 1024; //8KB
    for(int i=1; i <= numSplits; i++) 
    {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+i));

        if(bytesPerSplit > maxReadBufferSize) 
        {
            long numReads = bytesPerSplit/maxReadBufferSize;
            long numRemainingRead = bytesPerSplit % maxReadBufferSize;
            for(int j=0; j<numReads; j++) 
            {
                readWrite(raf, bw, maxReadBufferSize);
            }

            if(numRemainingRead > 0) 
            {
                readWrite(raf, bw, numRemainingRead);
            }
        }

        else 
        {
            readWrite(raf, bw, bytesPerSplit);
        }
        bw.close();
    }

    if(remainingBytes > 0) 
    {
        BufferedOutputStream bw = new BufferedOutputStream(new FileOutputStream("split."+(numSplits+1)));
        readWrite(raf, bw, remainingBytes);
        bw.close();
    }
        raf.close();
}

static void readWrite(RandomAccessFile raf, BufferedOutputStream bw, long numBytes) throws IOException 
{
    byte[] buf = new byte[(int) numBytes];
    int val = raf.read(buf);
    if(val != -1) 
    {
        bw.write(buf);
    }
}

}

如何修改此代码以符合我的新条件?我要感谢大家花时间阅读我的问题并提供帮助,我非常感谢!如果我的问题不够明确,请告诉我,我会修改它。

谢谢大家!

1 个答案:

答案 0 :(得分:0)

[建议] 只需使用好的Java内存映射文件(MappedByteBuffer)。

使用内存映射文件,您可以假装整个文件都在内存中,只需将其视为一个非常大的数组即​​可访问它。

    RandomAccessFile raf = new RandomAccessFile("data.txt", "rw");
    FileChannel fc = raf.getChannel();

    //A MemoryMappedBuffer has a fixed max-size, but the file it’s mapped to is elastic
    MappedByteBuffer in = fc.map(FileChannel.MapMode.READ_WRITE, startPosition, length);

您可以通过设置映射的bufferSize来控制已分配的内存。例如,尝试阅读/映射,即&#34; 512 MB&#34;每个缓冲区并根据需要重复此操作(fileSize)。