Opening a txt file with chosen directory location

Hi.
I have a code that works to read values from a formatted txt file that I'm producing with another code. The code works as long as I have the code in the same directory and choose the file using 'uigetfile'. However as I want to eventually run the code on multiple files in a directory, when I set a variable to choose the directory, the code gives this error:
Error using fopen
First input must be a file name of type char, or a file identifier of type double.* *
My x_filename variable comes out as a cell array which I belive is the main issue but having tried to convert and change it, I get different types of errors.
I know this is probably a very simple fix but I need some assistance to find it.
My code is something like this:
% Directories for Files
x_Directory = uigetdir;
y_Directory = uigetdir;
x_Files = dir([x_Directory, '\*.txt']); % Determine number of files in chosen directory
x_Filename = {x_Files.name}'; % Sanity check
file_x = fopen(x_Filename); % open raw txt file
data = textscan(file_x,'%s %s %s %s %s %s %s %s %s %s %s %s %s');
fclose(file_x); % close raw file
celldisp(data);
% MAIN CODE HERE
I am testing the above with only one file before I implement the for loop to read multiple files, but the above error is stopping me.
Can anyone help?

 Accepted Answer

x_Filename
is a cell array, you need to pass the individual file into fopen:
file_x = fopen ( x_Filename{1} )
You should also look at
fullfile
filename = fullfile ( x_Directory, x_Filename{1} );
file_x = fopen ( filename )
for connecting paths and files

23 Comments

When I use this the file identifier is -1, and this error is produced on the next line with textscan:
data = textscan(file_x,'%s %s %s %s %s %s %s %s %s %s %s %s %s');
Error using textscan
Invalid file identifier. Use fopen to generate a valid file identifier.
Does the file exist? What is the output of x_Filename{1}
Adam
Adam on 27 Oct 2014
Edited: Adam on 27 Oct 2014
So far as I can see your x_Filename will not contain a fullpath, only a filename, so unless you are either in the directory of the file or it is on your path then it won't be found.
You will need to add the directory on to the front of your filenames resulting from the dir call.
The output of:
x_Filename{1}
gives me the correct filename. So the file exists.
Adam, do you mean that I need to combine the x_directory variable with the filename? If that was the case surely the above output would fail?
I'm sure this is something small that I have overlooked. :P
When you call fopen you need to have the full path, not just the filename, so yes. The only cases I am aware of where this isn't the case is when you are already in the directory containing the file or when it is on your Matlab path.
Ok, I've been trying to add that in like so:
file_x = fopen(x_Directory (x_Filename{1}));
and some other variations but all are erroring. The above gives an:
Index exceeds matrix dimensions
error.
I would do it on multiple lines until you get it right. Usually I just play around with syntax on the command line until it achieves what I want.
In this case you probably want either fullfile or to put your full file path together in [...] using filesep between the directory and file if neither of them incorporates it.
I see where you are going with this I think, although I can get the directory part to display fine but the filename part just won't add onto the end of it.
I have never used fullfile before.
you've all been busy while I was away.... I've added a line to show how to use fullfile.
I just arrived at that solution then read your answer Robert. Thanks to all for your help. :)
If I put this as it is into a for loop to cycle through all the files in the directory, I shouldn't need to change any of the main code should I? I
probably not no. Depends on what you are doing with the data from each file though...
Remember to change the x_Filename{1} to the index of your loop - e.g. x_Filename{ii}.
I plan to add certain values from each file into an array so I can plot them.
Can you clarify the use of 'ii' in your example here:
x_Filename{ii}
I am assuming this only carries out the rest of the code for that particular file in the directory at a time so that when it loops round to the next file it would only run the code on the next file in the sequence. Is this correct?
When you iterate over all your files you need to make sure you load the correct one:
% pre-allocate your array here (best practice and performance)
% e.g. array = zeros(nFiles,nValues);
nFiles = length ( x_Filename )
for ii = 1 : nFiles
filename = fullfile ( x_Directory, x_Filename{ii} );
% then continue with your code
% and add your certain values to your array
end
Hi Robert,
I've been trying this, but I seem to be having issues with my array variable.
if I have it before my for loop, I get an error saying it can't find the variable I'm reading which comes later in the for loop. Am I implementing your line correctly here:
array = zeros(nFiles,mValues);
for 'mValues' I would use the variable name for the value I want?
Basically, I need the values later in the for loop to be added to an array, but should my array variable come before the for loop or at the end of the for loop?
It was supposed to be nValues, not mValues (i.e. number of values you extract from the file).
Without knowing what and how much you are extracting from each loop its difficult to say whats going wrong.
Is the number of items you are extracting from each file different?
No it's only one value per file in this particular array. So it's the same number of values as files, so I have tried setting my array as follows:
array = zeros(nFiles,nFiles);
This gives me an array of 14 by 14 for the particular number of files present. I step through the code and it takes the value I require and puts it into the array. When I look at this variable, it is now a single value. I continue stepping through my for loop until it loops around but it just overwrites the 1st value, again only giving me 1 value.
I'm using this line after the value I need line to add to the array:
array = Variable_Value_Required;
I must be doing this wrong somehow. I need it to add to the array not overwrite it with the next value.
How about we quit guessing, and you just attach your m-file and data files so we can get this solved once and for all?
Every time you run array = X; it will completely redefine array to be the variable X. If you want to put the value (or values) of X into array, then you need to use some indexing . If X is a scalar, then
array(row,col) = X;
will place the values of X in array at the row and column position that you specify with the integers row and col. You can also use linear indexing and logical indexing:
Unfortunately I can't attach the files as there is a lot of commercial sensitivity in it, otherwise I would have.
This is what I have been trying now with indexing, but everytime I add in the line it complains that variable 'X' is undefined. The variable I need for each file is in the for loop, the array is being defined outside the for loop, but I can't seem to get the value into the array.
Ok, I have fixed it now! :D I have it adding to the array.
I solved this by having:
Array = zeros(noFiles,noFiles);
for ii = 1:noFiles
% Rest of code
Array(ii) = Required_values;
end
I knew it would be something simple, I simply forgot to add the for 'ii' definition to my array bit.
Thanks for your help and patience guys.
Just replace X with whatever scalar variable you want.
You create array as a square matrix of size N, where N is the number of files. Then you fill array with values using linear indexing array(ii) = value in a loop. This means most of array is not used... in fact, only the first column will be used.
Is this your desired result?
I agree with Stephen it looks like you should have:
Array = zeros(noFiles,1);
I realised that after I posted, fixed now.
Thanks for all your help guys!
:)

Sign in to comment.

More Answers (1)

Try this snippet to get the full filename of what file the user browsed to.
% Have user browse for a file, from a specified "starting folder."
% For convenience in browsing, set a starting folder from which to browse.
startingFolder = 'C:\Program Files\MATLAB'; % Whatever you want....could be pwd if you want.
if ~exist(startingFolder, 'dir')
% If that folder doesn't exist, just start in the current folder.
startingFolder = pwd;
end
% Get the name of the file that the user wants to use.
defaultFileName = fullfile(startingFolder, '*.*');
[baseFileName, folder] = uigetfile(defaultFileName, 'Select a file');
if baseFileName == 0
% User clicked the Cancel button.
return;
end
fullFileName = fullfile(folder, baseFileName)
fid = fopen(fullFileName, 'rt');
% etc. more code......

Asked:

on 27 Oct 2014

Commented:

on 30 Oct 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!