Java 在 Windows 上读取文件非常慢

Posted

技术标签:

【中文标题】Java 在 Windows 上读取文件非常慢【英文标题】:Java reads files very slowly on Windows 【发布时间】:2012-04-28 15:58:59 【问题描述】:

有人对不同平台上文件 IO 的差异有任何经验吗?我编写了一个 LWJGL 程序,它可以传输 100+ MB TIFF 文件。流式传输在多台 Mac 和 Linux 计算机上发生得相当快,但在我的 64 位 Windows 7 桌面上,加载地图的每个图块似乎需要几秒钟。

基本上,我创建了一个 Tile 类实例的二维数组。每个 tile 是 TIFF 文件的 512x512 MB 区域,render 方法检查内存中的 tile 区域是否已加载,如果没有,加载将在 ThreadPoolExecutor 中排队,如果已排队则没有任何反应,如果已加载,则画。对 TIFF 的访问由 TIFF 类处理,该类使用 RandomAccessFile 实例读取文件。这是我用来从 TIFF 读取图块的函数

public BufferedImage getRasterTile(Rectangle area) 
    BufferedImage image = new BufferedImage(area.width, area.height,
            BufferedImage.TYPE_INT_RGB);
    try 
        long[] bytesPerSample = new long[bitsPerSample.length];
        for (int i = 0; i < bytesPerSample.length; i++) 
            bytesPerSample[i] += bitsPerSample[i] / 8 + bitsPerSample[i]
                    % 8 == 0 ? 0 : 1;
        
        long bytesPerPixel = 0;
        for (long bits : bitsPerSample) 
            bytesPerPixel += bits / 8 + bits % 8 == 0 ? 0 : 1;
        
        long bytesPerRow = bytesPerPixel * imageWidth;
        int strip, color;
        byte red, green, blue;
        for (int i = area.x; i < area.x + area.width; i++) 
            for (int u = area.y; u < area.y + area.height; u++) 
                if (i > 0 && u > 0 && i < imageWidth && u < imageLength) 
                    switch (planarConfiguration) 
                    case Chunky:
                        strip = (int) (u / rowsPerStrip);
                        seek(stripOffsets[strip]
                                + (u - strip * rowsPerStrip)
                                * bytesPerRow + i * bytesPerPixel);
                        red = readByte();
                        green = readByte();
                        blue = readByte();

                        color = (red & 0x0ff) << 16 | (green & 0x0ff) << 8
                                | (blue & 0x0ff);
                        image.setRGB(i - area.x, u - area.y, color);
                        break;
                    case Planar:
                        strip = (u / (int) rowsPerStrip);
                        seek(stripOffsets[strip] + i);
                        red = readByte();
                        seek(stripOffsets[strip + (int) imageLength] + i);
                        green = readByte();
                        seek(stripOffsets[strip + 2 * (int) imageLength]
                                + i);
                        blue = readByte();
                        color = (red & 0x0ff) << 16 | (green & 0x0ff) << 8
                                | (blue & 0x0ff);
                        image.setRGB(i - area.x, u - area.y, color);
                        break;
                    
                 else 
                    image.setRGB(i - area.x, u - area.y, 0);
                
            
        
     catch (IOException e) 
        e.printStackTrace();
        return null;
    
    return image;

【问题讨论】:

我很困惑,你是说读取速度慢(在这种情况下你能告诉我们你是如何读取数据的)还是转换速度慢。 【参考方案1】:

我怀疑这与您阅读文件的方式有关。我注意到您反复调用名为readByte()seek 的方法。如果这些方法在无缓冲流(或RandomAccessFile 实例)上进行调用,那么您可能会进行大量系统调用,这会使您的方法非常慢。

如果这是原因,那么您可能应该将整个图像文件读入byte[],并使用数组索引来找出您需要的字节。如果图像文件太大而无法执行此操作,则您需要重新构建代码以减少查找并一次读取多个字节。

【讨论】:

以上是关于Java 在 Windows 上读取文件非常慢的主要内容,如果未能解决你的问题,请参考以下文章

Qt 读取文件并映射到 QVector 非常慢(崩溃)

使用 UCanAccess 从大文本文件中插入数据非常慢

Python - 垃圾收集非常慢,无法禁用 gc

Java,为啥从 MappedByteBuffer 读取比从 BufferedReader 读取慢

java 读取大文件时怎么样才能加快速度?

利用VBA向excel表格中写入数据后,再次运行程序的话写入速度会非常慢