将文本文件作为字符串的2D数组加载,而不指定列数

时间:2018-01-26 14:20:38

标签: matlab csv file-io octave

假设我有一个纯文本文件test.dat

foo bar baz
qux ham spam

我知道想要将它加载到Octave(或者必要时是Matlab)作为二维单元格数组,保留以空格和换行符编码的结构。根据我对the documentation的理解,以下应该是要​​走的路:

format = '%s';
file = fopen('test.dat');
data = textscan(file,format);
fclose(file);
disp(data);

然而,这仅将数据加载为一维数组:

{
  [1,1] = 
  {
    [1,1] = foo
    [2,1] = bar
    [3,1] = baz
    [4,1] = qux
    [5,1] = ham
    [6,1] = spam
  }
}

明确指定DelimiterWhitespaceEndOfLine没有帮助(后者有什么意义呢?);也没有使用其他加载函数,如textreaddlmread。上面的工作是使用format = '%s%s%s'做了什么,但这要求我以某种方式确定列的数量,该函数应该能够自己完成。

因此我问:是否有内置功能能够满足我的需求?我对自己编写此类功能的方式不感兴趣 - 我有信心我可以做到这一点,但这正是我想要避免的(因为我需要用它来展示良好的练习,因此不能重新发明轮子)。

相关Q& As(知道列数的所有工作):

4 个答案:

答案 0 :(得分:5)

您可以使用readtable

data = readtable('test.txt', 'ReadVariableNames', false, 'Delimiter', ' ')

输出:

Var1     Var2      Var3 
_____    _____    ______

'foo'    'bar'    'baz' 
'qux'    'ham'    'spam'

如果你想要一个单元格,而不是一张桌子,你可以使用

data = table2cell( data );

>> data = {'foo'    'bar'    'baz' 
           'qux'    'ham'    'spam'}

我不确定readtable是否为Octave方法,它似乎是on GitHub但我无法检查安装。它在2013b中被引入Matlab。

您可以使用较低级别的操作,逐行阅读

fid = fopen('test.txt','r');
data = {};
while ~feof(fid)
    line = fgets(fid);       % Read line
    A = strsplit(line, ' '); % Split on spaces
    data(end+1, :) = A;      % Append to output
end
fclose(fid);

>> data = {'foo'    'bar'    'baz' 
           'qux'    'ham'    'spam'}

此方法假定data的每一行将具有相同数量的元素(每行中的分隔符数相同)。如果你不能这样做,那么更安全的方法是做data{end+1,1} = A,然后再分割线。

此方法中唯一不使用低级文件I / O的函数是strsplit。这是OctaveMatlab的内置功能。<​​/ p>

答案 1 :(得分:3)

在Octave中,您可以使用包io中的csv2cell

pkg load io
result = csv2cell('test.dat',' ')

答案 2 :(得分:0)

我建议您查看fgetl()或fgets()函数。 基本上你读了文件的行,然后你可以用textscan()应用你的代码并得到“列”。

答案 3 :(得分:0)

我有同样的问题。在Matlab中,readtable.m对我来说很慢,并且fgetl示例正在循环调整大小。 但也许可以接受的解决方案基于此论坛帖子: https://de.mathworks.com/matlabcentral/answers/476483-how-to-use-textscan-on-a-cell-array-without-a-loop

因此,至少在较新的Matlab中:

fid=fopen(file,'r');
data=textscan(fid,'%s','Delimiter','\r\n');
fclose(fid);
data=split(data{1},';',1); 

我还没有测试split.m处理大数据的速度。