How to get number from file in matlab? - matlab

In my program I want to save the counter value. Like 1 and if the counter increased then 1 will be replace with 2 like that. I created a file test.txt and manually entered a number 1, in the directory and used this code to read that number.
f=fopen('test.txt');
cno=fread(f);
cno
fclose(f);
But the value of cno is in ASCII I guess because its saved like this in file.
I try to used functions like parseInt but didn't work.
Please tell me how to write as well as read a number from file.
Also if there is any other way possible to save that counter value instead of file. I want to retain value even If I close matlab code that's why I am saving it to the file.

There are a couple methods for this. If you don't need to ensure compatibility with external programs, then MATLAB's save and load commands should be more than sufficient.
A basic example:
a = 5;
save('test.mat', 'a');
clear a
load('test.mat');
disp(a)
See the documentation for save for syntax information.
As a general note I would advise calling load with an output declared, which will load all of the variables in your saved *.mat file into a structure, preventing them from overwriting existing data in your workspace.
Using test.mat from the previous example:
mydata = load('test.mat');
disp(mydata.a)
EDIT: Now, if you wanted to store this to a generic file, the most common method would be to use fprintf and fscanf:
a = 5;
fID = fopen('test.txt', 'w+');
fprintf(fID, '%u', a);
fclose(fID);
clear a
fID = fopen('test.txt', 'r')
a = fscanf(fID, '%u');
fclose(fID);

Related

Efficiency loading a file into Matlab

I am trying to load a file in Matlab. But I am a bit confused about the best way to do it.
The file has 3 columns and looks like the screenshot below:
This file I can load very quickly by doing load('c').
However, I had to add 2 NaNs on the bottom row.
The original file actually looks like the file below:
Now if I do load('c') on the file below I get the error:
Error using load
Unable to read file 'c'. Input must be a MAT-file or an ASCII file containing numeric
data with same number of columns in each row.
Of course I can use ImportData to import this file, but it is just soooo slow to import it.
Any suggestions?
You should be able to use c = readtable('c'). This should automatically change the empty entries to "NaN" by default, but if not, there is a way to set that in the options.
If I have a file that is tricky to import (prior to readtable()...that made things a lot easier in the last few years), I will often use the Import Data tool (if its a really big file you can make a mock-up of the complicated file so it loads faster) then change all the import settings as I would want it, then where the green check says "Import Selection" use the black drop down arrow to select "Generate Function." This will give you the coded way of setting everything up to get the file in just the way you want it.
load() is better suited for reading in previously saved '.mat' files that were created in Matlab.
Here's a low-level approach, which might be faster than other methods:
filename = 'c'; % name of the file
N = 3; % number of columns
fid = fopen(filename, 'r'); % open file for reading
x = fscanf(fid, '%f'); % read all values as a column vector
fclose(fid); % close file
x = [x; NaN(N-mod(numel(x)-1,N)-1, 1)]; % include NaN's to make length a multiple of N
x = reshape(x, N, []).'; % reshape to N columns in row-major order

how to read binary format byte by byte in MATLAB

I have been struggling with this bug. When using MATLAB to read a binary file that contains three columns of numbers in float formats.
I am reading one number at a time using this line.
pt(j) = fread(fid,1,'float','a');
I have found that sometimes (rarely) MATLAB instead of reading four bytes for a float, it uses 5 bytes. And it misses up the rest of the reading. I am not sure if the file is corrupted or MATLAB has a bug there. When I printed the file as a txt and read it in txt everything works well.
As a work around here is what I did:
cur = ftell(fid);
if (cur - prev)~= 4
pt(j) = 0; % I m throwing this reading away for the sake of saving the rest of the data. This is not ideal
cur = prev +4;
fseek(fid, cur,'bof');
end
prev = cur;
I tried different combinations of different formats float32 float64 etc... nothing works MATLAB always read 5 bytes instead of 4 at this particular location.
EDIT:
To solve it based on Chris's answer. I was using this command to open the file.
fid = fopen(fname,'rt');
I replaced it with this
fid = fopen(fname,'r');
Sometimes, rarely, skipping a byte. It sounds to me like you are on Windows, and have opened the file in text mode. See the permissions parameter to the fopen function.
When opening a file in text mode on Windows, the sequence \r\n (13,10) is replaced with \n (10). This happens before fread gets to it.
So, when opening the file, don't do:
fid = fopen('name', 'rt');
The t here indicates "text". Instead, do:
fid = fopen('name', 'r');
To make this explicit, you can add b to the permissions. This is not documented, but is supposed to mean "binary", and makes the call similar to what you'd do in C or in the POSIX fopen():
fid = fopen('name', 'rb');

How do I write a MATLAB code that edits another MATLAB file (.m)?

I have two files, Editor.m and Parameters.m. I want to write a code in Editor.m that when run does the following task:
reads Parameters.m
searches for a line in it (e.g. dt=1)
replaces it with something else (e.g. dt=0.6)
saves Parameters.m.
So, at the end of this process, Parameters.m will contain the line dt=0.6 instead of dt=1, without me having edited it directly.
Is there a way to do this? If so, how?
You can use regexprep to replace the value of interest.
% Read the file contents
fid = fopen('Parameters.m', 'r');
contents = fread(fid, '*char').';
fclose(fid);
% Replace the necessary values
contents = regexprep(contents, '(?<=dt=)\d*\.?\d+', '0.6');
% Save the new string back to the file
fid = fopen('Parameters.m', 'w');
fwrite(fid, contents)
fclose(fid)
If you can guarantee that it will only ever appear as 'dt=1', then you can use strrep instead
contents = strrep(contents, 'dt=1', 'dt=0.6');

Matrix segmentation into files in Matlab

I have a very large matrix (M X N). I want to divide matrix into 10 equal parts (almost) and save each of them into a separate file say A1.txt, A2.txt, etc. or .mat format. How can I do this ?
Below is a code to divide a matrix into 10 equal parts and data_size is (M / 10).
for i=1:10
if i==1
data = DATA(1:data_size,:);
elseif i==10
data = DATA((i-1)*data_size+1:end,:);
else
data = DATA((i-1)*data_size+1: i*data_size,:);
end
save data(i).mat data
% What should I write here in order to save data into separate file data1.mat, data2.mat etc.
end
You said you wanted it in either txt format or mat format. I'll provide both solutions, and some of this is attributed to Daniel in his comment in your post above.
Saving as a text file
You can use fopen to open a file up for writing. This returns an ID to the file that you want to write to. After this, use fprintf and specify the ID to the file that you want to write to, and the data you want to write to this file. As such, with sprintf, generate the text file name you want, then use fprintf to write data to your file. It should be noted that writing matrices to fprintf in MATLAB assume column major format. If you don't want your data written this way and want it done in row-major, you need to transpose your data before you write this to file. I'll provide both methods in the code depending on what you want.
After you're done, use fclose to close the file noting that you have finished writing to it. Therefore, you would do this:
for i=1:10
if i==1
data = DATA(1:data_size,:);
elseif i==10
data = DATA((i-1)*data_size+1:end,:);
else
data = DATA((i-1)*data_size+1: i*data_size,:);
end
filename = sprintf('A%d.txt', i); %// Generate file name
fid = fopen(filename, 'w'); % // Open file for writing
fwrite(fid, '%f ', data.'); %// Write to file - Transpose for row major!
%// fwrite(fid, '%f ', data); %// Write to file - Column major!
fclose(fid); %// Close file
end
Take note that I space separated the numbers so you can open up the file and see how these values are written accordingly. I've also used the default precision and formatting by just using %f. You can play around with this by looking at the fprintf documentation and customizing the precision and leading zero formatting to your desire.
Saving to a MAT file
This is actually a more simpler approach. You would still use sprintf to save your data, then use the save command to save your workspace variables to file. Therefore, your loop would be this:
for i=1:10
if i==1
data = DATA(1:data_size,:);
elseif i==10
data = DATA((i-1)*data_size+1:end,:);
else
data = DATA((i-1)*data_size+1: i*data_size,:);
end
filename = sprintf('A%d.mat', i); %// Generate file name
save(filename, 'data');
end
Take note that the variable you want to save must be a string. This is why you have to put single quotes around the data variable as this is the variable you are writing to file.
You can use
save(['data' num2str(i) '.mat'], 'data');
where [ ] is used to concatenate strings and num2str to convert an integer to a string.

Workaround for indexing limitations of matfile command

I have a very large number of large data files. I would like to be able to categorize the data in each file, and then save the filename to a cell array, such that at the end I'll have one cell array of filenames for each category of data, which I could then save to a mat file so that I can then come back later and run analysis on each category. It might look something like this:
MatObj = matfile('listOfCategorizedFilenames.mat');
MatObj.boring = {};
MatObj.interesting = {};
files = dir(directory);
K = numel(files);
for k=1:K
load(files(k).name,'data')
metric = testfunction(data)
if metric < threshold
MatObj.boring{end+1} = files(k).name;
else
MatObj.interesting{end+1} = files(k).name;
end
end
Because the list of files is very long, and testfunction can be slow, I'd like to set this to run unattended overnight or over the weekend (this is a stripped down version, metric might return one of several different categories), and in case of crashes or unforeseen errors, I'd like to save the data on the fly rather than populating a cell array in memory and dumping to disk at the end.
The problem is that using matfile will not allow cell indexing, so the save step throws an error. My question is, is there a workaround for this limitation? Is there better way to incrementally write the filenames to a list that would be easy to retrieve later?
I have no experience with matfile, so I cannot help you with that. As a quick and dirty solution, I would just write the filenames to two different text-files. Quick testing suggests that the data is flushed to disk straight away and that the text-files are OK even if you close matlab without doing a fclose (to simulate a crash). Untested code:
files = dir(directory);
K = numel(files);
boring = fopen('boring.txt', 'w');
interesting = fopen('interesting.txt', 'w');
for k=1:K
load(files(k).name,'data')
metric = testfunction(data)
if metric < threshold
fprintf(boring, '%s\n', files(k).name);
else
fprintf(interesting, '%s\n', files(k).name);
end
end
%be nice and close files
fclose(boring);
fclose(interesting);
Processing the boring/interesting text files afterwards should be trivial. If you would also write the directory listing to a separate file before starting the loop, it should be pretty easy (either by hand or automatically) to figure out where to continue in case of a crash.
Mat files are probably the most efficient way to store lists of files, but I guess whenever I've had this problem, I make a cell array and save it using xlswrite or fprintf into a document that I can just reload later.
You said the save step throws an error, so I assume this part is okay, right?
for k=1:K
load(files(k).name,'data')
metric = testfunction(data)
if metric < threshold
MatObj.boring{end+1} = files(k).name;
else
MatObj.interesting{end+1} = files(k).name;
end
end
Personally, I just then write,
xlswrite('name.xls', MatObj.interesting, 1, 'A1');
[~, ~, list] = xlsread('name.xls'); % later on
Or if you prefer text,
% I'm assuming here that it's just a single list of text strings.
fid = fopen('name.txt', 'w');
for row=1:nrows
fprintf(fid, '%s\n', MatObj.interesting{row});
end
fclose(fid);
And then later open with fscanf. I just use the xlswrite. I've never had a problem with it, and it's not noticeably slow enough to detract me from using it. I know my answer is just a workaround instead of a real solution, but I hope it helps.