read text file that has repeating blocks of data in matlab - 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

Related

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.

MATLAB read formatted numbers from a file after a certain line

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.

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.

GNU-Octave: load data which contains geometric lines as blocks of coordinates

I would know if there is a way to load data stored like this in a file:
$ cat foo
12.108 24.21; 89.02 17.3131; 93.192368 13.10012; ....
10.3069 41.7442; 90.1277 19.351; 93.192368 13.10012; 91.1956 15.29712; ...
...
So the form is:
x y; x y; x y; and so on.
Each point defined by a couple of x y values is a point constituting a geometric line.
Each line of the file contains a unique geometric line which is defined by its sequence of points. Some lines are made of only two points, others of several. It varies. So as there is no constant number of fields I'm now unable to load that file.
Ideally, I'd like to store each line in a variable, or better, all lines in a kind of indexed structure, cell or nD-matrix so that I can further easily loop on their segments (a segment is defined by 2 consecutive points within a line).
Thanks.
Storing data in an array seems to be an elegant solution:
fid=fopen("File.csv");
tline=fgetl(fid);
ix=1;
while ischar(tline)
A{ix}=str2num(tline);
tline=fgetl(fid);
ix=ix+1;
end
fclose(fid);
Open the file using fopoen
Use fgetl to initialize tline with
Set an iterative value, here ix, to 1 (avoiding i is a good idea as it is also a mathematical constant...)
While tline is a char (remember, at the end of file fgetl returns -1) store the fgetl returned line converted to a num value using str2num in the A{ix} part of the A array.
Don't forget to close the file with fclose.
Thus, A{ix} is taking the ix-th line of the input file in (x,y) structured sub-arrays:
> A{1}
ans =
12.108 24.21
89.02 17.3131
93.192368 13.10012
...
> class(A{1})
ans = double
https://www.gnu.org/software/octave/doc/v4.0.0/Opening-and-Closing-Files.html
https://www.gnu.org/software/octave/doc/v4.0.0/Line_002dOriented-Input.html

Parsing a data file in matlab

I have a text file with two columns of data. I want to split this file and save it as two individual strings in matlab, but I also need to stop copying the data when I meet an identifier in the data then stat two new strings.
For example
H 3
7 F
B B
T Y
SPLIT
<>
Where SPLIT <> is where I want to end the current string.
I'm trying to use fopen and fscanf, but struggling to get it to do what I want it to.
I tried the following script on the example you provided and it works. I believe the comments are very self explanatory.
% Open text file.
fid = fopen('test.txt');
% Read the first line.
tline = fgetl(fid);
% Initialize counter.
ii = 1;
% Check for end string.
while ~strcmp(tline, 'SPLIT')
% Analyze line only if it is not an empty one.
if ~strcmp(tline, '')
% Read the current line and split it into column 1 and column 2.
[column1(ii), column2(ii)] = strread(tline, ['%c %c']);
% Advance counter.
ii = ii + 1;
end
% Read the next line.
tline = fgetl(fid);
end
% Display results in console.
column1
column2
% Close text file.
fclose(fid);
The key functions here are fgetl and strread. Take a look at their documentation, it has some very nice examples as well. Hope it helps.