views:

406

answers:

2

I have asked a related question in the past and I know how to read the file thanks to the help of the experts here. Now I have a new problem. I first read the data from the file like so:

fid = fopen('D:\file.txt', 'rt');
a = textscan(fid, '%s %f %f %f %f %f %f', ...
             'Delimiter',',', 'CollectOutput',1, 'HeaderLines',1);
fclose(fid);

I then process the file and change a few values of the column. Now I want to write a new file newfile.txt in the exact same format as my file.txt with the new values. How do I do that?

If I do the following:

M = [datenum(a{1}) a{2}];
dlmwrite('newfile1.txt', M);

it gives me a new file without my first row of headers and without column 1 and column2 in the format I want.

My file format is given below:

date        time,   M01, M02, M03, M04, M05, M06
8/15/2009, 0:00:00, 5.8, 7.8, 7.8, 7.3, 0, 7.9
8/15/2009, 0:10:00, 7.1, 8.1, 8.1, 7.7, 0, 8.1
8/15/2009, 0:20:00, 6.8, 7.4, 7.6, 7.1, 0, 7.3
8/15/2009, 0:30:00, 5.6, 6.8, 7.1, 6.6, 0, 6.8
8/15/2009, 0:40:00, 3.9, 6.2, 6.4, 6.2, 0, 6.4
8/15/2009, 0:50:00, 4.6, 5.5, 6.1, 5.8, 0, 5.6
8/15/2009, 1:40:00, 7, 7, 7.2, 6.9, 0, 6.3

i am able to make a new file.txt in format

My file format is given below:

                5.8, 7.8, 7.8, 7.3, 0, 7.9
                7.1, 8.1, 8.1, 7.7, 0, 8.1
                6.8, 7.4, 7.6, 7.1, 0, 7.3
                5.6, 6.8, 7.1, 6.6, 0, 6.8
                3.9, 6.2, 6.4, 6.2, 0, 6.4
                4.6, 5.5, 6.1, 5.8, 0, 5.6
                7, 7, 7.2, 6.9, 0, 6.3

Can some one help me 2 copy the headers and the first 2 columns into this new file?

A: 

Hi

dlmwrite writes a variable (for example, your array of M) to a file in ASCII text, as you know. Check the documentation for the function to discover how to set the separator character (to get , between values in each row) and how to append to an existing file.

To write the header line, I suggest you set up an array of strings, populate it and use dlmwrite to write it to your output file.

Now, if you want to write the rest of the file (the M array plus 2 leading columns of dates/times) you will need to create a temporary array with size the same as M plus 2 extra columns. Since your data values are floating-point numbers and your dates and times are structured data of some sort (strings perhaps) I think Mtemp will have to be an array of strings. Once you have created it you can append it to your output file with a single dlmwrite statement.

Note that num2str operates as you might hope on vectors but I'm not sure it can be coerced into putting , between values. It can, however, write numbers in a format you specify.

If this doesn't give you the output you want, or your array is too big to copy and expand or you have some other reason for not liking the proposed solution, then I fear that you will have to write a loop to write the output a line at a time, and use low-level file writing functions.

Regards

Mark

High Performance Mark
+1  A: 

Note: I've updated the answer to work with the most current file format specified in the question (i.e. a comma between the date and time values). I've also written the code below to handle very large files where the number of columns are known but the number of rows is variable.

First, you'll have to read your file using the following updated code (which saves the top line using the function FGETS):

fid = fopen('D:\file.txt','rt');  %# Open the file
topLine = fgets(fid);             %# Read the top line and store it in a string
data = textscan(fid,'%f','Delimiter',',/:');  %# Read the data
fclose(fid);                      %# Close the file

Next, you have to reshape data using the known number of columns of data (not counting the date and time columns):

N = 74;  %# Number of columns of data after the date and time
data = reshape(data{1},N+6,[])';

Now data is a matrix where the first six columns contain date and time information (month, day, year, hours, minutes, and seconds) and all the other data is in the remaining N columns. If you need to do anything with the date and time values, you can look at the following functions to figure out how to convert them to different formats: DATENUM, DATESTR, and DATEVEC.

After you've modified the values in data you can resave it using a for loop and the FPRINTF function:

fid = fopen('newfile1.txt','wt');  %# Open the file
fprintf(fid,'%s',topLine);         %# Print the top line
for i = 1:size(data,1)             %# Loop over the rows of data
  fprintf(fid,'%d/%d/%d, %d:%d:%d',data(i,1:6));  %# Print the date
  fprintf(fid,', %.1f',data(i,7:end));            %# Print the data
  fprintf(fid,'\n');                              %# Print a newline
end
fclose(fid);                       %# Close the file

I ran the above code with an 86400-by-80 matrix for data and it took around 30 seconds to write the data to a file.

gnovice
@ Gnoice: Thanks but anyway to make it faster? its taking me 5 min to run each file and if i skipped 2 columns and headers with my comments ( i wrote above ) it only takes 10s. I have 50 files to run and process!!
AP
@AP: I added a new version of my answer that I believe should be faster.
gnovice
@Gnoice : I changed back one edit you did erasing the , between date and time as my file has them separted by comma. so i have date in column 1 and time in column 2.
AP
@gnoice : Two issues 1) Its running out of memory evaluating 'char (10.*ones(size(M,1),1))' 2) davevec is failing and reading too many date fields . error looks like'Too many date fields in 10/5/2009 00:00:00 1 1 8 5 ...'
AP
@AP: 1) If it's running out of memory, it means your matrix `M` must be so large that MATLAB doesn't have enough space left to create `data`. You can try overwriting `M` by replacing `data = [...` with `M = [...`. 2) You should be using the function DATESTR (as in my code above), not DATEVEC.
gnovice
@ gnoice : yes i know if its running out of memory it means my file is huge ( my new set of data is 86400 74 ) but i ran on much shorter data and it still gives me ' running out of memory doing the ' char ' command, without it, its fine. 2) I am using your code of datestr... i was refering to error it gave me. ( as i belive datestr func calls datevec from matlab source )
AP
@AP: I've updated my answer. Because the data you are working with is taking up so much memory I had to switch back to looping over each row to write the data to a file. However, this should run faster than a previous for-loop solution I gave you since I am handling the date in a different way.
gnovice
@ You really are amazing in matlab.. I really need a faster computer for work. It still takes me long when i deal with huge files.Thanks a lot
AP