我必须编写一个函数,它从一个binary file (.dat)
结构中读取一个二维的双精度数组,该列由一个单独的列组成,其名称由函数的单个输入参数提供。该文件的格式如下:
首先,有两个uint32数字对应于数组的行数和列数。之后,有一个双数,即数组中非零元素的数量。然后,数组中的每个非零元素由两个uint32标量和文件中的双标量按此顺序表示:其行索引(uint32),其列索引(uint32)及其值(double)。一个例子可能是:
5
4
2
1
1
8
2
2
9
这意味着该数组有5行4列,总共2个非零元素。这些元素位于(1,1)
位置(值为8)和位置(2,2)
(值为9)。所有其他元素都等于0.因此,数组将是:
8 0 0 0
0 9 0 0
0 0 0 0
0 0 0 0
0 0 0 0
该函数必须返回它从文件中读取的二维数组作为输出参数,如果打开文件时出现问题,该函数将返回一个空数组。目前我尝试使用此代码:
function A = sparse_array_in( filename )
fid = fopen( filename,'rt' );
if fid < 0
A = [];
return;
end
% Get total number of elements on the file
n = 0;
while (fgets(fid) ~= -1),
n = n+1;
end
% Close then reopen
fclose(fid);
fid = fopen( filename,'rt' );
% Read size of array and number of non-zero elements
rows = fread( fid,1,'uint32' );
cols = fread( fid,1,'uint32' );
dims = [ rows,cols ];
non_zero = fread( fid,1,'uint32' );
% Create array of zeros
A = zeros( dims );
% Fill array A with the values from the file
for i = 1:non_zero
r = fread( fid,1,'uint32' );
c = fread( fid,1,'uint32' );
v = fread( fid,1,'double' );
A(r,c) = v;
end
fclose( fid );
end
但它似乎无法正常工作。我错过了什么?
答案 0 :(得分:2)
您的代码存在一些问题:
如果文件ID为负数,则不仅要返回空数组(正如您所做的那样),还要确保代码不从该点开始。我会在分配到return
后立即发表A
声明:
if fid < 0
A = [];
return;
end
接下来当您确定文本文件中的行数时,请注意每次调用fgets
时都要推进文件指针,这样当您最终完成所有行,文件指针指向文本文件的末尾。对fread
,fgets
或任何从文件中读取内容的f*
系列的任何进一步调用都不会为您提供任何内容,因为您位于文件的末尾。您需要做的是关闭文件并再次打开,以便您可以再次从文件中读取。因此,在读取行数时关闭文件,然后再次打开它:
% Get total number of elements on the file
n = 0;
while (fgets(fid) ~= -1),
n = n+1;
end
%// Close then reopen
fclose(fid);
fid = fopen( filename,'rt');
您没有使用fread
权利。第二个参数告诉您要读入的特定类型的数量数字。您使用的是1,2或3,这意味着您正在读取特定类型的1,2或3个数字。由于您使用fread
来读取每次通话的个别号码,因此全部为1 。此外,确定线路总数对我来说似乎是多余的。如果给出非零元素的总数,为什么还要弄清楚有多少行?您已经知道有多少非零元素,因此只需从1到非零数字迭代。因此,试试这个:
% Read size of array and number of non-zero elements
rows = double(fread( fid,1,'uint32' )); %// Change
cols = double(fread( fid,1,'uint32' )); %// Change
dims = [ rows,cols ];
non_zero = fread( fid,1,'uint32' ); %// Change
% Create array of zeros
A = zeros( dims );
% Fill array A with the values from the file
for i = 1 : non_zero %// Change
r = fread( fid,1,'uint32' ); %// Change
c = fread( fid,1,'uint32' ); %// Change
v = fread( fid,1,'double' ); %// Change
A(r,c) = v;
end
%A = reshape( A,dims' ); %// Why are you reshaping?
fclose( fid );
次要评论:你为什么重塑矩阵?如果您已经知道矩阵的行和列位置,并将它们准确地放在它们应该去的位置,为什么还要转置?
因此,通过上述注释,您的代码将如下所示:
function A = sparse_array_in( filename )
fid = fopen( filename,'rt' );
if fid < 0
A = [];
return; %// Change
end
% Read size of array and number of non-zero elements
rows = fread( fid,1,'uint32'); %// Change
cols = fread( fid,1,'uint32'); %// Change
dims = [ rows,cols ];
non_zero = fread( fid,1,'uint32' ); %// Change
% Create array of zeros
A = zeros( dims );
% Fill array A with the values from the file
for i = 1:non_zero
r = fread( fid,1,'uint32' ); %// Change
c = fread( fid,1,'uint32' ); %// Change
v = fread( fid,1,'double' ); %// Change
A(r,c) = v;
end
%// Change - remove reshape
fclose( fid );
end
这是一个示例,表明它适用于二进制文件。我创建了以下场景:
5
7
4
1
1
1
2
2
2
3
3
3
4
4
4
这是一个5 x 7矩阵,其中(1,1) = 1, (2,2) = 2, (3,3) = 3, (4,4) = 4
有4个非零值。我创建了一个二进制文件,然后使用我上面修复的函数来获得结果:
fid = fopen('sparse_binary.dat', 'w');
fwrite(fid, 5, 'uint32');
fwrite(fid, 7, 'uint32');
fwrite(fid, 4, 'uint32');
fwrite(fid, 1, 'uint32');
fwrite(fid, 1, 'uint32');
fwrite(fid, 1, 'double');
fwrite(fid, 2, 'uint32');
fwrite(fid, 2, 'uint32');
fwrite(fid, 2, 'double');
fwrite(fid, 3, 'uint32');
fwrite(fid, 3, 'uint32');
fwrite(fid, 3, 'double');
fwrite(fid, 4, 'uint32');
fwrite(fid, 4, 'uint32');
fwrite(fid, 4, 'double');
fclose(fid);
A = sparse_array_in('sparse_binary.dat');
我选择A
:
A =
1 0 0 0 0 0 0
0 2 0 0 0 0 0
0 0 3 0 0 0 0
0 0 0 4 0 0 0
0 0 0 0 0 0 0
......这就是我们所期望的。