Question

I'm writing an external file from Matlab. I want to put several types of fprintf statements in the same for loop, writing to the same file. However, I would like the lines resulting from each type of fprintf statement to be grouped together in the output file. That is to say that all of the lines resulting from iterating through the first fprintf statement should be before all of the lines resulting from iterating through the second fprintf statement.

This could trivially be achieved by having a separate for loop for each fprintf statement, but there should be a more elegant way to do this, especially if I have many types of fprintf statements.

 for ii=1:length(fieldnames(isom))
    clear cau cou
    cau=1; cou=1
    for kk=1:size(isom.(['m' num2str(ii)]),1)
        fprintf(fileID,'MPTEMP,,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),cau,isom.(['m' num2str(ii)])(kk,1));
        cau=cau+1;
        %Wait until first fprintf ends then
        fprintf(fileID,'MPDATA,,%d,NUXY,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),ii,cou,Info{ft(1,1),3});
        cou=cou+1;
    end
end
Was it helpful?

Solution 2

Instead of using fprintf, you can use sprintf and store all the data into a cell array and write to the file at the very end. Also, this way you would avoid writing multiple for loops for each fprintf. Make sure the output format is what you are looking for though, as also asked in my comment under your question.

Code

M = numel(fieldnames(isom));%%// numel is preferred over length
N = size(isom.(['m' num2str(length(fieldnames(isom)))]),1);

data = cell(M,N,2); %%// 2 is the no. of sprintfs used

for ii=1:M
    clear cau cou
    cau=1; cou=1;

    %%// Add all your fprintf statements as sprintf under this one FOR
    %%// loop, like data(ii,kk,3), data(ii,kk,4) etc.
    for kk=1:N
        data(ii,kk,1) = {sprintf('MPTEMP,,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),cau,isom.(['m' num2str(ii)])(kk,1))};
        data(ii,kk,2) = {sprintf('MPDATA,,%d,NUXY,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),ii,cou,Info{ft(1,1),3})};
        cau=cau+1;
        cou=cou+1; %%// Maybe you can avoid using both cau and cou by using kk instead
    end
end

data = data(:);
for k = 1:size(data,1)
    fprintf(fileID,'%s',data{k,:});
end

fclose(fileID);

OTHER TIPS

Think for a moment what writing to a file does: it copies bytes from memory to the storage media, sequentially (usually). What you are asking for is to do the following (I assume that the first fprintf writes aaa,bbb,ccc on subsequent calls, and the second writes AAA,BBB,CCC).

after each iteration you want the file contents to be the next line in this series:

aaaAAA              - after first pass
aaabbbAAABBB        - after second pass
aaabbbcccAAABBBCCC  - after third pass

Now if you know exactly how long the total of all the writings of the first statement will be, you can do

aaa      AAA
aaabbb   AAABBB
aaabbbcccAAABBBCCC

using "random access" to the file

That may be OK "sometimes". However I think it makes more sense to create these blocks in memory, and write them out in the end. You can do this with sprintf rather than fprintf:

s1 = '';
s2 = '';
for ii=1:5
  s1 = [s1 sprintf('format etc', data, data)];
  s2 = [s2 sprintf('other format', otherData)];
end

and finally you write them in order:

fprintf(fileID, '%s%s', s1, s2);

Not ideal, because you risk growing your strings which can be quite slow (if it gets too big for the space that was allocated, the whole string has to be moved; this gets progressively slower as the string gets larger. You could pre-allocate the string if you know how big it is going to be but that adds a lot of complexity).

Really - a series of for loops that do everything for one type of data at a time, so that the output gets generated in the order you want, is not such a bad plan.

One other solution - that circumvents some of the memory allocation problem: use sprintf to put values in a 2D cell array - and when you are done, print the transpose of the cell array to file.

storage = cell(3,2);
for ii=1:3
  storage{ii,1}=sprintf('%d \n',ii);
  storage{ii,2}=sprintf('%.2f\n', ii);
end

% now write the resulting strings in the order you want them:
for ii = 1:2
  for jj = 1:3
    fprintf(1, '%s', storage{jj,ii});
  end
end

% but you don't even need these loops:
fprintf(1, 'and now all at once:...\n');
fprintf(1, '%s', [storage{:}])

The output of this is what you were looking for:

1 
2 
3 
1.00
2.00
3.00
and now all at once:...
1 
2 
3 
1.00
2.00
3.00

As you can see, although we wrote alternate %d and %.2f numbers into the cell array, in the final output they are grouped as you wanted. And by choosing the order of the indices as I did for the cell array, printing the whole thing becomes a single line (rather than a second set of nested loops).

it's quite difficult to understand your question, but if I am understanding that you want to do the loop for all iterations with one print statement and then do the loop for all iterations with the other print statement, why don't you just execute the loop twice?

for ii=1:length(fieldnames(isom))
    clear cau cou
    cau=1; cou=1
    for kk=1:size(isom.(['m' num2str(ii)]),1)
        fprintf(fileID,'MPTEMP,,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),cau,isom.(['m' num2str(ii)])(kk,1));
        cau=cau+1;
    end
    for kk=1:size(isom.(['m' num2str(ii)]),1)    
        fprintf(fileID,'MPDATA,,%d,NUXY,%d,%d,%f\n',size(isom.(['m' num2str(ii)]),1),ii,cou,Info{ft(1,1),3});
        cou=cou+1;
    end
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top