首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java.io :性能调优

Java.io :性能调优
EN

Stack Overflow用户
提问于 2012-04-10 19:06:26
回答 3查看 2.1K关注 0票数 4

我有一个大约4MB的文件,该文件是一个只包含正常键盘字符的ascii文件。我尝试了java.io包中的许多类,以字符串形式读取文件内容。逐个字符地读取它们(使用FileReader和BufferedReader)大约需要40秒,使用java.nio包(FileChannel和ByteBuffer)读取内容大约需要25秒。据我所知,这需要更多的时间。有没有人知道如何将消耗的时间减少到10秒左右?甚至像使用C创建文件读取器和从java调用这样的解决方案也可以。我使用下面的代码片段在22秒内读取了4MB的文件-

代码语言:javascript
复制
public static String getContents(File file) {
    try {
        if (!file.exists() && !file.isFile()) {
            return null;
        }
        FileInputStream in = new FileInputStream(file);
        FileChannel ch = in.getChannel();
        ByteBuffer buf = ByteBuffer.allocateDirect(512);            
        Charset cs = Charset.forName("ASCII");          
        StringBuilder sb = new StringBuilder();
        int rd;
        while ((rd = ch.read(buf)) != -1) {
            buf.rewind();
            CharBuffer chbuf = cs.decode(buf);
            for (int i = 0; i < chbuf.length(); i++) {
                sb.append(chbuf.get());
            }
            buf.clear();
        }
        String contents = sb.toString();
        System.out.println("File Contents:\n"+contents);
        return contents;
    } catch (Exception exception) {
        System.out.println("Error:\n" + exception.getMessage());
        return null;
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-10 19:09:59

我无法想象你的硬件是什么,但对于一个4MB的文件来说,它应该只需要不到0.1秒的时间。

一次读取所有文件的快速方法是将其读取到byte[]中

代码语言:javascript
复制
public static String readFileAsString(File file) {
    try {
        DataInputStream in = new DataInputStream(FileInputStream(file));
        byte[] bytes = new byte[(int) file.length()];
        in.readFully(bytes);
        in.close();
        return new String(bytes, 0); // ASCII text only.

    } catch (FileNotFoundException e) {
        return null;
    } catch (IOException e) {
        System.out.println("Error:\n" + e.getMessage());
        return null;
    }
}

public static void main(String... args) throws IOException {
    File tmp = File.createTempFile("deleteme", "txt");
    tmp.deleteOnExit();

    byte[] bytes = new byte[4 * 1024 * 1024];
    Arrays.fill(bytes, (byte) 'a');
    FileOutputStream fos = new FileOutputStream(tmp);
    fos.write(bytes);
    fos.close();

    long start = System.nanoTime();
    String s = readFileAsString(tmp);
    long time = System.nanoTime() - start;
    System.out.printf("Took %.3f seconds to read a file with %,d bytes%n",
            time / 1e9, s.length());
}

打印

代码语言:javascript
复制
Took 0.026 seconds to read a file with 4,194,304 bytes

如果您想更快地读取文件,我建议使用内存映射文件,因为它将花费不到10毫秒,但在这种情况下,这是过度杀伤力。

票数 5
EN

Stack Overflow用户

发布于 2012-04-11 08:36:51

  1. 在这里使用直接字节缓冲区没有好处。
  2. 你的缓冲区大小512太小了。至少使用4096。
  3. 在这里使用NIO没有实际的好处。由于这是文本,我会使用BufferedReader.
  4. Your basic目标将整个文件读入内存是有缺陷的。它不会扩展,而且它已经使用了过多的内存。您应该设计一种策略,一次处理一行文件。
票数 2
EN

Stack Overflow用户

发布于 2012-04-10 19:10:57

你可以增加你的缓冲区大小,比如2048或4096字节。

不要使用原生API,因为你不会得到像编译时类型检查这样的Java特性。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10087534

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档