MATLAB read formatted numbers from a file after a certain line - matlab

I have a file that contains arbitrary lines of characters/numbers. I need to extract formatted number after a certain line as follows:
Start of text file
Here is arbitrary lines of characters and numbers
1 -100
2 -200
...
ABC
1 2 3
...
Start extracting the following formatted numbers after the blank line
10 1.5-04
20 -1.6-04
100 1.7-04
200 1.8-04
300 -1.9-04
400 -2.0-04
Stop reading when you find the previous blank line
Then more arbitrary lines of characters and numbers
ABC
1 2 3
Then end of file
Using MATLAB, the question is how to extract the two columns of formatted numbers starting from (10 1.5-04) to (400 -2.0-04) after reaching the line that says "Start extracting the following formatted numbers after the blank line." Note the length of this column is not known in advance.

I use regex to extract the numbers form your text, but I can't write a specific expression to extract the two columns because there is no such a text before and after these values can rely on.
clear
text = fileread('test_file.txt');
pattern = '(?=(\s|-)[\d]+)(-|\s)[\d]+';
%pattern = '((\s|-)[\d]+)';
out = regexp(text, pattern,'match')
I hope my code gives you an idea ^-^

(1) Read file line by line
(2) Find keyword to start reading after
(3) Read formatted number
(4) Leave file when done with formatted numbers
clc;close all; clear *
filename='Test.txt';
File = fopen(filename,'r');
LineCont=0; %Line counter
Flag=0; %Flag to start extracting formatted numbers
st2='Start extracting the'; %Keyword
%Read file line by line
tline = fgetl(SGDFile); %Read first line
while ischar(tline)
Lcont=Lcont+1; %Line number
k = strfind(tline,st2); %Check for keywork to start extracting
if ~isempty(k) %Start extracting numbers
Flag=1; %Flag to start reading formatted numbers
Num=[]; %Collect formatted numbers here
end
tline = fgetl(File); %Move to next line
if tline ~=-1 %If not empty
if Flag==1
value = strsplit(tline); %Split numbers and text
num= str2num(char(value))'; %Convert text to number
if size(num,1)<1 %Stop reading when blank
break %Exit loop
else
Num=[Num;num]; %Collect formatted numbers
end
end
end
end
fclose(File);
This might be an inefficient way of doing it, but it works.

Related

read text file that has repeating blocks of data in matlab

I have a text file of the following form:
...
3
x= 0.10000 3 s
A -1.554489099 -6.345000000 0.55574511
A 6.346000000 -0.134800000 4.45454546
V -1.666613300 -6.333453600 -2.11111145
3
x= 0.20000 3 s
A 7.777755558 -4.033333330 -5.323232323
A 8.122322238 -5.007007007 2.045467754
V -2.443366723 -5.222333337 -6.868889099
3
...
the first line is mostly spaces and a number, the second line has a variable I want to aggregate (x=some number), and ignore the rest of the line, and the next 3 lines have all variables I also want to aggregate in an array form (the A,A,V), and this repeats again and again.
I would like to read this text file such that I will have a vector (1xn) for x values, and a 3D array (3x3xn) for the A,A,V values as function of x.
What I have tried is to read line by line using fgetl(fid) but this gives me for each line a vector of char that I can't work with. I've also tried dlmread but the file structure doesn't work here.
How can I read such a text file in a form that I can use?
So with the help of strsplit this is the solution I've got:
(if there is something better I can do please let me know)
fid = fopen(fn);
n=0;
while true
tline = fgetl(fid);
if ~ischar(tline); break; end %end of file
n=n+1;
c{n}=strsplit(tline);
end
Names={c{3}{1},c{4}{1},c{5}{1}}; % the A A V
k=0;
for n=2:5:numel(c)
k=k+1;
x(k)=str2num(c{n}{3});
for j=1:numel(Names)
AAV(j,:,k)= cell2mat(cellfun(#str2num,c{n+j}(2:4),'un',0));
end
end

how to get the line number having a specific string in a txt file - matlab

I have a txt file that has a lot of content and in this file there is a lot of "include" word and I want to get data from all three lines after that.
myFile.txt:
"-include:
-6.5 6.5
sin(x^2)
diff
-include
-5 5
cos(x^4)
diff"
How do I get this data in an array?
Based on your example (first include has : at the end, second one doesn't) you could use something like this.
fID = fopen('myFile.txt'); % Open the file for reading
textString = textscan(fID, '%s', 'Delimiter', '\n'); % Read all lines into cells
fclose(fID); % Close the file for reading
textString = textString{1}; % Use just the contents on the first cell (each line inside will be one cell)
includeStart = find(contains(textString,'include'))+1; % Find all lines with the word include. Add +1 to get the line after
includeEnd = [includeStart(2:end)-2; length(textString)]; % Get the position of the last line before the next include (and add the last line in the file)
parsedText = cell(length(includeStart), 1); % Create a new cell to store the output
% Loop through all the includes and concatenate the text with strjoin
for it = 1:length(includeStart)
parsedText{it} = strjoin(textString(includeStart(it):includeEnd(it)),'\n');
% Display the output
fprintf('Include block %d:\n', it);
disp(parsedText{it});
end
Which results in the following output:
Include block 1:
-6.5 6.5
sin(x^2)
diff
Include block 2:
-5 5
cos(x^4)
diff
You can tune the loop to suit your needs. If you just want line numbers, use includeStart and includeEnd variables.

Change text line in a file by using Matlab

So I have to modify a .dxf file (an Autocad file) by changing some data in it for another one we choose previously. Changing some lines of a .txt file in Matlab is not pretty difficult.
However, I cannot change a specific line when the new input's length is larger than the old one.
This is what I have and I want to change only 1D57:
TEXT
5
1D57
330
1D52
100
AcDbEntity
8
0
If I have as an input BBBB, everything goes right since both strings have the same length. The same does not apply when I try with BBBBbbbbbbbbbb:
TEXT
5
BBBBbbbbbbbbbb2
100
AcDbEntity
8
0
It deletes everything after it until the string stops. It happens the same when the input is shorter: it does not change the line for the new string but it writes until the new input stops. For example, in our case with AAA as an input, the result would be AAA7.
This is basically the code I am using to modify the file:
fID = fopen('copia.dxf','r+');
for i = 1:2
LineToReplace = TextIndex(i);
for k = 1:((LineToReplace) - 1);
fgetl(fID);
end
fseek(fID, 0, 'cof');
fprintf (fID, [Data{i}, '\n']);
end
fclose(fID);
You need to overwrite at least the rest of the file in order to change it (unless exact number of characters is replaced), as explained in jodag's comment. For instance,
% String to change and it's replacement
% (can readily be automated for more replacements)
str_old = '1D52';
str_new = 'BBBBbbbbbbbbbb';
% Open input and output files
fIN = fopen('copia.dxf','r');
fOUT = fopen('copia_new.dxf','w');
% Temporary line
tline = fgets(fIN);
% Read the entire file line by line
% Write it to the new file
% Replace str_old with str_new when encountered - note, if there is more
% than one occurence of str_old in the file all will be replaced - this can
% be handled with a proper flag
while (ischar(tline))
% char(10) is MATLAB's newline character representation
if strcmp(tline, [str_old, char(10)])
fprintf(fOUT, '%s \n', str_new);
else
% No need for \n - it's already there as we're using fgets
fprintf(fOUT, '%s', tline);
end
tline = fgets(fIN);
end
% Close the files
fclose(fIN);
fclose(fOUT);
% Copy the new file into the original
movefile 'copia_new.dxf' 'copia.dxf'
In practice, it is often far easier to simply overwrite the whole file.
As written in the notes - this can be automated for more replacements and it would also need an additional flag to only replace a given string once.

How to read in lines of unequal length CSV doubles

I have a file where each line is a list of CSV doubles, i.e:
80,81,179,180,181,182
114,115,27,31,34
16,17,18,25
63,64,35,58,73,75,76,94,95
67,68
I need to read in each line, temporarily store it as a 1 x n double array for some calculations, then move onto the next line.
The idea I had was:
fid = fopen('fileName.txt');
tline = fgets(fid);
while ischar(tline)
% Update with solution I came up with
values = cellfun(#str2double,regexp(tline,',', 'split'));
tline = fgets(fid);
end
You can search for the commas contained in each line and the either use the indexes of their location in the string or their amount to loop till the end of the line.

MATLAB - How to save vectors with different length

I created a file that contains vectors and these could have empty space between their elements.
-77.4 1 0.17 260 88 1004.0 1006.5
-77.3 1 0.17 1009.2 1011.8
I save the file 'myfile.txt' row by row with fprintf() function.
Well, when I load the file with the command load('myfile.txt') I receive this error message "Number of columns on line ... must be the same as previous lines"
How can I fix it? Perhaps save the row vectors by another way? How to do?
Thank you
You would be better off by using the save command as #maxywb stated in his comment, but if you find yourself in a situation where you have a text file that does not have consistent column numbers, you can parse the file line by line and save the results into a cell array
fid = fopen('myFile.txt','r');
values = {};
count = 1;
tline = fgets(fid);
while ischar(tline)
values{count} = textscan(tline,'%f','delimiter',', ');
count = count+1;
tline = fgets(fid);
end
fclose(fid)