Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在大文件中循环时内存不足处理-Java_Java_Sorting_Memory Management_Java.util.scanner_File Handling - Fatal编程技术网

在大文件中循环时内存不足处理-Java

在大文件中循环时内存不足处理-Java,java,sorting,memory-management,java.util.scanner,file-handling,Java,Sorting,Memory Management,Java.util.scanner,File Handling,我遇到了一个问题,我在一个过大(大约2gb)的文件中循环。运行大约5分钟后,我发现以下问题:OutOfMemoryError:超出了GC开销限制 我的代码如下,比较干净: import java.io.File; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.Sc

我遇到了一个问题,我在一个过大(大约2gb)的文件中循环。运行大约5分钟后,我发现以下问题:OutOfMemoryError:超出了GC开销限制

我的代码如下,比较干净:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;

public class Organiser {
    public static void main(String[] args) throws FileNotFoundException {
        ArrayList<String> lines = new ArrayList<>();
        String directory = "C:\\Users\\xxx\\Desktop\\Files\\combined";
        Scanner fileIn = new Scanner(new File(directory + ".txt"));
        while (fileIn.hasNextLine() == true) {
            lines.add(fileIn.nextLine());
            System.out.println("Reading.");
            System.out.println("Reading..");
            System.out.println("Reading...");
            }

        PrintWriter out = new PrintWriter(directory + "_ordered.txt");
        Collections.sort(lines);
        System.out.println("Ordering...");
        for (String output : lines) {
            out.println(output + "\n");
        }       
        out.close();
        System.out.println("Complete - See " + directory + "_ordered.txt");
    }
}
导入java.io.File;
导入java.io.FileNotFoundException;
导入java.io.PrintWriter;
导入java.util.ArrayList;
导入java.util.Collections;
导入java.util.Scanner;
公开课组织者{
公共静态void main(字符串[]args)引发FileNotFoundException{
ArrayList行=新的ArrayList();
String directory=“C:\\Users\\xxx\\Desktop\\Files\\combined”;
Scanner fileIn=new Scanner(新文件(目录+“.txt”);
while(fileIn.hasNextLine()==true){
line.add(fileIn.nextLine());
System.out.println(“读取”);
System.out.println(“读取…”);
System.out.println(“读取…”);
}
PrintWriter out=新的PrintWriter(目录+“_ordered.txt”);
集合。排序(行);
System.out.println(“订购…”);
for(字符串输出:行){
out.println(输出+“\n”);
}       
out.close();
System.out.println(“完成-请参阅“+directory+”_ordered.txt”);
}
}

想知道我该如何解决这个问题吗?

要对非常大的文件进行排序,您可能需要执行一个合并排序,该排序可以容纳内存中的最大数量。这就是
排序
unix实用程序的工作方式。注意:您可以从Java运行
sort
,而不是自己实现它


一个更简单的选择是为进程提供更多内存。您将需要大约5 GB或更多的堆。当UTF-16像Java一样编码时,2 GB的编码文本将变成4 GB,并为数据结构的其余部分留出空间。

不要一次读取完整的文件,而是分块读取

有关一次读取字节的信息,请参阅

示例代码:

try {
    File file = new File("myFile");
    FileInputStream is = new FileInputStream(file);
    byte[] chunk = new byte[1024];
    int chunkLen = 0;
    while ((chunkLen = is.read(chunk)) != -1) {
        // your code..
    }
} catch (FileNotFoundException fnfE) {
    // file not found, handle case
} catch (IOException ioE) {
    // problem reading, handle case
}
希望这能给你一个想法

这并不完全是Java的问题。您需要研究一种有效的算法来对未完全读入内存的数据进行排序。对合并排序进行一些调整可以实现这一点

看看这个:

以及:


基本上,这里的想法是将文件分成更小的部分,对它们进行排序(使用合并排序或其他方法),然后使用“合并自合并排序”创建新的已排序文件。

如果您的文件包含拉丁-1符号,您可以节省一些内存,将行存储在UTF-8
ByteBuffer中,而不是
String
String
以UTF-16表示,仅拉丁语-1输入可能占用2倍的内存):

导入java.nio.ByteBuffer;
导入java.nio.charset.StandardCharset;
...
ArrayList行=新的ArrayList();
...
while(fileIn.hasNextLine()==true){
add(ByteBuffer.wrap(fileIn.nextLine().getBytes(StandardCharsets.UTF_8));
...
for(字节缓冲输出:行){
println(新字符串(output.array(),StandardCharsets.UTF_8));
}       
...

与简单的
byte[]不同,
数组
ByteBuffer
具有可比性,因此可以进行排序。

在启动程序时尝试指定java VM选项。 如果您使用的是IDE,请转到运行配置,并提供
-Xmx
-Xms
标志,其中包含排序大文件内容所需的值。将其设置为大约4GB的高值,并将字符串内容包装为
UTF-8
编码的
字节缓冲
而不是
UTF-16
可以救命啊

    javac Organiser.java
    java -Xms1024m -Xmx4096m Organiser

当您看到一个
OutOfMemoryException
,是时候优化您的程序以降低内存消耗了

您可以实现的一些典型“轻松收获”:

  • 不要使用
    ArrayList
    Collections.sort
    对大量数据进行排序:而是使用
    TreeSet,
    自动按照自然顺序对其项进行排序
  • 如果这还不够,请通过
    -Xmx
    选项增加JVM内存
看看这篇类似的帖子:

要么保留较小的文件,要么调整分配的内存。您正在将所有行添加到一个列表中,因此RAM,然后再对它们进行排序,这会导致
OutOfMemoryError
。您唯一的选择是在将它们添加到
\u ordered.txt
时对它们进行排序。不要累积列表。请阅读该行,然后重试proceed@ravindra那个这将是我的答案,但OP需要对行进行排序。to希望对输入文件的行进行排序。
    javac Organiser.java
    java -Xms1024m -Xmx4096m Organiser