Write a tabbed matrix in a txt file

Hi everyone,
I need to write a numeric matrix in a text file, in such a way that each row is indented at the beginning.
Let's say I want a header and a matrix written below:
clear all
clc
A = [2 4 ; 5 3 ; 9 6 ; 6 4 ; 8 8];
test = fullfile("test");
[fid, error] = fopen(test, 'w');
fprintf(fid, "############\n");
dlmwrite(test, A, 'delimiter',"\t", '-append');
fclose(fid);
I would obtain a file "test" with:
############
2 4
5 3
9 6
6 4
8 8
Is there a way to write "test" like this?
############
2 4
5 3
9 6
6 4
8 8
Thank you for any kind of help

 Accepted Answer

dpb
dpb on 30 Apr 2021
Edited: dpb on 30 Apr 2021
Read the rest of the documentation for dlmwrite --
Name-Value Pair Arguments
...
'precision' — Numeric precision
(default) | scalar | C-style format specifier | character vector
dlmwrite(test, A, 'delimiter',"\t",'precision','%3d','-append')
Salt to suit...limitation is same format string for all variables; if you want/need more control, use fprintf and whatever formatting string you desire.
NB: dlmwrite is also deprecated in favor of writematrix beginning in R2019b, but the latter fails to provide the ability to specify a format string; you get whatever the 'long g' format returns for the given numeric data and so is not suitable replacement in terms of all functionality if must control the format.

6 Comments

In the end I used
fid = fopen ("test", 'w');
fprintf (fid, "############\n");
fid = fopen ("test", 'a');
fprintf (fid, '\t %-12g \t %-12g \n', A');
fclose (fid);
I was unable to use writematrix due to a problem with the text file extension, which is unconventional in my case, but this is no longer a problem.
writematrix tries to be too clever sometimes, but to try to make common cases easy, it uses the extension provided to determine the internal algorithm to use to write the file.
If you want/need a file with no extension, use the 'FileType' optional named parameter
writematrix(A,'test.','FileType','text')
NB: You MUST include the trailing period in the base file name, however, otherwise it will append the 'txt' extension for you.
You're still stuck in that you can't specify a fixed format width; if the data are mixed integer, float or have differing magnitudes, you'll get the "whatever fits" result from a '%g' format string...
This last concept escapes me a bit even reading the MATLAB explanation and I don't really know what is best to do. The values to be entered (which I have not specified, but are not those of matrix A which was just a simplifying example), are various, but consistent. They range from 240.14 to 0.0031567 for example. What I would be interested in is to avoid losing significant digits and possibly avoid unnecessary zeros after the decimal point. It doesn't really matter that the columns are always perfectly aligned.
"avoid losing significant digits and possibly avoid unnecessary zeros after the decimal point. It doesn't really matter that the columns are always perfectly aligned."
Ah. That turns the problem definition upon its head from the original "need to write a numeric matrix in a text file, in such a way that each row is indented at the beginning." where it was the formatting that was the issue, not the precision.
You'll come close with the default 'long g' as far as precision, but lose out on the leading blanks (and any other spacing for "prettyfiying" the file for human consumption).
Example:
>> A(1,:)=[240.14,0.0031567]
A =
240.1400 0.0032
5.0000 3.0000
3.1416 6.0000
6.0000 4.0000
8.0000 0.0000
>> writematrix(A,'test.','FileType','text')
>> type test
240.14,0.0031567
5,3
3.14159265358979,6
6,4
8,3.14159265358979e-08
>>
shows that is pretty-much what the definition of the '%g' format string is -- give most number of significant digits in least amount of white space -- but don't worry at all about column alignment or the like.
Your '%12g' has the effect of lining everything up neatly, but will truncate precision--
>> fprintf('%12g\t%12g\n',A.')
240.14 0.0031567
5 3
3.14159 6
6 4
8 3.14159e-08
>>
because when you don't specify a precision, a default precision of 5 digits precision after the decimal place is used and '%g' then picks the shorter of what '%e' or '%f' would produce for the given value. Hence something like your 0.0031567 shows up ok but if your user were to add more significant digits after the 7, they will get truncated as the value of 3.14159 for pi stored to machine precision shows.
writetable uses the equivalent of
>> fprintf('%.15g\t%.15g\n',A.')
240.14 0.0031567
5 3
3.14159265358979 6
6 4
8 3.14159265358979e-08
>>
which specifies the precision but not the field width so you get the desired "short as possible" but not the alignment since the length of the string for pi results in the second field being a couple of tabs past the location of the other records with shorter conversions.
The easiest, more compact way to to store data to be retrieved by MATLAB is to use save and load and save the data as .mat files. This, of course, isn't human readable but preserves full machine precision without you having to worry about things like format strings.
What are the immutable requirements for the application?
Yes, I probably wasn't very clear at first. Basically I was interested that the whole matrix was indented equally on the left with tabs and that significant figures are not lost, the rest is more: if the columns remain aligned, so much better for readability, but if a row has to remain offset further to the right because a value, with all its significant digits results in a very long string, that's okay. Again for a pure question of "cleanliness" if too many useless zeros are avoided it is better, otherwise it is the same. Now, without going into too much details, I seem to understand that, with values with at most 5 or 6 significant digits after the decimal point, a long g format can be a good choice for not losing data, having columns readable and sufficiently, but not strictly, aligned. What I have to do is just extrapolate some data from an external text file, stack them according to a precise criterion and then export other N text files, the really important thing is that no data information is lost and that they are indented on the left so that output files can be read by a sw, the rest is meticulousness. In any case, thank you very much for the precious clarifications, I'll think about them more thoroughly.
Well, you can do both if you add the width and precision...I didn't show; thought it would be evident
>> fprintf('%20.15g\t%20.15g\n',A.')
240.14 0.0031567
5 3
3.14159265358979 6
6 4
8 3.14159265358979e-08
>>
The file is then bigger thatn with just the '%.15g' because the alignment requires blank fill that you don't have with the variable field width.

Sign in to comment.

More Answers (0)

Asked:

on 30 Apr 2021

Commented:

dpb
on 2 May 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!