There are a few of problems with your code:
If the file ID is negative, you should not only return the empty array (as you're doing), but also make sure the code doesn't proceed from that point. I would stick a return statement right after the assignment to A:
if fid < 0
A = [];
return;
end
Next when you're determining the number of lines in your text file, be advised that you're advancing the file pointer each time you call fgets and so when you finally finish reading all of the lines, the file pointer points at the end of the text file. Any further calls to fread, fgets, or any of the f* family that reads things from files will not give you anything because you're at the end of the file. What you need to do is close the file and open it again so that you can start reading from the file again. Therefore, close the file when you read the number of lines, then open it up again:
% 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');
You're not using fread right. The second parameter tells you how many numbers of a particular type you want to read in. You are using 1, 2 or 3 which means that you're reading 1, 2 or 3 numbers of a particular type. Because you're using fread to read in individual numbers per call, they should all be 1. Also, determining the total number of lines seems rather superfluous to me. If you are given the total number of non-zero elements, why bother figuring out how many lines there are? You already know how many non-zero elements there are, so just iterate from 1 up to as many non-zero numbers. Therefore, try this:
% 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 );
Minor comment: Why are you reshaping the matrix? If you already know the row and column locations of your matrix and are putting them exactly where they're supposed to go, why bother transposing?
Therefore, with the above comments, your code would look like this:
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
Here's an example that shows that it works for a binary file. I've created the following scenario:
5
7
4
1
1
1
2
2
2
3
3
3
4
4
4
This is a 5 x 7 matrix where (1,1) = 1, (2,2) = 2, (3,3) = 3, (4,4) = 4 with 4 non-zero values. I create a binary file, then use the function I fixed above to get the results:
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');
I get for 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
... which is what we expect.