Java 以可读格式将巨大的ArrayList写入文件
我有一个程序,可以处理来自传感器系统的大量传感器数据。我目前正在研究将程序的输出写入一个文本文件,这样我就可以检查程序是否正确地处理了输出 现在,我正在ArrayList之前写入一些标识符,然后使用ArrayList.toString将ArrayList写入文件 输出文件总共包含21行,ArrayList的大小从100项到400.000项不等。使用toString方法,我通常使用的任何文件编辑程序都无法打开文件并检查它们 我想对ArrayList中的项进行一个小处理:Java 以可读格式将巨大的ArrayList写入文件,java,arraylist,filewriter,large-data,Java,Arraylist,Filewriter,Large Data,我有一个程序,可以处理来自传感器系统的大量传感器数据。我目前正在研究将程序的输出写入一个文本文件,这样我就可以检查程序是否正确地处理了输出 现在,我正在ArrayList之前写入一些标识符,然后使用ArrayList.toString将ArrayList写入文件 输出文件总共包含21行,ArrayList的大小从100项到400.000项不等。使用toString方法,我通常使用的任何文件编辑程序都无法打开文件并检查它们 我想对ArrayList中的项进行一个小处理: String lineTo
String lineToWrite = "";
String arrayListString = "\n";
for(String s : sensorLine){
arrayListString += "\t" + s + "\n";
}
lineToWrite = identifer1 + ";" + identifier2 + ";" + arrayListString;
但对于一些足够大的ArrayList来说,这似乎需要永远的时间。是否有人有更好/更快的方法来执行此操作,或者知道一个好的文件查看程序
我使用了以下方法,但没有以下问题:
记事本++->打开缓慢,完全打开后会变慢
升华文本3->打开速度非常慢!
作为传感器数据的一个小提示:我总共有230万个传感器输入
编辑1:
为了扩展这个问题,我可能需要补充一点,那就是将庞大的数组拆分为单个字符串的部分被证明是一个问题。该程序在数组上的迭代速度非常慢,因为它只是在每次遍历时增加arrayListString的大小,我想这会占用大量内存/处理能力
编辑2:
至于编写方法本身,我使用的是一个BufferedWriter,带有实际方法变量的占位符:
output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename, toAppend), "UTF-8"));
对于我正在使用的实际写作:
output.append(line)
output.flush();
问题是,您正在将一个非常大的字符串组装到内存中,然后一次将其全部写入,需要引导大量的字符串操作,从而为每个字符串分配内存 相反,请考虑使用流。使用Writer,您可以迭代数组并在运行时附加到文件,这将快得多 以下是一个很好的基础教程:
至于编辑器问题,大多数编辑器要么将整个文件加载到内存中,要么将其以行或字节块的形式加载。如果您有大量的行,您可能需要重新检查您的格式。我认为您必须将数据分割成块,并在需要时加载到编辑器中。下面是一个很好的答案。 将数据转储到数据库中 然后你可以做一些有趣的事情,比如选择数字1000-1100,或者搜索值,在数据库客户端(比如Toad)中执行avg/min/max SQL查询语言应该不是问题。客户也不是
Java有嵌入式独立数据库;H2可能就足够了。出于某种奇怪的原因,几乎所有的文本编辑器在您排长队时都会非常慢。通常,您可以轻松编辑一个有一百万行的文件,但如果该文件包含一行100000个字符,则会遇到问题 关于编写文件的性能,有几个权衡 写入较大的数据块通常有利于提高性能。也就是说:当你想写1000个字节时,你应该一次写这1000个字节,而不是一个接一个地写。但在本例中,您正试图通过组合一个巨大的字符串来构建一个真正巨大的数据块。这可能会造成回击并降低性能,因为由于许多字符串串联,组装此字符串的成本可能会很高 因此,逐行写入文件可能是一个合理的折衷方案:块仍然足够大以补偿一般写入操作的工作量,并且仍然足够小以避免字符串连接开销 例如:使用BufferedWriter写入100万行的时间很难测量:
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class ArrayListToFile
{
public static void main(String[] args) throws IOException
{
List<String> sensorLine = new ArrayList<String>();
int size = 1000000;
Random random = new Random(0);
for (int i=0; i<size; i++)
{
sensorLine.add(String.valueOf(random.nextDouble()));
}
write("out.txt", sensorLine);
}
private static void write(String fileName, Iterable<?> elements)
throws IOException
{
try (BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream(fileName))))
{
String identifier1 = "i1";
String identifier2 = "i2";
bw.write(identifier1 + ";" + identifier2 + ";\n");
for (Object s : elements)
{
bw.write("\t" + s + "\n");
}
}
}
}
最后我找到了解决办法 我使用了StringBuilder来解决向文件中写入巨大字符串的问题。方法如下:
StringBuilder sb = new StringBuilder();
for(String s : arrayList){
sb.append("\t" + s + "\n"
}
String line = identifier1 + ";" + identfier2 + ";" + sb.toString();
对于编辑来说,Sublime Text 3似乎不太在意,只要行长度不超过40万个字符+是一个可怕的主要性能杀手,我不认为它是否被StringBuilder有效地取代。你是否考虑过数据流?写的速度快百倍。这是我的方法,但是我现在需要验证数据在进入数据库存储之前经过的算法。这就是将其存储到文件中的原因。无论如何谢谢你的建议!:我真的很喜欢你的建议,把传感器线和其他数据分开写。我不确定它是否比我目前的方法快。我和一个架线工一起去的。计算一个我只需写一次的字符串元素总量似乎真的很快。可以,StringBuilder在某些情况下可以避免大量字符串连接开销。然而,有一点需要考虑的是,当你没有40万B时 ut 4亿行,您可能会在某个时候耗尽内存。以流式方式单独写入行,这样可以更好地扩展。但是,当您当前的解决方案适合您时,就可以了。
StringBuilder sb = new StringBuilder();
for(String s : arrayList){
sb.append("\t" + s + "\n"
}
String line = identifier1 + ";" + identfier2 + ";" + sb.toString();