Writing txt files accurately with a restriction on the number of columns.
7 views (last 30 days)
Show older comments
Okay. So I am having kind of a weird problem. I am trying to write a bunch of txt files where I have some vectors (arrays) and I print/write them in txt files using fprintf. And you know when you go into Notepad to edit a txt file and you see at the right bottom corner of the program where it says "Ln X, Col Y" where it reports which line and column the cursor is in? Well, I have a restriction where I CANNOT write information in Col that is greater than 50. So if I reach Col 50, I need to move to the next line. The problem is when I have a vector like [0,0,1,2.14,3] and lets say I reached column 50 in the fourth element of the array, I cannot simply fprintf it like this:
0,0,1,2.1
4,3
It will come out weird. I have to code it such that MATLAB knows that it will reach the 50 column and stops printing the number at the current line before moving to the next line:
0,0,1,
2.14,3
I hope I described the problem accurately for someone to help me implement this in MATLAB. Thank you.
Accepted Answer
dpb
on 16 Apr 2023
Edited: dpb
on 16 Apr 2023
a=randi(200,[1,25]);
fmt=['%d' repmat(',%d',1,numel(a)-1)];
s=sprintf(fmt,a)
LL=25;
L=strlength(s)
O=[];
while L>0
I=strfind(s,','); % locate the delimiters
J=I(find(I<=LL,1,'last')); % get the last one within line length limit
O=[O;string(s(1:J))]; % add that to the output array
s=s(J+1:end); % get the rest of the string
L=strlength(s); % recompute the length remaining
if L<=LL % handle last line w/o trailing comma
O=[O;string(s)];
L=0;
end
end
O
Now you can write the output string array with writematrix or you could echo out each line during the loop with the venerable fprintf but that requires you explicitly open/close the file.
The above seemed to get pretty klunky; I'm sure it could be optimized "more better", but seems to work ok.
"LL" is, of course, the line-length limit; set as wish...
0 Comments
More Answers (2)
Stephen23
on 16 Apr 2023
Edited: Stephen23
on 16 Apr 2023
V = randi(123,1,23)
T = sprintf('%g,',V);
U = regexprep(T,'(.{1,13}),','$1\n'); % e.g. max 13 columns
fprintf('%s',U)
And if you want to include the trailing comma:
U = regexprep(T,'.{1,12},','$&\n'); % e.g. max 13 columns
fprintf('%s',U)
Note that any single values longer than the requested column limit will not be broken over two lines.
4 Comments
dpb
on 17 Apr 2023
Edited: dpb
on 17 Apr 2023
5 columns of %3d would be 20 characters counting the comma; the same five columns as %12E.5 would be 65; it would depend on the formatting, not the number of columns to ensure didn't pass the character count oun the line...
Now, granted, OP wrote "columns" in the title, but the problem description is actually counting characters
Stephen23
on 17 Apr 2023
Edited: Stephen23
on 18 Apr 2023
"but the problem description is actually counting characters"
Correct, but for MS Notepad the "Col #" value as the OP described is a count of characters (sort of):
"this counts/limits columns not characters, correct?"
Ummm.... For MS Notepad the two are basically equivalent: the "Col #" is actually the number of the column which will get printed in at the given cursor location (note Notepad++ also uses this definition). This matches what the OP described and what my code does. You appear to be using another definition of "column", which so far you have not explicitly described.
"5 columns of %3d would be 20 characters counting the comma; the same five columns as %12E.5 would be 65"
Aaaha, so you are using your own, different definition of "column".
It appears that you are thinking of "column" in terms of something like the fields per line of a CSV file, but I do not see this definition as matching what the OP described, nor the behavior of my code, nor does it match what MS Notepad provides with the "Col #" value (see OP's question above and also the MS Notepad screenshot). The OP explicitly referred to the the MS Notepad context and meaning.
Still, not very relevant for my code, which limits the columns (as MS Notepad and the OP consistently use the term, or equivalently the number of characters) per line.
"this counts/limits columns not characters, correct?"
So it appears the answer to your very first question is "no, not as you use the term".
In any case, I presume that a simple test would also resolve your question:
V = randi(123,1,23)
T = sprintf('%12e5,',V);
U = regexprep(T,'(.{1,20}),','$1\n'); % e.g. max 20 columns
fprintf('%s',U)
dpb
on 16 Apr 2023
Still with same idea but a little cleaner implementation...
%a=randi(200,[1,25]);
%fmt=['%d' repmat(',%d',1,numel(a)-1)];
%s=sprintf(fmt,a)
s = '169,69,96,41,196,14,77,27,21,47,155,58,60,100,37,168,68,126,49,189,136,70,85,95,76'
LL=25; % max line length
I=strfind(s,','); % breakpoints
for i=I(fliplr(find(diff(ceil(strfind(s,',')/(LL-1)))))) % insert from back to front
s=insertAfter(s,i,newline);
end
s
strfind(s,newline) % all \n < LL*l where l is line number
2 Comments
Stephen23
on 16 Apr 2023
Edited: Stephen23
on 16 Apr 2023
The last line does not seem to be split correctly, it always includes the two last values:
s = '123,456,789'
LL=4; % max line length
I=strfind(s,','); % breakpoints
for i=I(fliplr(find(diff(ceil(strfind(s,',')/(LL-1)))))) % insert from back to front
s=insertAfter(s,i,newline);
end
disp(s)
dpb
on 16 Apr 2023
I didn't check anything but longer values; seemed to work for that so I'm not sure -- the rounding is probably suspect...
See Also
Categories
Find more on Environment and Settings in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!