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

Writing huge ArrayList to file in a human readable format

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

现在我正在 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;

但对于一些足够大的 ArrayList 来说,这似乎需要永远。有没有人有 better/faster 方法来执行此操作或知道一个好的文件查看程序?

我用过以下,没有出现以下问题:

作为传感器数据的一个小注释:我总共有 230 万个传感器输入。

编辑 1:

为了扩展问题,我可能不得不补充说,将巨大的数组拆分为单个字符串的部分被证明是一个问题。该程序在数组上迭代非常缓慢,因为它只是在每次通过时增加 arrayListString 的大小,我猜这会占用很多 memory/processing 功率。

编辑 2:

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

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

对于实际写作,我使用的是:

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

问题是您要将一个非常大的字符串组装到内存中,然后一次将其全部写入,需要启动大量字符串操作(导致为每个字符串分配内存)。

相反,考虑使用 Stream。使用 Writer,你可以遍历数组并附加到文件,会快得多。

这是一个很好的基础教程: http://www.tutorialspoint.com/java/java_files_io.htm

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

我认为当 needed.Here 一个好的答案时,您将不得不将数据分成块并加载到编辑器中。 How to read Text File of about 2 GB?

将数据转储到数据库

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

SQL查询语言应该没有问题。一个客户也没有。

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

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

关于写入 文件的性能,需要权衡取舍。

写"larger blocks of data"一般对性能有好处。即:当你要写入1000个字节时,你应该一次写入这1000个字节,而不是一个一个地写入。但在这种情况下,您正试图通过组装一个巨大的字符串来构建一个 really 的巨大数据块。这可能会反击并降低性能,因为由于有许多字符串连接,组装此字符串可能会很昂贵。

一样,逐行写入文件在这里可能是一个合理的权衡:块仍然足够大以补偿一般的写操作的工作量,并且仍然足够小以避免字符串连接开销。

举个例子:用 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 似乎并不介意,只要行不是 400.000 个字符长