如何从一个巨大的文件中读取并通过java写入一个新文件

时间:2013-09-05 07:39:00

标签: java

我正在做的是逐行读取一个文件,格式化每一行,然后写入新文件。但问题是文件很大,接近178 MB。 但总是收到错误消息:IO控制台更新程序错误,java堆空间。这是我的代码:

public class fileFormat {
    public static void main(String[] args) throws IOException{

        String strLine;

        FileInputStream fstream = new FileInputStream("train_final.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(fstream));
        BufferedWriter writer = new BufferedWriter(new FileWriter("newOUTPUT.txt"));

        while((strLine = reader.readLine()) != null){
            List<String> numberBox = new ArrayList<String>();
            StringTokenizer st = new StringTokenizer(strLine);
            while(st.hasMoreTokens()){
                numberBox.add(st.nextToken());
            }
            for (int i=1; i< numberBox.size(); i++){
                String head = numberBox.get(0);
                String tail = numberBox.get(i);
                String line = head + "  "+tail ;
                System.out.println(line);
                writer.write(line);
                writer.newLine();
            }
            numberBox.clear();
        }
        reader.close();
        writer.close();
    }
}

如何避免此错误消息?此外,我已设置VM首选项:-xms1024m

4 个答案:

答案 0 :(得分:3)

删除行

System.out.println(line);

这是一个解决方案,它可能会耗尽内存控制台更新程序。

答案 1 :(得分:0)

程序看起来还不错。我怀疑问题是你在Eclipse中运行它,并且Eclipse在内存中收集了System.out(将显示在该控制台窗口中)。

 System.out.println(line);

尝试在Eclipse之外运行它,将Eclipse设置更改为管道System.out,或删除该行。

答案 2 :(得分:0)

这部分代码:

       for (int i=1; i< numberBox.size(); i++){
            String head = numberBox.get(0);
            String tail = numberBox.get(i);
            String line = head + "  "+tail ;
            System.out.println(line);
            writer.write(line);
            writer.newLine();
       }

可以翻译成:

       String head = numberBox.get(0);
       for (int i=1; i< numberBox.size(); i++){
            String tail = numberBox.get(i);
            System.out.print(head);
            System.out.print(" ");
            System.out.println(tail);
            writer.write(head);
            writer.write(" ");
            writer.write(tail);
            writer.newLine();
       }

这可能会添加一些代码重复,但它可以避免创建大量对象。

此外,如果您将此for循环与构造numberBox的循环合并,则根本不需要numberBox结构。

答案 3 :(得分:0)

如果您读取整个文件,堆内存将占用更好的选项来读取chuck中的文件。请参阅下面的代码。它将从参数中给出的偏移量开始读取并返回结束偏移量。您需要传递要读取的行数。

请记住:在调用此方法读取下一个块之前,您可以使用任何集合来存储这些读取行并清除集合。

FileInputStream fis = new FileInputStream(file);
InputStreamReader   streamReader = new InputStreamReader(fis, "UTF-8");
LineNumberReader   reader = new LineNumberReader(streamReader);

//以递归方式调用此方法,直到文件没有到达结尾

public int getParsedLines(LineNumberReader reader, int iLineNumber_Start, int iNumberOfLinesToBeRead) {
    int iLineNumber_End = 0;

    int iReadUptoLines = iLineNumber_Start + iNumberOfLinesToBeRead;

    try {
        reader.mark(iLineNumber_Start);
        reader.setLineNumber(iLineNumber_Start);
        do {
            String str = reader.readLine();
            if (str == null) {
                break;
            }
            // your code


            iLineNumber_End = reader.getLineNumber();
        } while (iLineNumber_End != iReadUptoLines);
    } catch (Exception ex) {
        // exception handling
    }
    return iLineNumber_End;
}