Matlab: Printing a data on a specific line - matlab

I have below function:
function [] = Write(iteration)
status=close('all');
nomrep=num2str(iteration);
fid=fopen('ID.dat','a');
frewind(fid);
for l=1:iteration
line=fgetl(fid);
end
fprintf(fid,[nomrep,' \n']);
status=fclose(fid);
end
I expect that Write(15) creates ID.dat and prints 2 and 15 in consecutive lines at begining of line 15th.
But is prints those values always on the beginning of the file.
Even I tried fgetl(fid) alone, and also replaced for loop with while loop still did not work.
Is it due to the fact that I should fill in the lines before that with some dummy space? along side this, I executed
for i=1:5
Write(i);
end
Which should print 1 to 5 in each line but even this does not work.

This line is the problem:
fid=fopen('ID.dat','w');
Everytime you open the file, you are overwriting the previous contents (that is what the 'w' argument does). Change 'w' to 'a' (for append), and your file will retain the contents from one write to the next.

Related

MATLAB fwrite\fread issue: two variables are being concatenated

I am reading in a binary EDF file and I have to split it into multiple smaller EDF files at specific points and then adjust some of the values inside. Overall it works quite well but when I read in the file it combines 2 character arrays with each other. Obviously everything afterwords gets corrupted as well. I am at a dead end and have no idea what I'm doing wrong.
The part of the code (writing) that has to contain the problem:
byt=fread(fid,8,'*char');
fwrite(tfid,byt,'*char');
fwrite(tfid,fread(fid,44));
%new number of records
s = records;
fwrite(tfid,s,'*char');
fseek(fid,8,0);
%test
fwrite(tfid,fread(fid,8,'*char'),'*char');
When I use the reader it combines the records (fwrite(tfid,s,'*char'))
with the value of the next variable. All variables before this are displayed correctly. The relevant code of the reader:
hdr.bytes = str2double(fread(fid,8,'*char')');
reserved = fread(fid,44);%#ok
hdr.records = str2double(fread(fid,8,'*char')');
if hdr.records == -1
beep
disp('There appears to be a problem with this file; it returns an out-of-spec value of -1 for ''numberOfRecords.''')
disp('Attempting to read the file with ''edfReadUntilDone'' instead....');
[hdr, record] = edfreadUntilDone(fname, varargin);
return
end
hdr.duration = str2double(fread(fid,8,'*char')');
The likely problem is that your character array s does not have 8 characters in it, but you expect there to be 8 when you read it from the file. Whatever the number of characters in the array is, that's how many values fwrite will write out to the file. Anything less than 8 characters and you'll end up reading part of the next piece of data when you read from the file.
One fix would be to pad s with blanks before writing it:
s = [blanks(8-numel(records)) records];
In addition, the syntax '*char' is only valid when using fread: the * indicates that the output class should be 'char' as well. It's unnecessary when using fwrite.

reading data from csv files with `textscan` in MATLAB

[Edited:] I have a file data2007a.csv and I copied and pasted (using TextEdit in MacBook) the first consecutive few lines to a new file datatest1.csv for testing:
Nomenclature,ReporterISO3,ProductCode,ReporterName,PartnerISO3,PartnerName,Year,TradeFlowName,TradeFlowCode,TradeValue in 1000 USD
S3,ABW,0,Aruba,ANT,Netherlands Antilles,2007,Export,6,448.91
S3,ABW,0,Aruba,ATG,Antigua and Barbuda,2007,Export,6,0.312
S3,ABW,0,Aruba,CHN,China,2007,Export,6,24.715
S3,ABW,0,Aruba,COL,Colombia,2007,Export,6,95.885
S3,ABW,0,Aruba,DOM,Dominican Republic,2007,Export,6,11.432
I wanted to use textscan to read it into MATLAB with only columns 2,3,5 (starting from the second row) and I wrote the following code
clc,clear all
fid = fopen('datatest1.csv');
data = textscan(fid,'%*s %s %d %*s %s %*[^\n]',...
'Delimiter',',',...
'HeaderLines',1);
fclose(fid);
But I ended up with only the second row of columns 2,3 and 5:
I then keep the first row in data2007a.csv and selected several others to saved as datatest2.csv:
Nomenclature,ReporterISO3,ProductCode,ReporterName,PartnerISO3,PartnerName,Year,TradeFlowName,TradeFlowCode,TradeValue in 1000 USD
S3,ABW,1,Aruba,USA,United States,2007,Export,6,1.392
S3,ABW,1,Aruba,VEN,Venezuela,2007,Export,6,5633.157
S3,ABW,2,Aruba,ANT,Netherlands Antilles,2007,Export,6,310.734
S3,ABW,2,Aruba,USA,United States,2007,Export,6,342.42
S3,ABW,2,Aruba,VEN,Venezuela,2007,Export,6,63.722
S3,AGO,0,Angola,DEU,Germany,2007,Export,6,105.334
S3,AGO,0,Angola,ESP,Spain,2007,Export,6,8533.125
And I wrote:
clc,clear all
fid = fopen('datatest2.csv');
data = textscan(fid,'%*s %s %d %*s %s %*[^\n]',...
'Delimiter',',',...
'HeaderLines',1);
fclose(fid);
data{1}
It gives exactly what I wanted:
When I use the same code for my original data file data2007a.csv, it goes as in the first case.
What is going wrong and how can I fix it?
[Added:] If one replicates my experiments1, one can find that both cases work and the problem does not exist! I really don't know what is going on.
1 For "replicate" I mean copy-and-paste the data given above and save it as two new files, say, datatest4a.csv and datatest4b.csv. I used visdiff('datatest1.csv', 'datatest4a.csv') to compare two files and it returned:
Given how you fixed it, I think this is an end-of-line character issue. This sometimes comes up when moving text files between Windows and Unix based systems, as they use different conventions.
When you add %*[^\n] to the end of a textscan format, as you have here. it means to skip everything to the end of line. But if it expects a specific end of line character, and can't find one, it will skip everything to the end of the file. This would explain why you get one row correctly read and then nothing else.
If you don't specify what the end of line character is, Matlab appears to default to... something... in this not very clear specification in the help:
The default end-of-line sequence is \n, \r, or \r\n, depending on the contents of your file.
One way to try and cure this without having to create a new file would be to add this 'EndOfLine', '\r\n' to your textscan call:
If you specify '\r\n', then textscan treats any of \r, \n, and the
combination of the two (\r\n) as end-of-line characters.
This will hopefully handle most standard(ish) EOL conventions. It is likely that copy-pasting and saving with a different bit of software than was originally used to create the file changed the end of line characters such that Matlab was able to recognise them.

Hackerrank stdin only gives me the first line from multiple lines

I am trying to solve this challenge on HackerRank:
https://www.hackerrank.com/challenges/30-operators?h_r=next-challenge&h_v=zen
the way I tried to read the stdin is this:
let input = readline()!
However, the input consists of three lines, e.g.
12.00
20
8
How do I get all three lines, ideally in some separated way so that I can cast them to their respective types?
If you need the 3 lines, call it 3 times :)
The documentation is explicit
Returns Characters read from standard input through the end of the
current line or until EOF is reached, or nil if EOF has already been
reached.
But it seems they forgot to indicate that reading a line will change the current line
Generally what I would do is use input() to assign the stdin values to a variable and then pass the variables for functions.
example:
a = input() #gives the first line
b = input() #gives the second line
c = input() #gives the third line
if you would like to read all the lines then use a for loop:
example:
import sys
for line in sys.stdin:
print(line)

Preventing fgets from deleting first line

I'm opening a file, reading the first line using fgets, using regexp to test what format the file is in, and if the file is in the desired format, I use fscanf to read the entire file.
fid = fopen('E:\Tick Data\Data Output\Differentformatfiles\AUU01.csv','rt');
% reads first line of file but seems to be deleting the line:
str = fgets(fid);
% test for pattern mm/dd/yyyy
if(regexp(str, '\d\d/\d\d/\d\d\d\d'))
c = fscanf(fid, '%d/%d/%d,%d:%d:%d,%f,%d,%*c');
Unfortunately, if the contents of my file look like:
20010701,08:29:30.000,95.00,29,E
20010702,08:29:30.000,95.00,68,E
20010703,08:29:30.000,95.00,5,E
20010704,08:29:30.000,95.00,40,E
20010705,08:29:30.000,95.00,72,E
str will equal 20010701,08:29:30.000,95.00,29,E, but c will only equal the last 4 lines:
20010702,08:29:30.000,95.00,68,E
20010703,08:29:30.000,95.00,5,E
20010704,08:29:30.000,95.00,40,E
20010705,08:29:30.000,95.00,72,E
Is there a way to prevent fgets from deleting the first line? Or another function I should use?
It isn't actually erasing it, it's just moving on to the next line. You could either use a combination of fpos and fseek to go back to the beginning of that line, but since you've already got the line stored in str, I would add two lines:
if(regexp(str, '\d\d/\d\d/\d\d\d\d'))
c1 = sscanf(str, '%d/%d/%d,%d:%d:%d,%f,%d,%*c'); % scan the string
c2 = fscanf(fid, '%d/%d/%d,%d:%d:%d,%f,%d,%*c');
c = {c1;c2}; % concatenate the cells
It certainly isn't the most elegant solution, but it's robust and easy to shoehorn into your existing code.

Index exceed matrix dimension error when reading a csv file using matlab?

I have a few cvs files from which I want to read specific lines and so to collect specific information from them.
While I found that I am able to read these files all good if removing manually a line, I would like to be able to skip this line using some code to avoid going through each of these files and manually removing this line.
Example:
My file looks like this
blabla
blabla
blabla
S>
blabla
blabla
nquan = 12
blabla
I am reading this file using the following code in matlab:
din = 'C:/example/';
CNVfiles = dir ([din '*.cnv']);
fid = fopen([din CNVfiles], 'r');
I want to be able to get the number '12' from the line '# nquan = 12' (which is the number of
column (Ncol) that I will need later),
p = ' ';
while ~isequal(p(1:7),'* nquan')
p = fgets(fid);
end
Ncol = str2double(p(11:end));
fclose(fid);
However, it gets me an error stating 'Index esceed matrix dimension' at 'end' ....when I look at what 'p' is, it tells me '* S>' and hence I am guessing that I have an issue when reading that '* S>' line in the files..
When I manually remove that line '* S>', it works all good and I get my Ncol = 12. However, I would like to avoid to do this manually since I have a bunch of cnv files like that.
I was thinking of skipping that line, but do not know how to do that...any ideas what is wrong here? and what can I do to make it works?
Many thanks,
Sophie
You are getting this error because when your loop reaches the line in your file which contains "* S>", the value of p is equal to '* S>'. As you can see, p is an array of length 4. When you now try p(1:7), Matlab complains since you are accessing elements that aren't present.