Octave strread 无法 return 将结果解析为数组(?)

Octave strread can't return parsed results to an array (?)

在 Octave 中,我从磁盘读取非常大的文本文件并解析它们。函数 textread() 做的正是我想要的,除了它的实现方式。查看源代码,textread.m 在尝试解析行之前将整个文本文件拉入内存。如果文本文件很大,它会用文本填充我所有的空闲 RAM (16 GB),然后在解析之前开始保存回磁盘(虚拟内存)。如果我等待足够长的时间,textread() 将完成,但它几乎要花很长时间。

请注意,在解析为浮点值矩阵后,相同的数据很容易装入内存。所以我在中间区域使用 textread(),那里有足够的内存用于浮点数,但没有足够的内存用于与文本相同的数据。

所有这些都是为我的问题做准备,这是关于 strread() 的。我的文本文件中的数据如下所示

0.0647148      -2.0072535       0.5644875       8.6954257
0.1294296      -8.4689583       0.6567095       144.3090450
0.1941444      -9.2658037      -1.0228742       173.8027785
0.2588593      -6.5483359      -1.5767574       90.7337329
0.3235741      -0.7646807      -0.5320896       1.7357120

...等等。文件中没有 header 行或注释。

我编写了一个逐行读取文件的函数,请注意我尝试使用 strread() 解析一行数据的两种方式。

function dest = readPowerSpectrumFile(filename, dest)

  % read enough lines to fill destination array
  [rows, cols] = size(dest);

  fid = fopen(filename, 'r');

  for line = 1 : rows
    lstr = fgetl(fid);

% this line works, but is very brittle
    [dest(line, 1), dest(line, 2), dest(line, 3), dest(line, 4)]  = strread(lstr, "%f %f %f %f");

% This line doesn't work. Or anything similar I can think of.
%    dest(line, 1:4) = strread(lstr, "%f %f %f %f");

  endfor

  fclose(fid);

endfunction

有没有一种优雅的方法可以让 strread return 将值解析为数组?否则我每次更改列数时都必须编写一个新函数。

谢谢

如果您输入 fprintf 比其格式规范中更多的值,它将重新应用打印语句,直到用完为止:

>> fprintf("%d %d \n", 1:6)
1 2
3 4
5 6

看来这也适用于 strread。如果你只指定一个值来读取,但当前行有多个值,它会继续读取它们并将它们添加到一个列向量中。我们需要做的就是将这些值分配给 dest:

的正确行
function dest = readPowerSpectrumFile(filename, dest)

   % read enough lines to fill destination array
   [rows, cols] = size(dest);

   fid = fopen(filename, 'r');

   for line = 1 : rows
      lstr = fgetl(fid);

      % read all values from current line into column vector 
      % and store values into row of dest
      dest(line,:) = strread(lstr, "%f");
      % this will also work since values are assumed to be numeric by default:
      % dest(line,:) = strread(lstr);
   endfor

   fclose(fid);

endfunction

输出:

readPowerSpectrumFile(filename, zeros(5,4))
ans =

   6.4715e-02  -2.0073e+00   5.6449e-01   8.6954e+00
   1.2943e-01  -8.4690e+00   6.5671e-01   1.4431e+02
   1.9414e-01  -9.2658e+00  -1.0229e+00   1.7380e+02
   2.5886e-01  -6.5483e+00  -1.5768e+00   9.0734e+01
   3.2357e-01  -7.6468e-01  -5.3209e-01   1.7357e+00

您描述的格式是具有浮点值的矩阵。在这种情况下,您可以只使用 load

d = load ("yourfile");

这比任何其他函数都快得多。您可以查看 libinterp/corefcn/ls-mat-ascii.cc 中使用的实现:read_mat_ascii_data