Loop through text files, replace consecutive asterisks with 0.00 - matlab

all,
I am writing a matlab program to read in text data and rearrange it. Now I am meeting with a new problem.
When I am writing data out to csv file, there are randomly missing data noted as ******, as shown below causing my program to terminate.
2055 6 17 24.2 29.57 7.02****** 0.99 2.65 2.73 4.09 0.11
Any one can help me with a small program to loop through all the text files in the folder, and replace the consecutive stars, with 0.00? The stars are always in columns 33 to 38, occupying 6 spaces. I want it to be changed to be two spaces followed by 0.00.
Thanks,
James

For a given text file, you can read it into memory, replace the asterisks with the desired text, and then overwrite the original text file:
filename = 'blah.txt'
% Read it into memory
fid = fopen(filename, 'r');
scanned_fields = textscan(fid, '%s', 'Delimiter','\n');
fclose(fid);
% The first (and only) field of textscan will be our cell array of text
lines = scanned_fields{1};
% Replace the asterisks with the desired text
lines = strrep(lines, '******', ' 0.00');
% Overwrite the original file
fid = fopen(filename, 'w');
fprintf(fid, '%s\n', lines{:});
fclose(fid);
To do this for all of the text files in your directory, you can use dir to get a list of files in your current directory that end in ".txt":
files = dir('*.m');
filenames = {files.name};
And then loop over the files:
for ii = 1:length(filenames)
filename = filenames{ii};
% Read it into memory
fid = fopen(filename, 'r');
scanned_fields = textscan(fid, '%s', 'Delimiter','\n');
fclose(fid);
lines = scanned_fields{1};
% Replace the asterisks with the desired text
lines = strrep(lines, '******', ' 0.00');
% Overwrite the original file
fid = fopen(filename, 'w');
fprintf(fid, '%s\n', lines{:});
fclose(fid);
% Go on to the next file
end
And of course, I would recommend creating a backup copy of this directory before running this, just in case something unexpected comes up.

Related

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 - string containing a number and equal sign

I have a data file that contains parameter names and values with an equal sign in between them. It's like this:
A = 1234
B = 1353.335
C =
D = 1
There is always one space before and after the equal sign. The problem is some variables don't have values assigned to them like "C" above and I need to weed them out.
I want to read the data file (text) into a cell and just remove the lines with those invalid statements or just create a new data file without them.
Whichever is easier, but I will eventually read the file into a cell with textscan command.
The values (numbers) will be treated as double precision.
Please, help.
Thank you,
Eric
Try this:
fid = fopen('file.txt'); %// open file
x = textscan(fid, '%s', 'delimiter', '\n'); %// or '\r'. Read each line into a cell
fclose(fid); %// close file
x = x{1}; %// each cell of x contains a line of the file
ind = ~cellfun(#isempty, regexp(x, '=\s[\d\.]+$')); %// desired lines: space, numbers, end
x = x(ind); %// keep only those lines
If you just want to get the variables, and reject lines that do not have any character, this might work (the data.txt is just a txt generated by the example of data you have given):
fid = fopen('data.txt');
tline = fgets(fid);
while ischar(tline)
tmp = cell2mat(regexp(tline,'\=(.*)','match'));
b=str2double(tmp(2:end));
if ~isnan(b)
disp(b)
end
tline = fgets(fid);
end
fclose(fid);
I am reading the txt file line by line, and using general expressions to get rid of useless chars, and then converting to double the value read.

MATLAB:How to copy contents from a file into a particular position of an old file

I have two text files: file1.txt & file2.txt
Contents of file1.txt:
Required contents of file;
Required contents of file;
Required contents of file;
Required contents of file;
Required contents of file;
My old contents(1);
My old contents(2);
My old contents(3);
My old contents(4);
Required contents of file;
Required contents of file;
Required contents of file;
Required contents of file;
Contents of file2.txt:
My new var(1);
My new var(2);
My new var(3);
My new var(4);
I have an updateFile.m function: which is trying to replace the old contents from file1.txt with new var respectively
function updateFile(file)
% Read the new contents
fid = fopen('file2.txt', 'r');
c1 = onCleanup(#()fclose(fid));
newVars = textscan(fid,'%s','Delimiter','\n');
newVars = newVars{1};
% Save the testfile in to a cellaray variable
fid = fopen(file, 'r');
c2 = onCleanup(#()fclose(fid));
oldContent = textscan(fid,'%s','Delimiter','\n');
% Search for specific strings
oldContentFound = strfind(oldContent{1},'My old contents(1);');
oldContentRowNo = find(~cellfun('isempty',oldContentFound));
% Move the file position marker to the correct line
fid = fopen(file, 'r+');
c3 = onCleanup(#()fclose(fid));
for k=1:(oldContentRowNo-1)
fgetl(fid);
end
% Call fseek between read and write operations
fseek(fid, 0, 'cof');
for idx = 1:length(newVars)
fprintf(fid, [newVars{idx} '\n']);
end
end
The problem I am facing is that, file1.txt still contains some old contents which are not required. Any help would be appreciated.
Thanks
You can add some characters into the file but you can't remove some. You have to erase your file with a new one that has the correct content.
Here is a rewriting of your function that does the job:
function updateFile(file)
% Read the new contents
fid = fopen('file2.txt', 'r');
newVars = textscan(fid,'%s','Delimiter','\n');
fclose(fid);
newVars = newVars{1};
% Read the old content
fid = fopen(file, 'r');
f1 = textscan(fid, '%s', 'Delimiter', '\n');
fclose(fid);
f1 = f1{1};
% Find pattern start line
[~,k] = ismember('My old contents(1);', f1);
% Replace pattern
for i = 1:numel(newVars)
f1{k+i-1} = newVars{i};
end
% Replace initial file
fid = fopen(file, 'w');
cellfun(#(x) fprintf(fid, '%s\n', x), f1);
fclose(fid);
Best,
File access is inherently byte-based. There's no such thing as inserting or deleting content at the middle of a file. In most cases, the easiest approach is to edit the content in memory, then rewrite the entire file.
In your case, after reading the input file, find the start and end rows in the cell array, and simply replace them with the new data. Then open your file again for normal writing, and output the entire cell array.

Text Scanning to read in unknown number of variables and unknown number of runs

I am trying to read in a csv file which will have the format
Var1 Val1A Val1B ... Val1Q
Var2 Val2A Val2B ... Val2Q
...
And I will not know ahead of time how many variables (rows) or how many runs (columns) will be in the file.
I have been trying to get text scan to work but no matter what I try I cannot get either all the variable names isolated or a rows by columns cell array. This is what I've been trying.
fID = fopen(strcat(pwd,'/',inputFile),'rt');
if fID == -1
disp('Could not find file')
return
end
vars = textscan(fID, '%s,%*s','delimiter','\n');
fclose(fID);
Does anyone have a suggestion?
If the file has the same number of columns in each row (you just don't know how many to begin with), try the following.
First, figure out how many columns by parsing just the first row and find the number of columns, then parse the full file:
% Open the file, get the first line
fid = fopen('myfile.txt');
line = fgetl(fid);
fclose(fid);
tmp = textscan(line, '%s');
% The length of tmp will tell you how many lines
n = length(tmp);
% Now scan the file
fid = fopen('myfile.txt');
tmp = textscan(fid, repmat('%s ', [1, n]));
fclose(fid);
For any given file, are all the lines equal length? If they are, you could start by reading in the first line and use that to count the number of fields and then use textscan to read in the file.
fID = fopen(strcat(pwd,'/',inputFile),'rt');
firstLine = fgetl(fID);
numFields = length(strfind(firstLine,' ')) + 1;
fclose(fID);
formatString = repmat('%s',1,numFields);
fID = fopen(strcat(pwd,'/',inputFile),'rt');
vars = textscan(fID, formatString,' ');
fclose(fID);
Now you will have a cell array where first entry are the var names and all the other entries are the observations.
In this case I assumed the delimiter was space even though you said it was a csv file. If it is really commas, you can change the code accordingly.

Remove Characters from EOF while Writing to File in Matlab

In Matlab, after creating a certain number of lines and printing them to a file, I have the need to delete a line and rewrite the rest of the data to that same file. When I do so, the new data overwrites the previous data, but since the data is shorter than the original, there are still remnants of the original data. Does anyone have any idea what the best/most efficient way to delete that extra data is?
Here is a simplified example of what I'm trying to do:
fid = fopen('file.txt','w');
for i=1:10
fprintf(fid,'%i\r\t',i);
end
frewind(fid);
for i=3:5
fprintf(fid,'%i\r\t',i);
end
fprintf(fid,'EOF');
fclose(fid);
I've looked all over, but I can't seem to find the solution to my question. Any suggestions?
Without using any temp files, you can do the following:
fid = fopen('file.txt', 'wt');
for i=1:10
fprintf(fid, '%i\n', i);
end
frewind(fid);
for i=3:5
fprintf(fid, '%i\n', i);
end
pos = ftell(fid); % get current position in file
fclose(fid);
% read from begining to pos
fid = fopen('file.txt', 'r');
data = fread(fid, pos);
fclose(fid);
% overwite file with data read
fid = fopen('file.txt', 'w');
fwrite(fid, data);
fclose(fid);
Printing "EOF" won't work - nice try!
There are Unix system calls truncate and ftruncate that will do that, given either a file descriptor (truncate) or handle (ftruncate) in the first argument and a desired length in the second.
I'd try and see if Matlab supports ftruncate. Failing that... if worst came to worst you could copy-write the file to a new file, stopping and closing the new file when you hit what you consider the end of data.
To follow up on Carl Smotricz's suggestion of using two files, you can use MATLAB's DELETE and MOVEFILE commands to avoid system calls:
fid = fopen('file.txt','wt');
for i=1:10
fprintf(fid,'\t%i\r',i);
end
fclose(fid);
fid = fopen('file.txt','rt');
fidNew = fopen('fileNew.txt', 'wt');
for i = 1:2
s = fgetl(fid);
fprintf(fidNew, '%s\r', s);
end
for i=4:10
fprintf(fidNew, '\t%i\r', i);
end
fclose(fid);
fclose(fidNew);
delete('file.txt');
movefile('fileNew.txt', 'file.txt')