以人类可读的格式将巨大的ArrayList写入文件

时间:2016-09-20 13:38:05

标签: java arraylist filewriter large-data

我有一个程序可以处理来自传感器系统的大量传感器数据。我目前正在考虑将我的程序输出写入文本文件,以便我可以检查程序是否正常处理。

现在我在ArrayList之前编写一些标识符,然后使用ArrayList.toString()将ArrayList写入文件。

lineToWrite = identifer1 + ";" + identifier2 + ";" + ArrayList.toString()

输出文件总共包含21行,并且ArrayLists从100个项目到400.000个项目大。使用toString()方法使我通常无法使用的任何文件编辑程序打开文件并进行检查。

我想过对ArrayList中的项进行一些小处理:

String lineToWrite = "";

String arrayListString = "\n";
for(String s : sensorLine){
    arrayListString += "\t" + s + "\n";
}

lineToWrite = identifer1 + ";" + identifier2 + ";" + arrayListString;

但似乎这对于一些足够大的ArrayLists来说是永远的。有没有人有更好/更快的方法来做这个或知道一个好的文件查看程序?

我使用了以下内容,但没有以下问题:

  • Notepad ++ - >完全打开后缓慢打开和滞后
  • Sublime Text 3 - >打开很慢!

作为传感器数据的一个侧面说明:我总共有230万个传感器输入。

EDIT1:

为了扩展问题问题,我可能需要补充说,它是将巨大的数组拆分成一个被证明是个问题的单个字符串的一部分。程序在数组上的迭代非常缓慢,因为它只是在每次传递时增加arrayListString的大小,这会占用大量的内存/处理能力。

EDIT2:

至于编写方法本身,我使用BufferedWriter(),并使用实际方法变量的占位符:

output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename, toAppend), "UTF-8"));

对于我正在使用的实际写作:

output.append(line)
output.flush();

5 个答案:

答案 0 :(得分:5)

问题是你正在将一个非常大的字符串组装到内存中,然后一次写入所有字符串,并启动大量字符串操作(导致为每个字符串分配内存)。

相反,请考虑使用Stream。使用Writer,您可以迭代数组并随时附加到文件中,速度会快得多。

这是一本关于基础知识的好教程: http://www.tutorialspoint.com/java/java_files_io.htm

关于编辑器问题,大多数编辑器要么将整个文件加载到内存中,要么将其加载到行或字节块中。如果你有大行,你可能想重新审视你的格式。

答案 1 :(得分:2)

我认为您必须将数据分成块并在需要时加载到编辑器中。这是一个很好的答案。 How to read Text File of about 2 GB?

答案 2 :(得分:2)

将数据转储到数据库

然后你可以做一些有趣的事情,比如选择数字1000 - 1100,或搜索值,做avg / min / max。在像Toad这样的数据库客户端中。

SQL查询语言应该不是问题。客户也没有。

Java具有嵌入式独立数据库; H2可能就足够了。

答案 3 :(得分:1)

由于一些奇怪的原因,当你有长行时,几乎所有的文本编辑都非常慢。通常,您可以轻松编辑具有一百万行的文件,但如果文件包含一行包含100000个字符,则会遇到问题。

关于文件的性能,有几种权衡取舍。

写入更大的数据块&#34>通常有利于提高性能。那就是:当你想写1000个字节时,你应该一次写下这1000个字节,而不是一个一个地写。但在这种情况下,您试图通过组装一个巨大的字符串来构建一个真正巨大的数据块。这可能会反击并降低性能,因为由于许多字符串连接,组装此字符串可能会很昂贵。

作为Taylor pointed out in his answer,逐行写入文件可能是一个合理的权衡:然后块仍然足够大,以补偿一般写入操作的努力,并且仍然足够小避免字符串连接开销。

作为一个例子:用BufferedWriter写一百万行的时间几乎不可测量:

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");
            }
        }
    }
}

答案 4 :(得分:0)

最后我找到了解决方案。

我使用StringBuilder来解决将大字符串写入文件的问题。方法如下:

StringBuilder sb = new StringBuilder();
for(String s : arrayList){
    sb.append("\t" + s + "\n"
}

String line = identifier1 + ";" + identfier2 + ";" + sb.toString();

对于编辑 Sublime Text 3 似乎并不介意太多,只要行不是400.000个字符