Java 读取和存储大型ASCII文件的内容

Java 读取和存储大型ASCII文件的内容,java,ascii,large-files,Java,Ascii,Large Files,我得到了一个538MB的ASCII文件,有16807行,每行有16807个0和1,用空格隔开。我想获取所有这些值并将它们存储在列表列表中,就像将每一行存储在新列表中一样 在上一个项目中,我为一个文本文件编写了下面的代码,但使用ASCII文件时,它会抛出一个Java堆空间错误 ArrayList<ArrayList<String>> listOflists = new ArrayList<ArrayList<String>>(); File

我得到了一个538MB的ASCII文件,有16807行,每行有16807个0和1,用空格隔开。我想获取所有这些值并将它们存储在列表列表中,就像将每一行存储在新列表中一样

在上一个项目中,我为一个文本文件编写了下面的代码,但使用ASCII文件时,它会抛出一个Java堆空间错误

ArrayList<ArrayList<String>> listOflists = new ArrayList<ArrayList<String>>();

    FileInputStream fstream = new FileInputStream("C:\Users...\file.txt");
    DataInputStream in = new DataInputStream(fstream);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));

    while (true)
    {
        String line = br.readLine();
        if (line == null) {
            break;
        }

        Scanner tokenize = new Scanner(line);
        ArrayList<String> tokens = new ArrayList<String>();

        while (tokenize.hasNext()) 
        {
            tokens.add(tokenize.next());
        }
        listOflists.add(tokens);
    }
    br.close();
String inputFile = "C:\Users...\file.txt";

    LinkedList<LinkedList<Character>> charList = new LinkedList<LinkedList<Character>>();

    File file = new File( inputFile );
    Reader reader = new FileReader(file);
    char val = 0;
    int c;
    int iLine = 0;

    while( (c = reader.read()) != -1) {

        val = (char)c;
        charList.add(new LinkedList<Character>());

        if((c == 48) || (c == 49)){ //ascii code for 0 is 48 and for 1 is 49
            charList.get(iLine).add(val);
        }
        if( c == 92 ){ //ascii code for "/" is 92 as to know when it changes line
            iLine++;
     } 
}
reader.close();
ArrayList ListofList=新建ArrayList();
FileInputStream fstream=新的FileInputStream(“C:\Users…\file.txt”);
DataInputStream in=新的DataInputStream(fstream);
BufferedReader br=新的BufferedReader(新的InputStreamReader(in));
while(true)
{
String line=br.readLine();
如果(行==null){
打破
}
扫描器标记化=新扫描器(行);
ArrayList标记=新的ArrayList();
while(tokenize.hasNext())
{
add(tokenize.next());
}
添加(令牌);
}
br.close();
现在我编写了这段代码,但再次抛出Java堆空间错误

ArrayList<ArrayList<String>> listOflists = new ArrayList<ArrayList<String>>();

    FileInputStream fstream = new FileInputStream("C:\Users...\file.txt");
    DataInputStream in = new DataInputStream(fstream);
    BufferedReader br = new BufferedReader(new InputStreamReader(in));

    while (true)
    {
        String line = br.readLine();
        if (line == null) {
            break;
        }

        Scanner tokenize = new Scanner(line);
        ArrayList<String> tokens = new ArrayList<String>();

        while (tokenize.hasNext()) 
        {
            tokens.add(tokenize.next());
        }
        listOflists.add(tokens);
    }
    br.close();
String inputFile = "C:\Users...\file.txt";

    LinkedList<LinkedList<Character>> charList = new LinkedList<LinkedList<Character>>();

    File file = new File( inputFile );
    Reader reader = new FileReader(file);
    char val = 0;
    int c;
    int iLine = 0;

    while( (c = reader.read()) != -1) {

        val = (char)c;
        charList.add(new LinkedList<Character>());

        if((c == 48) || (c == 49)){ //ascii code for 0 is 48 and for 1 is 49
            charList.get(iLine).add(val);
        }
        if( c == 92 ){ //ascii code for "/" is 92 as to know when it changes line
            iLine++;
     } 
}
reader.close();
String inputFile=“C:\Users…\file.txt”;
LinkedList charList=新建LinkedList();
文件文件=新文件(inputFile);
Reader Reader=新文件读取器(文件);
char-val=0;
INTC;
内线=0;
而((c=reader.read())!=-1){
val=(char)c;
添加(新的LinkedList());
如果((c==48)| |(c==49)){//0的ascii码是48,1的ascii码是49
charList.get(iLine.add)(val);
}
若(c==92)“/”的{//ascii码为92,则知道它何时更改行
iLine++;
} 
}
reader.close();
有什么想法吗?

你的名单是空的

LinkedList<LinkedList<Character>> charList = new LinkedList<LinkedList<Character>>();

从空列表中,因此引发IndexOutOfBoundsException。

您正在为while循环的每一次迭代添加一个新的
LinkedList
,该行为
charList.add(new LinkedList()),即使行没有改变。

我不知道我以前代码中的错误具体在哪里,但这里有一个解决方案,我读取文件并将1的位置存储在列表中(首先是列,然后是找到它的行)。 为了提供更多帮助,我还更改了项目的VM选项,并添加了-Xmx1g As以增加堆大小。如果没有这个,我会得到一个OutOfMemory错误(在3G RAM系统中运行代码)

String inputFile=“C:\Users\…\file.txt”;
FileInputStream in=新的FileInputStream(inputFile);
FileChannel ch=in.getChannel();
ByteBuffer buf=ByteBuffer.allocate(1024);
ArrayList=新建ArrayList();
int列=-1;
int行=0;
国际公路;
而((rd=ch.read(buf))!=-1){
buf.flip();
while(buf.haslaining()){
byte byteVal=buf.get();
如果((字节值==48)| |(字节值==49)){//0的ascii码是48,1的ascii码是49
列++;
}
若(byteVal==92)“/”的{//ascii码为92,则知道它何时更改行
行++;
列=0;
}
if(字节==49){
列表。添加(列);
列表。添加(行);
}
}
buf.clear();
}
ch.close();

增加堆内存,或以占用内存较少的方式存储。我使用-Xmx1024m增加堆内存,但错误仍然存在,问题的目的是找到占用内存较少的方式,因为我找不到。这样做有什么意义?读取文件并将其存储在一个位字段中,这将大大减少内存使用量。我只是表明我发布了错误的代码,我编辑了我的问题并发布了正确的问题,该问题引发了IndexOutOfBounds异常,但Java堆空间错误。但是您的注释对于前面的代码是正确的。请增加堆大小。例如,这个参数-Xmx1024m将为您提供1024MB的Java堆空间。我这样做了,但同样的问题是Java堆空间。您将整个文件读取到内存中。试着更有效地阅读它。检查此链接,或者您可以尝试为堆大小指定一个更大的值,如-Xmx4g(4GB)-我不知道您的RAM数量。我有3GB RAM,但即使使用-Xmx1g,内存不足错误仍然存在,堆大小越大,虚拟机初始化就有问题。是的,但如果没有这个值,我会得到IndexOutOfBounds异常,而不是修复该错误,您决定添加这么多
列表
,而不是获取
索引AutofBoundsException
,您的内存会用完吗?您只需要为每一行添加一个列表,当然在循环之前为第一行添加列表。所以我认为问题不在于清单,清单是你的主要问题。次要的部分是你的代码错了,主要的部分是你试图把字符加载到一个列表中,这是一个非常糟糕的选择。你从来没有说过你要用字符列表做什么,但我敢打赌,你要做的事情有一个更好的数据结构。这个文件就像一个数组16807x16807,以0和1为元素,我想把它存储在某个地方,以便知道我在哪一列和哪一行中得到了1,在哪一行中得到了0。如果你有另一个想法,在哪里存储的数据作为代码要与此格式的不同文件的功能,请让我知道。