将文件读入d中的行数组

时间:2012-04-25 05:46:52

标签: arrays file-io d

将文本文件读入行数组的正确方法是什么?我在Rosetta Stone上找到了以下内容:

string[] readLines(string filename) {
  auto f = File(filename);
  scope(exit) f.close();
  string[] lines;

  foreach (str; f.byLine) {
    lines ~= str.idup;
  }

  return lines;
}

但看起来每行调整一个数组,效率非常低。我可以通过标准的双倍方法跟踪读入的行数并调整数组的大小

  int i = 0;
  foreach (str; f.byLine) {
    if (lines.length <= i + 1) {
      lines.length = lines.length * 2 + 1;
    }
    lines[i] = str.idup;
    i++;
  }
  lines.length = i;

但这是足够的样板代码,我不得不想知道我是不是只是忽略标准库中已经为我做过的事情。


编辑:为fwend的评论提供更多可见性:this article详细描述了数组分配器的工作原理,以及运行时有效处理追加的原因

3 个答案:

答案 0 :(得分:4)

实际上,只要阵列的空间不足,D就会使阵列的预留空间加倍,所以你不需要手动完成。关于D'数组here

的信息很多

答案 1 :(得分:4)

您最初可能会获得大量重新分配,但随着阵列的增长,其容量应该增长,以便通过进一步追加分配的可能性更小。您可以打印出数组的capacity属性,看它是如何增长的。

但是,如果你特别担心附加性能,那么你应该使用std.array.Appender,在这种情况下,你的代码看起来像这样:

string[] readLines(string filename)
{
    auto file = File(filename);
    auto lines = appender!(string[]);

    foreach(line; file.byLine())
        lines.put(to!string(line));

    return lines.data;
}

Appender旨在提高追加效率,并利用其所能提供的任何技巧使附加效率高于~=本身。

答案 2 :(得分:4)

也许这个:

import std.algorithm;
import std.array;
import std.file;

string[] readLines(string input)
{
    Appender!(string[]) result;
    foreach (line; input.splitter("\n"))
        result.put(line);
    return result.data;
}

void main()
{
    string input = cast(string)std.file.read("test.d");
    string[] lines = readLines(input);
}

它应该足够快,因为结果只是创建预加载的输入字符串的片段而不分配新的数组(除了片段本身的分配,IOW指针+长度字段)。