如何写入文件以避免 OutOfMemoryError
How to write into File to avoind OutOfMemoryError
尽管我为我的项目增加了内存,但以下函数运行到 java.lang.OutOfMemoryError。
这发生在 sb.append(CostMatrix[k][j]);
行
我想原因是写入文件效率低下。与其将所有数据存储在 CostMatrix
中,不如逐行写入文件,每次更新 sb
可能会更好。如何实现?
private static void saveDistanceMatricesToCSV(int i, List<Object[]> data)
{
System.out.println("Saving distance matrix " + i + " to CSV");
try
{
String NEW_LINE = System.getProperty("line.separator");
File file = new File("clusters/d"+i+".csv");
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
StringBuilder sb = new StringBuilder();
int len = data.size();
double[][] CostMatrix = new double[len][len];
for (int k=0; k<len; k++)
{
for (int j=k; j<len; j++)
{
double lat1 = (Float) data.get(k)[3];
double lon1 = (Float) data.get(k)[4];
double lat2 = (Float) data.get(j)[3];
double lon2 = (Float) data.get(j)[4];
double dist = distfunc(lat1,lon1,lat2,lon2);
CostMatrix[k][j] = dist;
CostMatrix[j][k] = dist;
}
}
for (int k=0; k<len; k++)
{
for (int j=0; j<len; j++)
{
sb.append(CostMatrix[k][j]);
sb.append(",");
}
sb.append(NEW_LINE);
}
bw.write(sb.toString());
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
您可以使用 PrintWriter :
PrintWriter printWriter = new PrintWriter(file);
然后,不是附加到 StringBuilder,而是打印到输出:
printWriter.println(NEW_LINE);
我看到了各种低效率的根源。您正在做 2 对相同的 for 周期:
- 第一对:迭代data结构并填充CostMatrix(顺便说一句,java变量名以小写字母开头)
- 第二对:迭代 CostMatrix 以填充 StringBuilder.
正如 Berger 已经告诉您的那样,您可以避免使用 StringBuilder,但我还会删除第二对 for 循环,从而删除 [=14= 的内存中使用]CostMatrix 并在前几个周期中直接移动书写指令。
您可以将每一行写入文件,如下所示。
for (int k = 0; k < len; k++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < len; j++) {
sb.append(CostMatrix[k][j]).append(",");
}
output.write(sb.toString());
output.newLine();
}
BufferWriter的newLine也是使用系统属性line.separator。
尽管我为我的项目增加了内存,但以下函数运行到 java.lang.OutOfMemoryError。
这发生在 sb.append(CostMatrix[k][j]);
行
我想原因是写入文件效率低下。与其将所有数据存储在 CostMatrix
中,不如逐行写入文件,每次更新 sb
可能会更好。如何实现?
private static void saveDistanceMatricesToCSV(int i, List<Object[]> data)
{
System.out.println("Saving distance matrix " + i + " to CSV");
try
{
String NEW_LINE = System.getProperty("line.separator");
File file = new File("clusters/d"+i+".csv");
FileWriter fw = new FileWriter(file.getAbsoluteFile());
BufferedWriter bw = new BufferedWriter(fw);
StringBuilder sb = new StringBuilder();
int len = data.size();
double[][] CostMatrix = new double[len][len];
for (int k=0; k<len; k++)
{
for (int j=k; j<len; j++)
{
double lat1 = (Float) data.get(k)[3];
double lon1 = (Float) data.get(k)[4];
double lat2 = (Float) data.get(j)[3];
double lon2 = (Float) data.get(j)[4];
double dist = distfunc(lat1,lon1,lat2,lon2);
CostMatrix[k][j] = dist;
CostMatrix[j][k] = dist;
}
}
for (int k=0; k<len; k++)
{
for (int j=0; j<len; j++)
{
sb.append(CostMatrix[k][j]);
sb.append(",");
}
sb.append(NEW_LINE);
}
bw.write(sb.toString());
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
您可以使用 PrintWriter :
PrintWriter printWriter = new PrintWriter(file);
然后,不是附加到 StringBuilder,而是打印到输出:
printWriter.println(NEW_LINE);
我看到了各种低效率的根源。您正在做 2 对相同的 for 周期:
- 第一对:迭代data结构并填充CostMatrix(顺便说一句,java变量名以小写字母开头)
- 第二对:迭代 CostMatrix 以填充 StringBuilder.
正如 Berger 已经告诉您的那样,您可以避免使用 StringBuilder,但我还会删除第二对 for 循环,从而删除 [=14= 的内存中使用]CostMatrix 并在前几个周期中直接移动书写指令。
您可以将每一行写入文件,如下所示。
for (int k = 0; k < len; k++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < len; j++) {
sb.append(CostMatrix[k][j]).append(",");
}
output.write(sb.toString());
output.newLine();
}
BufferWriter的newLine也是使用系统属性line.separator。