0

我在将 3D 字节矩阵(作为无符号字节)写入文本文件时遇到问题。矩阵是 3D 的,看起来像wMatrix3D[k][j][i]. 我想将它保存到一个文本文件中,因此这些值由空格分隔,并且每 1,000 个值换行一个新行(每行有 1,000 个像素值,1,000 行构成一个代表图像的 1,000 x 1,000 文本文件)。

目前,我这样做:

BufferedWriter out = new BufferedWriter(new FileWriter(imgout));

//Parse Headers
for(int countHeaderLines = 0; countHeaderLines < numHeaders; countHeaderLines+=1){
    out.write(headers[countHeaderLines] + "\n");
}
System.out.println("Wrote Headers");

//Parse 1,000,000 x 1,000 2D matrix into 3D (1,000 x 1,000) x 1,000 matrix 
System.out.println("Writing main matrix to text...");

//String slice = new String();
for(int k = 0; k < numLayers; k++){
    for(int j = 0;  j < numRows; j++){
        String rowStr = new String();
        for(int i = 0; i < numColumns; i++){
            rowStr += Integer.toString((Integer.valueOf(wMatrix3D[k][j][i]) & 0xFF)) + " ";
        }
    out.write(rowStr + "\n");
    }

/*if( (k+1) % 5 == 0){
slice = new String();
out.write(slice);
System.out.println("Writing Set of 10:" + k);
}*/

System.out.println("k: " + k);
}

但是,这种方式非常非常慢。有没有更有效的方法来做到这一点?在 CI 中使用“fprintf”没有问题,但在 Java 中我无法让它正常工作。

4

4 回答 4

0

Arrays 和bytes 都Serializable在 Java 中。只需通过ObjectOutputStream.

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;

class MatrixWriter {
    public static void main(String... a) throws FileNotFoundException,
            IOException, ClassNotFoundException {

        byte[][][] data = new byte[][][] {
                { { 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 } },
                { { 9, 10 }, { 11, 12 } } };
        String filename = "data.ser";

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(
                filename));
        out.writeObject(data);
        out.close();

        ObjectInputStream in = new ObjectInputStream(new FileInputStream(
                filename));
        byte[][][] array = (byte[][][]) in.readObject();
        in.close();

        for (byte[][] b : array) {
            System.out.print("[");
            for (byte[] c : b) {
                System.out.print(Arrays.toString(c));
            }
            System.out.println("]");
        }
    }
}
于 2012-06-20T04:47:32.863 回答
0

您在其他答案中获得的大部分输入都是正确的。但是找出导致性能问题的最佳方法是分析您的应用程序。Netbeans IDE 实际上内置了一个不错的分析器。如果您要分析您的应用程序,最好使用矩阵的子集(我尝试了 200^3 次迭代),您会注意到字符串操作是您的问题。

在此处输入图像描述

每次连接字符串时,您都是String在后台创建一个对象。正如其他答案使您意识到的那样,您正在这样做十亿次。因此,实现良好解决方案的第一步是在每次迭代时停止创建对象。这可以通过使用StringBuilder连接append()值和setLength(0)重用字符数组来完成。这将产生轻微的改进,因为每次迭代只创建 1 个字符串。另一种方法是out.write()使用您想编写的每个字符串进行调用,而不必将它们连接起来。您可以在下面看到结果:

使用 StringBuilder:

在此处输入图像描述

直接到 BufferedWriter:

在此处输入图像描述

仅供参考,我读过内存映射文件提高了文件写入速度。我看到的唯一缺点是您必须事先知道预期的文件大小。

于 2012-06-20T07:13:41.223 回答
0

您在文件上写入 10 亿个整数,因此假设每个数字至少 1 个字节 + 每个空格 1 个字节,忽略换行符,您已经是必须写入磁盘的 2 GB 数据。

现在这是一个很好的数量,肯定需要时间,但您可以考虑PrintWriter在您周围使用 a ,BufferedWriter以便您可以直接使用许多其他可以更优化的操作,例如

void print(int i) 

此外,您的矩阵似乎存储为字符串(因为您使用Integer.valueOf(...))将字符串转换为整数,然后您将它们与它们并再次转换回来。我想您可以通过将所有内容都设置为 int 来节省一些时间(或者无论如何这似乎更有意义)。

还可以考虑使用 aStringBuilder来代替像您正在做的那样连接长字符串。但我认为你根本不应该连接任何东西(通过使用PrintWriter和优化数据结构)。

如果您的数据不适合人类阅读,那么只需跳过字符串并保存二进制数据,您将获得至少 10 倍的速度。

于 2012-06-20T04:36:01.720 回答
0

You have to remember that you are effectively executing the central loop 1 billion times. There's nothing you can do to reduce that because that is the number of values in your 3d array. All you can hope to do is make that loop as tight as possible.

Creating strings by 'adding' (using the + operator) is very inefficient. Reducing the number of strings you create (which occurs every time you use the + operator to concatenate them) will help. Look into using a StringBuilder instead.

StringBuilder rowStr = new StringBuilder();
    ...
    rowStr.append(...);
    ...
rowStr.append("\n");
out.write(rowStr.toString());

Also, don't use Integer.toString on the result of Integer.valueOf. Try just casting to int and handling the case where the result is negative.

Any time you can remove the construction of a new object in the inner loop, you will be saving time.

于 2012-06-20T04:45:13.993 回答