Abort reading a txt file while it is being updated - Matlab - matlab

I have 2 instances of Matlab running. While the first is writing data to a .txt file, the other is reading that data.
Is there a way to verify that the .txt file is being accessed and accordingly throw an exception/error?
I found that the second Matlab instance reads the data anyways but generates an error such as Horzcat etc while that .txt file was being updated as well.
fName = 'Test.txt' ;
% Matlab Instance1
mat = 1 + (2-1)*randn(100000,5) ; mat = mat.' ;
[fid, fMsg] = fopen(fName, 'at') ;
if fid~=-1, fprintf(fid, '%.10f\t%.10f\t%.10f\t%.10f\t%.10f\r\n', mat(:)) ; end
fclose(fid);
% Matlab Instance2
fid = fopen(fName);
C = textscan(fid, '%f %f %f %f %f', 'Delimiter', '\t');
C=cell2mat(C);
fclose(fid);

On the writing instance create a file called 'busyWriting.bla' before opening the file for writing, delete this file after you are done writing. And on the reading instance enclose everything with the clause if(~exist('busyWriting.bla','file')) ... end

Related

Issue with format specification while reading from file Matlab

I have a .dat file with a table containing data in following order:
0,000E+0 4,069E-2 -5,954E+0 1,851E-2
What I need to do is to read this data with matlab and then somehow handle it.
Here is my code:
path = 'C:/Users/user/Desktop/file1.dat';
fileID = fopen(path,'r');
formatSpec = '%e';
A = fscanf(fileID,formatSpec);
fclose(fileID);
disp(A);
Unfortunately, it doesn't work. What did I do wrong?
After replacement of comma with dot in data you can read it using dlmread function:
M = dlmread('filename', ' ');
M is what you want.
For the first part, replacing a character, you can use the following code:
% read the file
fid = fopen('input.txt','r');
f=fread(fid,'*char')';
fclose(fid);
%replace the char
f = strrep(f,',','.');
% write into the another file
fid = fopen('output.txt','w');
fprintf(fid,'%s',f);
fclose(fid);

Read compressed files without unzipping them in Matlab

I have (very large) comma separated files compressed in bz2 format. If I un-compressed them and I read with
fileID = fopen('file.dat');
X = textscan(fileID,'%d %d64 %s %f %d %f %f %d', 'delimiter', ',');
fclose(fileID);
everything is fine. But I would like to read them without uncompressing them, something like
fileID = fopen('file.bz2');
X = textscan(fileID,'%d %d64 %s %f %d %f %f %d', 'delimiter', ',');
fclose(fileID);
which, unfortunatley, returns an empty X. Any suggestions? Do I have to uncompressed them unavoidably via the system(' ... ') command ?
You could try to use the form of textscan that takes a string instead of a stream. Using the Matlab Java integration, you can leverage Java chained streams to decompress on the fly and read single lines, which can then be parsed:
% Build a stream chain that reads, decompresses and decodes the file into lines
fileStr = javaObject('java.io.FileInputStream', 'file.dat.gz');
inflatedStr = javaObject('java.util.zip.GZIPInputStream', fileStr);
charStr = javaObject('java.io.InputStreamReader', inflatedStr);
lines = javaObject('java.io.BufferedReader', charStr);
% If you know the size in advance you can preallocate the arrays instead
% of just stating the types to allow vcat to succeed
X = { int32([]), int64([]), {}, [], int32([]), [], [], int32([]) };
curL = lines.readLine();
while ischar(curL) % on EOF, readLine returns null, which becomes [] (type double)
% Parse a single line from the file
curX = textscan(curL,'%d %d64 %s %f %d %f %f %d', 'delimiter', ',');
% Append new line results
for iCol=1:length(X)
X{iCol}(end+1) = curX{iCol};
end
curL = lines.readLine();
end
lines.close(); % Don't forget this or the file will remain open!
I'm not exactly vouching for the performance of this method, with all the array appending going on, but at least that is how you can read a GZ file on the fly in Matlab/Octave. Also:
If you have a Java stream class that decompresses another format (try e.g. Apache Commons Compress), you can read it the same way. You could read bzip2 or xz files.
There are also classes to access archives, like zip files in the base Java distribution, or tar/RAR/7z and more in Apache Commons Compress. These classes usually have some way of finding files stored within the archive, allowing you to open an input stream to them within the archive and read in the same way as above.
On a unix system I would use named pipes and do something like this:
system('mkfifo pipename');
system(['bzcat file.bz2 > pipename &']);
fileID = fopen('pipename', 'r');
X = textscan(fileID,'%d %d64 %s %f %d %f %f %d', 'delimiter', ',');
fclose(fileID);
system('remove pipename');

Appending data to a file in Matlab, removing before a symbol

I have a file which is written via Matlab from a vector M with binary data values. This file is written with Matlab's fwrite in the following script myGenFile.m of the form function myGenFile(fName, M):
% open output file
fId = fopen(fName, 'W');
% start by writing some things to the file
fprintf(fId, '{DATA BITLENGTH:%d}', length(M));
fprintf(fId, '{DATA LIST-%d:#', ceil(length(M) / 8) + 1);
% pad to full bytes
lenRest = mod(length(M), 8);
M = [M, zeros(1, 8 - lenRest)];
% reverse order in bytes
M = reshape(M, 8, ceil(length(M) / 8));
MReversed = zeros(8, ceil(length(M) / 8));
for i = 1:8
MReversed(i,:) = M(9-i,:);
end
MM = reshape(MReversed, 1, 8*len8);
fwrite(fId, MM, 'ubit1');
% write some ending of the file
fprintf(fId, '}');
fclose(fId);
Now I want to write a file myAppendFile.m, which appends some values to the existing file and has the following form: function myAppendFile(newData, fName). To do this I will have to remove the trailing '}':
fId = fopen(nameFile,'r');
oldData = textscan(fId, '%s', 'Delimiter', '\n');
% remove the last character of the file; aka the ending '}'
oldData{end}{end} = oldData{end}{end}(1:end-1);
The problem is now when trying to write oldData into the file (writing newData should be trivial, since it is also a vector of binary data like M), since it is a cell of cell arrays, containing strings.
How could I overcome this issue and append the new data correctly?
Instead of using textscan which copies the file to your memory, then writes it back, you could use fseek to set the pointer where you want to continue writing. Just put it one char before end of file and continue writing.
fseek(fid, -1, 'eof');

Loop through text files, replace consecutive asterisks with 0.00

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.

save each data in loop as text file in matlab

I am doing an operation to get a matrix M_T. This matrix is to be saved into a text file. And this text file is to be again utilized as the primary data file. This has to be repeated for 100 times. Also in the end I want to save all the data in the 100 text files generated into a single text file named final_result.txt. I am not able to figure out how to save the different text files in different names within the loop. I tried by writing the following code. But it is showing errors.
for k=1:100
fid = fopen('data1.txt');
A = textscan(fid, '%f %f %f ') ;
%read the file
a = A{1};
b = A{2};
c = A{3};
p=[a b c];
p_t=p.';
M=rotationMatrix*p_t;
M_T=M.';
fid = fopen('data1.txt', 'wt');
fprintf(fid,' %f\t %f\t %f\n',M_T);
fclose(fid);
textfilename = ['result' num2str(k) '.txt'];
fid1 = fopen('result'k '.txt', 'wt');
fprintf(fid1,' %f\t %f\t %f\n',M_T);
fclose(fid1);
end
Try this
textfilename = ['result' num2str(k) '.txt'];
fid1 = fopen(textfilename, Write);
...
this should generate a separate file resultk.txt where k = 1,...,100.
Also, you are opening the input file twice but only closing it once. I think it would be better to close the file when you open it for reading before again opening it for writing.
If this doesn't solve the problem, try posting the specific error messages you get.
To output all files to a master file, do this before the loop starts
fidresult = fopen('final_result.txt', Write);
then at each iteration
fprintf(fidresult,' %f\t %f\t %f\n',M_T);
then after the loop is finished
fclose(fidresult)
This should output your matrix at each iteration to the master result file in addition to creating an individual file for each loop iteration