import data into matlab from .cnv file - matlab

I am attempting to read some data from a .cnv file. I can open the file with:
TopFolder = 'Name_of_my_file';
SubFolder = dir(fullfile(TopFolder,'*.cnv'));
fid = fopen(fullfile(TopFolder,SubFolder{i}));
All of the data is located following the string END, which is on a separate line to the other headers. I would like to import the data that is stored on the lines following this string. How can this be achieved?
For example, the a section of the .cnv file is as follows:
# datcnv_in = D:\data\110606_000.hex D:\instrument software\Seabird 2010-07\Seabird Con Files\SBE19_2108_ScufaTOBS.con
# datcnv_skipover = 0
# file_type = ascii
*END*
-0.051 0.0312 15.4328 138.1551 0.0000 0.0000 0.0000 0.0000 0.000e+00
-0.033 0.0305 15.4277 138.1551 0.0000 0.0000 0.0000 0.0000 0.000e+00
So, I would like to avoid those lines prior to End
Maybe a first step would be to find the line number of END? How would I do this?

First of all open the file and search through the lines until you find 'END'
fid = fopen('yourfile.cnv') % open file to read
fseek(fid,0,-1); % set read position to beginning of file
while strcmp(fgetl(fid),'*END*') == 0 end % go through lines until '*END*'
Next read data, line by line, into a matrix (data):
n=1;
while 1
tline = fgetl(fid) % read in line
if ~ischar(tline), break, end % if eof, break and finish
data(:,n) = sscanf(tline,'%f') % put numbers in a matrix (in columns)
n=n+1
end
fclose(fid) % close file

When using the import wizard in matlab you can specify the number of header rows.
If you set this to four, it should work in this example.
After using the import wizard you can let it generate code if you want to automate the process for the future.

Try this:
L = '';
while isempty(findstr(L,'*END*')) % if the line doesn't contain *END* => read a new line
L = fgetl(fid); % read next line of file
end
a = fscanf(fid,'%g %g %g %g'); % add as many %g as columns in your data
fclose(fid);
I've added some comments on how this works. Basically, this reads the opened file line by line until it finds a line containing *END*.
You could use strcmp(L,'*END*') if there is more than 1 line that may contain the same characters.
A warning: this code assumes that the file you are reading contains at least one line that has the *END* characters, if not, you'll get an error when attempting to read beyond the EOF.
Hope this helps.

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.

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.

MATLAB: Get variable from textfile

I've been trying to obtain a variable from a text file which I read in within the Matlab workspace.
The file contains the following:
---------------------------------------------------------------
Surface Forces (referred to Sref,Cref,Bref about Xref,Yref,Zref)
Standard axis orientation, X fwd, Z down
Sref = 35.00 Cref = 2.4325 Bref = 14.5000
Xref = 18.5306 Yref = 0.0000 Zref = -0.7092
n Area CL CD Cm CY Cn Cl CDi CDv
1 35.263 0.6972 0.0138 4.8547 0.0040 0.0069 -0.2817 0.0138 0.0000 F27 WING
Surface Forces (referred to Ssurf, Cave about root LE on hinge axis)
n Ssurf Cave cl cd cdv cm_LE
1 35.263 2.432 0.6920 0.0137 0.0000 0.0000 F27 WING
---------------------------------------------------------------
I need the value below CL, in this case its 0.6972. I've tried using fopen and importdata without succes. The importdata just puts the whole file in a cell array with 9 rows and 1 column containing all strings. From there I dont't know how to proceed further.
With the fopen, I've tried to read the file line by line and to check whether he finds the CL string. He does find it but the value its gives is [].
Can anyone give me a tip? Thank you.
Use fgetl() to extract lines you don't need, then use fscanf() to read a line of data into a vector ('dataline'). Then you can access the individual elements of the vector.
Example based on your file:
Open and read file, discarding first 7 lines, including blank lines:
fid = fopen(filename, 'r')
for i = 1:7
oneline = fgetl(fid);
end
read 8th line of file; store in a vector of floats
dataline = fscanf(fid, ['%f' ])
assign third value of vector to 'CL'
CL = dataline(3)
fclose(fid)
CL
ans =
0.6972
If you have the luxury of having one of the newer versions of Matlab, then the following will work.
B = readtable('test.dat'),'Delimiter','\t');
c = regexp(B{9,:}, ' ','split');
CL_vec = c{1,1};
CL_cell = CL_vec(13);
Wing_CL = str2num(CL_cell{1,1});

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)

Problem (bug?) loading hexadecimal data into MATLAB

I'm trying to load the following ascii file into MATLAB using load()
% some comment
1 0xc661
2 0xd661
3 0xe661
(This is actually a simplified file. The actual file I'm trying to load contains an undefined number of columns and an undefined number of comment lines at the beginning, which is why the load function was attractive)
For some strange reason, I obtain the following:
K>> data = load('testMixed.txt')
data =
1 50785
2 58977
3 58977
I've observed that the problem occurs anytime there's a "d" in the hexadecimal number.
Direct hex2dec conversion works properly:
K>> hex2dec('d661')
ans =
54881
importdata seems to have the same conversion issue, and so does the ImportWizard:
K>> importdata('testMixed.txt')
ans =
1 50785
2 58977
3 58977
Is that a bug, am I using the load function in some prohibited way, or is there something obvious I'm overlooking?
Are there workarounds around the problem, save from reimplementing the file parsing on my own?
Edited my input file to better reflect my actual file format. I had a bit oversimplified in my original question.
"GOLF" ANSWER:
This starts with the answer from mtrw and shortens it further:
fid = fopen('testMixed.txt','rt');
data = textscan(fid,'%s','Delimiter','\n','MultipleDelimsAsOne','1',...
'CommentStyle','%');
fclose(fid);
data = strcat(data{1},{' '});
data = sscanf([data{:}],'%i',[sum(isspace(data{1})) inf]).';
PREVIOUS ANSWER:
My first thought was to use TEXTSCAN, since it has an option that allows you to ignore certain lines as comments when they start with a given character (like %). However, TEXTSCAN doesn't appear to handle numbers in hexadecimal format well. Here's another option:
fid = fopen('testMixed.txt','r'); % Open file
% First, read all the comment lines (lines that start with '%'):
comments = {};
position = 0;
nextLine = fgetl(fid); % Read the first line
while strcmp(nextLine(1),'%')
comments = [comments; {nextLine}]; % Collect the comments
position = ftell(fid); % Get the file pointer position
nextLine = fgetl(fid); % Read the next line
end
fseek(fid,position,-1); % Rewind to beginning of last line read
% Read numerical data:
nCol = sum(isspace(nextLine))+1; % Get the number of columns
data = fscanf(fid,'%i',[nCol inf]).'; % Note '%i' works for all integer formats
fclose(fid); % Close file
This will work for an arbitrary number of comments at the beginning of the file. The computation to get the number of columns was inspired by Jacob's answer.
New:
This is the best I could come up with. It should work for any number of comment lines and columns. You'll have to do the rest yourself if there are strings, etc.
% Define the characters representing the start of the commented line
% and the delimiter
COMMENT_START = '%%';
DELIMITER = ' ';
% Open the file
fid = fopen('testMixed.txt');
% Read each line till we reach the data
l = COMMENT_START;
while(l(1)==COMMENT_START)
l = fgetl(fid);
end
% Compute the number of columns
cols = sum(l==DELIMITER)+1;
% Split the first line
split_l = regexp(l,' ','split');
% Read all the data
A = textscan(fid,'%s');
% Compute the number of rows
rows = numel(A{:})/cols;
% Close the file
fclose(fid);
% Assemble all the data into a matrix of cell strings
DATA = [split_l ; reshape(A{:},[cols rows])']; %' adding this to make it pretty in SO
% Recognize each column and process accordingly
% by analyzing each element in the first row
numeric_data = zeros(size(DATA));
for i=1:cols
str = DATA(1,i);
% If there is no '0x' present
if isempty(findstr(str{1},'0x')) == true
% This is a number
numeric_data(:,i) = str2num(char(DATA(:,i)));
else
% This is a hexadecimal number
col = char(DATA(:,i));
numeric_data(:,i) = hex2dec(col(:,3:end));
end
end
% Display the data
format short g;
disp(numeric_data)
This works for data like this:
% Comment 1
% Comment 2
1.2 0xc661 10 0xa661
2 0xd661 20 0xb661
3 0xe661 30 0xc661
Output:
1.2 50785 10 42593
2 54881 20 46689
3 58977 30 50785
OLD:
Yeah, I don't think LOAD is the way to go. You could try:
a = char(importdata('testHexa.txt'));
a = hex2dec(a(:,3:end));
This is based on both gnovice's and Jacob's answers, and is a "best of breed"
For files like:
% this is my comment
% this is my other comment
1 0xc661 123
2 0xd661 456
% surprise comment
3 0xe661 789
4 0xb661 1234567
(where the number of columns within the file MUST be the same, but not known ahead of time, and all comments denoted by a '%' character), the following code is fast and easy to read:
f = fopen('hexdata.txt', 'rt');
A = textscan(f, '%s', 'Delimiter', '\n', 'MultipleDelimsAsOne', '1', 'CollectOutput', '1', 'CommentStyle', '%');
fclose(f);
A = A{1};
data = sscanf(A{1}, '%i')';
data = repmat(data, length(A), 1);
for ctr = 2:length(A)
data(ctr,:) = sscanf(A{ctr}, '%i')';
end