0
    read_data = new BufferedReader( new FileReader(args[0]) );
    data_buffer = new StringBuffer();

    int i;

    while(read_data.ready())
    {           
        while((i = read_data.read()) != -1)
        {
            data_buffer.append((char)i);
        }           
    }

    data_buffer.append(System.getProperty("line.separator"));

我想要做的是,将整个 .txt 文件读入字符串并在字符串中附加一个换行符。然后可以通过传递 data_buffer.toString() 创建一个新的 Scanner 来处理这个字符串。显然,对于非常大的文件,此过程会占用大量时间,而我要做的只是将换行符附加到已读入内存的 .txt 文件中。

我知道整个想法似乎有点古怪或奇怪,但有没有更快的方法?

干杯:)

4

3 回答 3

3

做某事的最快方法往往是根本不做。

为什么不以不需要末尾换行符的方式修改解析代码?如果您每次都附加它,您也可以更改代码以使其表现得好像它在那里,而实际上它并不存在。

接下来我要尝试的是避免逐个字符地创建一个巨大的字符串,因为这确实相当昂贵。您可以Scanner基于 an创建一个,它可能比将数据读入并解析它InputStream要快得多。String您可以覆盖您FileInputStream以在文件末尾返回一个虚拟换行符,从而避免粘贴字符串的实例化。

如果您确实必须将数据读入缓冲区,那么使用基于数组read()的流方法读取字节数组可能会更好 - 比逐字节快得多。由于您可以提前知道文件的大小,因此您可以为缓冲区分配空间以放置额外的行尾标记并将其插入数组中。与创建 aStringBuffer并从中制作 a 相比String,这不需要缓冲区的完整副本。

于 2012-04-22T14:41:14.267 回答
2

据我所知,您实际上要做的是以这样一种方式读取文件,即在最后一行的末尾似乎总是有一个行分隔符。

如果是这种情况,那么您可以通过实现 的子类型来做到这一点FilterReader,并在到达字符流末尾时让它“插入”一个或两个额外的字符。

执行此操作的代码不会是微不足道的,但它会避免在内存中缓冲整个文件的时间和空间开销。

于 2012-04-22T14:54:27.697 回答
1

如果您所做的只是将生成的文件传递给 Scanner,您应该为该文件创建一个 Readable 并将其发送给 Scanner。

这是一个示例(未经测试):

public class NLReader implements Readable {

    Reader r;
    boolean atEndOfReader = false;
    boolean atEnd = false;

    public NLReader(Reader r) {
        this.r = r;
    }

    public int read(CharBuffer cb) throws IOException {
        if (!atEndOfReader) {
            int result = r.read(cb);
            if (result == -1) {
                atEndOfReader = true;
            } else {
                return result;
            }
        }
        if (!atEnd) {
            String nl = System.getProperty("line.separator");
            cb.append(nl);
            atEnd = true;
            return nl.length();
        }

        return -1;
    }
}

这只会读取文件一次,从不复制它(与您的 StringBuffer 不同——除非您真的需要 StringBuffer 的同步,否则您应该使用 StringBuilder)。

这也不会将实际文件加载到内存中,因此也可以节省内存压力。

于 2012-04-22T14:51:02.987 回答