Hello everyone,
I have a .dat file like in the picture and I would like to modify I3 values (the last column). I can't use textscan since the beginning of the file has a different format.
Do you have any idea on how can I do this ?

3 Comments

Rik
Rik on 3 Sep 2020
There are many methods to read files besides textscan. A simple google search should have turned up several.
What release are you using? Do you want to write the modified data exactly as it is in the original file? Then it might make the most sense to read as text and modify the char array directly.
Izem
Izem on 3 Sep 2020
Thank you sir for your answer !
I am using Matlab 2019b. Yeah I want to keep everything exactely the same except the last column where I want to replace the values by (old values+Delta(m,n)) .
How can I get the char array ?
Sorry for my stupid question. I am new to Matlab.
I think you mean :
C = fileread('text.dat');
Then I can modify those values. Thanks again.

Sign in to comment.

 Accepted Answer

Rik
Rik on 3 Sep 2020
You can get my readfile function from the FEX or through the AddOn-manager (R2017a or later).
data=readfile(filename);
HeaderLines=9;
delta=rand(numel(data)-HeaderLines,1);%generate some random data for this example
for n=(HeaderLines+1):numel(data)
%store in temp variable
str=data{n};
%read the value, add something to it, and merge back
ind=strfind(str,' ');ind=ind(end)+1;%assumes you don't have a trailing space and the delimiter is a space
lastval=str2double(str(ind:end));
lastval=lastval+delta(n-HeaderLines);
str=sprintf('%s%.3f',str(1:(ind-1)),lastval);
%store back to array
data{n}=str;
end
%write back to file (overwrites the original)
fid=fopen(filename,'wt');
fprintf(fid,'%s\n',data{:});
fclose(fid)

17 Comments

Izem
Izem on 8 Sep 2020
Hello, I have many errors.
-readfile does not exist
-'str=data{n};' I can't store data in this type of variable
-Problems with indices
Please find attached the text file
Rik
Rik on 8 Sep 2020
Which release are you using?
If you are using R2017a or later you will see an 'Add-Ons' button in the lint if click on the 'HOME' tab. If you click on it you will see a window with a search box. Type readfile and hit enter. My submission should be one of the top results. Click on it (the name or the icon; both will work). Now will see the button 'Add from GitHub'. Once you click it and wait a few seconds you will see a green banner over the icon saying 'Installed'. That means you can use the function.
If you have R2016b or earlier you will have to get it manually. Go to the link I provided in my answer. There you can click the button 'Download from GitHub'. That will download a zip file. Somewhere in that zip file you will find readfile.m. Put that file in your current folder, or put it somewhere on you path (e.g. create a folder C:\FEX-submissions\ put readfile.m there and run addpath('C:\FEX-sumissions\','-end');).
Tell me which one of the two options you tried and what if anything went wrong when getting readfile. You can use the second option for newer releases as well if you prefer.
Izem
Izem on 8 Sep 2020
I got the readfile function. Here is the error I have now :
'Array indices must be positive integers or logical values.'
Izem
Izem on 8 Sep 2020
I copied only the readfile.m in y folder. It s enough right ?
Your file has a trailing empty line. Put the code below at the start of the loop:
if isempty(data{n}),continue,end
Izem
Izem on 8 Sep 2020
Finally, it works. Thank you sir!
Izem
Izem on 8 Sep 2020
Sorry to bother you again I have another problem here.
Actually for the same m and n, The correction is the same so the size of my correction list is inferior than the number of lines in the text file (without headerlines). For example, as you can see in the picture, the first 5 lines that start with m = 0 and n = 1 have only one corresponding correction that should be added to all the five values in the last column of the text file.
I ve tried to convert the data{n} to num and then compare the two first values but when I go back to str after the modification, i don't find exactely the same format (there is a lot of spaces) Do you have any idea on how I can do this ?
Rik
Rik on 8 Sep 2020
How did you try to determine the values of m and n on a single line? That is your goal. Don't modify anything elso on the line, make a copy if you need to. Also note that m has values of 0, so those aren't valid Matlab indices.
Izem
Izem on 8 Sep 2020
I think you didn't get my request. Actually, what I asked for in the beggining was not what I wanted, your solution works perfect according to what I asked at the beggining. But now, I want to modify the alogithm so that for the same m and n, the addes value to the last column is the same like for example :
for m = 0 and n = 1
I3
96,84+val1
91.04+val1
89.75+val1
84.36+val1
83.96+val1
Rik
Rik on 8 Sep 2020
I did understand you. You just need to find a way to extract the values of m and n from a single line and use those to find the value you want to add. So how did you try to find m and n? Are m and n guaranteed to be single digit integers? That would make it a lot easier, although you could also just use textscan on the single lines by this point.
Izem
Izem on 8 Sep 2020
Ah I see. Wel, I Tried str2num to access m and n and then compare with the table where I have val1,val2..
m and n are integers between 0 and 100, would that makes it easy ? you think textscan is the way to go ?
Rik
Rik on 8 Sep 2020
Who taught you str2num? All the way back to at least R2011a you can read the advice to choose str2double instead. I don't think there is only one way to go, but str2num is certainly a worse choice than textscan.
What release are you using?
Izem
Izem on 8 Sep 2020
I m bginner in Matlab so I knew cell2mat and I tried to do the same with num and str. I am using 2019b.
You should really read the documentation. It is one of the major benefits of Matlab. As for this specific problem: you can easily get the values for m and n:
data=readfile('https://www.mathworks.com/matlabcentral/answers/uploaded_files/357712/Matlab.txt');
str=data{10};%select the first line to show the example
vals=textscan(str,' %f %f %f %f %f %f %f');
m=vals{1};n=vals{2};
Here is what I did and it worked well but is there any bad programming there ?
for i=(HeaderLines+1):numel(data)
%store in temp variable
if isempty(data{i}),continue,end
str=data{i};
vals=textscan(str,' %f %f %f %f %f %f %f');
m=vals{1}; n=vals{2};
for j=1:length(correction)
if m == str2double(mcorrection(j)) && n == str2double(ncorrection(j))
%read the value, add something to it, and merge back
ind=strfind(str,' ');ind=ind(end)+1;%assumes you don't have a trailing space and the delimiter is a space
lastval=str2double(str(ind:end));
lastval=lastval+correction(j);
str=sprintf('%s%.3f',str(1:(ind-1)),lastval);
%store back to array
data{i}=str;
end
end
end
%write back to file (overwrites the original)
fid=fopen(newname,'wt');
fprintf(fid,'%s\n',data{:});
fclose(fid);
Rik
Rik on 9 Sep 2020
I would separate finding the value of the correction and using it. I also would not use i and j as variables. You might also consider using ismember and/or find. A possible optimization would be to convert the mcorrection and ncorrection arrays to double only once (so outside the loop).
So no, I don't see any 'bad programming' here.
Izem
Izem on 9 Sep 2020
Alright! thank you sir for your help, I do appreciate it !

Sign in to comment.

More Answers (0)

Categories

Products

Release

R2019b

Tags

Asked:

on 3 Sep 2020

Commented:

on 9 Sep 2020

Community Treasure Hunt

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

Start Hunting!