如何在Java中处理一个巨大的一行文件

前端之家收集整理的这篇文章主要介绍了如何在Java中处理一个巨大的一行文件前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要读取一个巨大的文件(15 GB)并执行一些小的修改(添加一些换行符,以便不同的解析器可以真正地使用它).您可能会认为已经有正常的答案:

> Reading a very huge file in java
> How to read a large text file line by line using Java?

但我的整个文件在一行.

目前我的一般做法是非常基本的:

char[] buffer = new char[X];
BufferedReader reader = new BufferedReader(new ReaderUTF8(new FileInputStream(new File("myFileName"))),X);
char[] bufferOut = new char[X+a little];
int bytesRead = -1;
int i = 0;
int offset = 0;
long totalBytesRead = 0;
int countToPrint = 0;
while((bytesRead = reader.read(buffer)) >= 0){
    for(i = 0; i < bytesRead; i++){
        if(buffer[i] == '}'){
            bufferOut[i+offset] = '}';
            offset++;
            bufferOut[i+offset] = '\n';
        }
        else{
            bufferOut[i+offset] = buffer[i];
        }
    }
    writer.write(bufferOut,bytesRead+offset);
    offset = 0;
    totalBytesRead += bytesRead;
    countToPrint += 1;
    if(countToPrint == 10){
        countToPrint = 0;
        System.out.println("Read "+((double)totalBytesRead / originalFileSize * 100)+" percent.");
    }
}
writer.flush();

经过一番实验,我发现X值超过一百万的值可以提供最佳的速度 – 看起来我每10分钟就会得到2%左右,而X值约为60,000的值在15小时内只有60% .分析显示我花了96%的时间在read()方法中,这绝对是我的瓶颈.在撰写本文时,我的800万X版本在2小时40分钟后已完成文件的32%,以防您想知道如何执行长期.

是否有更好的处理这样大的一行文件方法?像在这里,是否有更快的方法来阅读这种类型的文件,给我一个相对容易的插入换行符的方法

我知道不同的语言或程序可能会很好地处理这个问题,但我将其限制在Java视角.

解决方法

你所做的这个比现在要复杂得多.通过使用标准类提供的缓冲区,您应该获得至少几MB的每秒钟数,而不会有任何麻烦.

这个简单的测试程序在我的电脑上不到2分钟内处理1GB(包括创建测试文件):

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Random;

public class TestFileProcessing {

    public static void main(String[] argv) {

        try {
            long time = System.currentTimeMillis();
            File from = new File("C:\\Test\\Input.txt");
            createTestFile(from,StandardCharsets.UTF_8,1_000_000_000);
            System.out.println("Created file in: " + (System.currentTimeMillis() - time) + "ms");

            time = System.currentTimeMillis();
            File to = new File("C:\\Test\\Output.txt");
            doIt(from,to,StandardCharsets.UTF_8);
            System.out.println("Converted file in: " + (System.currentTimeMillis() - time) + "ms");
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(),e);
        }
    }

    public static void createTestFile(File file,Charset encoding,long size) throws IOException {
        Random r = new Random(12345);
        try (OutputStream fout = new FileOutputStream(file);
                BufferedOutputStream bout = new BufferedOutputStream(fout);
                Writer writer = new OutputStreamWriter(bout,encoding)) {
            for (long i=0; i<size; ++i) {
                int c = r.nextInt(26);
                if (c == 0)
                    writer.write('}');
                else
                    writer.write('a' + c);
            }
        }
    }

    public static void doIt(File from,File to,Charset encoding) throws IOException {
        try (InputStream fin = new FileInputStream(from);
                BufferedInputStream bin = new BufferedInputStream(fin);
                Reader reader = new InputStreamReader(bin,encoding);
                OutputStream fout = new FileOutputStream(to);
                BufferedOutputStream bout = new BufferedOutputStream(fout);
                Writer writer = new OutputStreamWriter(bout,encoding)) {
            int c;
            while ((c = reader.read()) >= 0) {
                if (c == '}')
                    writer.write('\n');
                writer.write(c);
            }
        }
    }

}

当您看到没有精心制作的逻辑或使用过多的缓冲区大小.使用的是简单地缓冲最接近硬件的流FileInput / OutputStream.

猜你在找的Java相关文章