How to use fscanf in matlab to read any element of a matrix?
7 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
f1=fopen('input.dat');
data1=fscanf(f1,'%d',[2,3]);
data1'
this is not giving desired results. the input matrix is
1 2 3
4 5 6
7 8 9
3 Commenti
dpb
il 7 Ago 2015
With a sequential ASCII file, only possible by an extension of what I showed earlier of skipping over N elements where the N is computed from the field position to the linear position in sequence in the file, or if it is a fixed-width file one can equivalently compute the byte offset (remembering to include the \n character(s) in the computation) and position in the file via fseek.
All in all, as I suggested in the previous response, you're generally far better off to simply read the full array into memory and retrieve the desired locations via sub2ind.
NB: the computation of position in memory is column-major whereas in a file you're reading by record--for example if the file were three records by two columns, your (2,2) position above would be the fifth element in memory but the fourth in the file.
Risposta accettata
dpb
il 6 Ago 2015
Modificato: dpb
il 7 Ago 2015
To not read the third column (which I presume is the answer to Stephen's logical question) you've got to "tell" the i/o routines you don't want them...
>> fmt=['%f %f %*f']; % read two elements of record, skip a third...
>> fid=fopen('test.dat');
>> cell2mat(textscan(fid,fmt,3,'collectoutput',1))
ans =
1 2
4 5
7 8
>>
With fscanf low-level routine it's
>> frewind(fid)
>> fscanf(fid,fmt,[2,inf]).'
ans =
1 2
4 5
7 8
>> fid=fclose(fid);
Answering the question posed in the follow-up comment, even though I do NOT recommend it; consider the following--since the array in the file is symmetric let's get the 2nd record, last column instead as example, the 2,2 element is a special case being in the middle.
>> fmt=[repmat('%*d',1, sub2ind([3,3],2,3)-1) '%d'];
>> frewind(fid)
>> fscanf(fid,fmt,1)
ans =
8
>> frewind(fid)
>> fmt=[repmat('%*d',1, sub2ind([3,3],3,2)-1) '%d'];
>> fscanf(fid,fmt,1)
ans =
6
>>
Note in the first case we used the 2nd row, 3rd column as the indices into the 3x3 array and didn't get what we thought we wanted--that's the point discussed below about the difference between order in memory and on disk in a sequential file. When we transpose the two indices in the latter call, then we get the value we're after.
NB however, the format string is skipping the N-1 entries needed to get to the one desired; this is, while possible, very inefficient in practice, particularly for larger files and even more so if you're after a general grouping of values scattered around. As recommended, almost always you'll be better off to read the entire file and then just select from memory those wanted and clear out the remaining values by setting their locations to [] or save the ones wanted in a new variable/array and then just clear the original entirely.
ADDENDUM Also note in doing this you're not saving anything on the read other than not returning the extra values (which you can easily purge anyway). The fmt statement has N fields; only that N-1 of them are read and thrown away; so there's really no difference at all in the i/o; you still read N values either way; it's the only way the i/o library can find the location of the desired entry in a sequential file.
3 Commenti
dpb
il 7 Ago 2015
Modificato: dpb
il 8 Ago 2015
Of course you don't; you gave an output shape of [2,3] which asks for two rows by three columns; transposing that will give three rows by two columns. But, since internal memory order is, again, column major, while the shape is the same the order isn't.
>> type test.dat
1 2 3
4 5 6
7 8 9
>> fscanf(fid,'%d',[3,2])
ans =
1 4
2 5
3 6
>> frewind(fid)
>> fscanf(fid,'%d',[3,2]).'
ans =
1 2 3
4 5 6
>> fid=fclose(fid);
>>
To retain the shape of an input file, you needs must use the number of columns as the first argument, the second can be either a count or inf to read to EOF. That's one advantage of the higher-level routines such as textscan; they do "look at" the record length in the file internally and automagically return the same shape whereas with the low-level routines you have to do that manually.
NB: one gets the array in column-major order unless transpose owing to that being Matlab's internal storage order. (Also note that [ ' ] is the complex conjugate transpose; what you want for this purpose is the element-wise "dot" version [ .' ]. Doesn't make a difference numerically for reals but it'll screw you up royally if get in the habit and do so for a complex array so recommend get in habit of using the proper operator from the git-go rather than try to unlearn a bad habit later...)
Also note that you retrieve the first six elements from the 3x3 array in the file arranged as you asked by the format string in a 2x3 array. This reflects that the file is sequential and each element in the file is read per the associated format string. Since you gave a single '%d', one integer field is read per application of the format string and the string is applied at total of 2x3 times per your SIZE argument, [2,3] and the result is arranged as requested. Again note the elements are ordered in memory in column-major order; that is the first element of the first record is followed by the second as the first in the second row, then proceed down the second column...hence, to arrange as are in the file the need to transpose as an image of a disk file is stored in apparent row-major order instead.
Note that the SIZE argument does NOT represent the shape of an "area" you might be trying to map of the file but simply the number of times to apply the format string and the resulting shape in which that sequence of N elements will be returned. It does and can not help in trying to read any particular element from the file without reading others; only skipping fields or directly positioning the file will allow that (or a direct-acess file, but Matlab does not implement such for formatted files directly, only simulating them as outlined in the previous comment or converting to a stream (unformatted) file and memmapfile or the like will allow that).
Più risposte (0)
Vedere anche
Categorie
Scopri di più su Large Files and Big Data in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!