如何有效地篡改非常大的文本文件的内容?

时间:2015-12-09 01:30:07

标签: java file-io

我正在阅读一些非常大的文本文件并遇到Java - Char Buffer Issue中描述的错误。

当我有一个非常大的文件(> 1gb)时,Charset.defaultCharset().decode(ByteBuffer bb).toString()会抛出一个IllegalArgumentException。大概是因为缓冲容量溢出并变成负数。

这是我一直在使用的啜食功能:

public static String slurp(File f) throws IOException, FileNotFoundException
    {
        FileInputStream fis = new FileInputStream(f);
        try{
            FileChannel fc = fis.getChannel();
            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());

            //The decode method on the following line throws the IllegalArgumentException
            return Charset.defaultCharset().decode(bb).toString();
        }finally{
            fis.close();
        }
    }

我想简单地为此函数添加错误处理,以便在抛出异常时使用另一种更安全的方法,例如How do I create a Java string from the contents of a file?中的问题语句中的模式

例如,

public static String slurp(File f) throws IOException, FileNotFoundException
    {
        FileInputStream fis = new FileInputStream(f);
        try{
            FileChannel fc = fis.getChannel();
            MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
            return Charset.defaultCharset().decode(bb).toString();
        } catch (IllegalArgumentException e) {
            // This exception is thrown by extremely large files
            BufferedReader reader = new BufferedReader(new FileReader(f));
            String line = null;
            StringBuilder stringBuilder = new StringBuilder();
            String ls = System.getProperty("line.separator");

            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line);
                stringBuilder.append(ls);
            }

            return stringBuilder.toString();

        }finally{
            fis.close();
        }
    }

另一种方法是在同一个问题上使用效率最高的建议答案。

public static String slurp(File f) throws IOException, FileNotFoundException
{
    FileInputStream fis = new FileInputStream(f);
    try{
        FileChannel fc = fis.getChannel();
        MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
        return Charset.defaultCharset().decode(bb).toString();
    } catch (IllegalArgumentException e) {
        // This exception is thrown by extremely large files
        List<String> lines = Files.readAllLines(f.toPath(), Charset.defaultCharset());
        return String.join("/n", lines);

    }finally{
        fis.close();
    }
}

任何大文件在内存时都会变得很麻烦,而不是流式传输,但有没有理由更喜欢这两种方法中的一种或其他什么?

我问,因为问题的接受答案讨论了两个答案解决方案的内存利用率,而不是提问者的示例模式。

0 个答案:

没有答案