我有一个程序,我生成一个巨大的矩阵,一旦计算出来,我必须在以后重用它。出于这个原因,我想将它缓存到本地硬盘,以便以后可以读取它。我只是通过将数据写入文件然后再读取它来使用它。
但是,在 java 中执行此类任务时,我应该考虑什么特别之处。例如,我是否需要对其进行序列化或者可能会做一些特别的事情。在存储重要的应用程序使用数据的地方,我是否应该注意做这些事情。它应该是纯 ASCII/xml 还是什么?
数据不敏感,但数据的完整性很重要。
我有一个程序,我生成一个巨大的矩阵,一旦计算出来,我必须在以后重用它。出于这个原因,我想将它缓存到本地硬盘,以便以后可以读取它。我只是通过将数据写入文件然后再读取它来使用它。
但是,在 java 中执行此类任务时,我应该考虑什么特别之处。例如,我是否需要对其进行序列化或者可能会做一些特别的事情。在存储重要的应用程序使用数据的地方,我是否应该注意做这些事情。它应该是纯 ASCII/xml 还是什么?
数据不敏感,但数据的完整性很重要。
您有几种存储数据的选项。您可以尝试简单地在标题中说明宽度是多少,然后将所有内容放入带有分隔符的列表中(例如,,,'\n'
等'\t'
)' '
。否则,您可以使用特殊的 ObjectOutputStream 来存储数据。请注意:这可能比您的解决方案效率低下。但是,它会更容易使用。
除此之外,您可以自由选择。我通常使用 FileWriter 并以纯文本形式写入所有数据。如果您追求超高效率,那么 FileOutputStream 就是您所需要的。
如果您的数据真的很大,我会推荐一些二进制形式——这将使它更小、更快地读取,尤其是解析(XML 或 JSON 比读取/写入二进制数据慢很多倍)。序列化也会带来很多开销,因此您可能需要检查 DataInputStream 和 DataOutputStream。如果您知道您将只编写特定类型的数字,或者您知道数据的顺序 - 这些肯定是最快的。
不要忘记用缓冲流包装文件流 - 它们将使您的操作速度更快一个数量级。
类似的东西(8192 是示例缓冲区大小 - 您可以根据需要对其进行调整):
final File file = null; // get file somehow
final DataOutputStream dos = new DataOutputStream(
new BufferedOutputStream(new FileOutputStream(file), 8192));
try {
for (int x: ....) { //loop through your matrix (might be different if matrix is sparse)
for (int y: ....) {
if (matrix[x,y] != 0.0) {
dos.writeInt(x);
dos.writeInt(y);
dos.writeDouble(matrix[x,y]);
}
}
}
} finally {
dos.writeInt(-1); // mark end (might be done differently)
dos.close();
}
并输入:
final File file = null; // get file somehow
final DataInputStream dis = new DataInputStream(
new BufferedInputStream(new FileInputStream(file), 8192));
try {
int x;
while((x = dis.readInt()) != -1) {
int y = dis.readInt();
double value = dis.readDouble();
// store x,y, value in matrix
}
} finally {
dis.close();
}
正如 Ryan Amos 正确指出的那样,如果矩阵不是稀疏的,只写值(但所有值)可能会更快:
出去:
dos.write(xSize);
dos.write(ySize);
for (int x=0; x<xSize; x++) {
for (int y=0; y<ySize; y++) {
value = matrix[x,y];
dos.write(value);
}
}
在:
int xSize = dis.readInt();
int ySize = dis.readInt();
for (int x=0; x<xSize; x++) {
for (int y=0; y<ySize; y++) {
double value = dis.readDouble();
matrix[x,y] = value;
}
}
(请注意我没有编译它 - 所以你可能需要更正一些东西 - 它不在我的脑海中)。
如果没有缓冲区,您将逐字节读取,这将使其变慢。
还有一条评论 - 对于如此庞大的数据集,您应该考虑使用 SparseMatrix 并仅写入/读取非零元素(除非您确实拥有那么多重要元素)。
正如上面评论中所写 - 如果您真的想写入/读取该大小矩阵中的每个元素,那么您已经在谈论写入时间而不是几秒钟。
如果您的条目是数字,那么您可以将矩阵的每一行保存为文件中的一行,由一些分隔符分隔。那么你不需要特殊的序列化。:)
这完全取决于您稍后将如何输出它,或者您是否还将它存储在数据库或其他地方。如果您从不输出它或将其存储在其他任何地方,那么文本文件就可以了。
如果不需要持久化数据(即在 java 程序终止后保留它),将它保存在内存中的 Java 变量中会更快。有很多类型可以满足您的要求(hashmap、arraylist...)。如果您需要保留数据以在后续程序执行中使用它,您可以使用标准文件读/写方法将其存储在文件中。纯 ASCII 比 XML 读/写更快。关于文件的完整性,它与操作系统相关,因为 - 最后 - 这将是本地文件系统上的文件。