Allowing for code to work different with file names

I have a code that works fine but i have thus far only used it with a single test file. As a result of this i could run it while specifying the filename as well as the folder inside the code itself:
f1d = fopen(fullfile(sbd,'TEST_A.asc'),'rt');
Now that i need to apply it to multiple different files the code will not work. I have tried including a colon to read all files (as there is only one) but this doesn't work as the matlab error says there is no file name given. Can I not just specify the folder from which to select the file and the code read whatever files are in the folder?

 Respuesta aceptada

Aaron, if you just want the user to pick some file instead of using dir() or sprintf() to build/get the filename, do this:
% 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.....
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)

10 comentarios

I tried this out but i still get an invalid file identifier error:
sbd = uigetdir('C:\Users\c13459232\Documents\MATLAB'); % Generate command window to choose a folder
if ~isdir(sbd) % if the directory is not a valid path
errorMessage = sprintf('Error: the following file does not exist: \n%s', sbd); % print this error message
uiwait(warndlg(errorMessage)); % block the execution of program and wait to resume
return;
end
% Get the name of the file that the user wants to use.
defaultFileName = fullfile(sbd, '*.*');
[baseFileName, folder] = uigetfile(defaultFileName, 'Select a file');
if baseFileName == 0
% User clicked the Cancel button.
return;
end
outFolder = fullfile(sbd, 'output'); % build full file name from parts in folder 'Output'
mkdir(outFolder); % create folder
f2d = fopen(fullfile(outFolder,'temp_01.asc'),'wt'); %open the files that are being written
f1d = fopen((defaultFileName),'rt'); %open the original file to be read
k = 0;
while ~feof(f1d) %find the end of the file
str = fgetl(f1d); %Read the original file line by line removing deliimiters
[row,~,~,idx] = sscanf(str,'%d'); %ignore the first number on each line
if row==1
k = k+1;
fclose(f2d);
fnm = fullfile(outFolder,sprintf('temp_%02d.asc',k));
f2d = fopen(fnm,'wt');
end
fprintf(f2d,'%s\n',str(idx+1:end));
end
fclose(f1d); %close the original TEST_A file
fclose(f2d); %close the new file
message = sprintf( 'Task Complete' );
uiwait(msgbox(message));
Error using feof
Invalid file identifier. Use fopen to generate a valid file identifier.
I wrote another piece of code yesterday but i got an error that baffles me slightly as it doesn't seem like it should be an error:
sbd = uigetdir('C:\Users\c13459232\Documents\MATLAB'); % Generate command window to choose a folder
if ~isdir(sbd) % if the directory is not a valid path
errorMessage = sprintf('Error: the following file does not exist: \n%s', sbd); % print this error message
uiwait(warndlg(errorMessage)); % block the execution of program and wait to resume
return;
end
fullFileName = fullfile(folder, baseFileName)
filePattern = fullfile(sbd, '*.asc');
Files = dir(filePattern);
for length(Files)
f1d = fopen((filePattern),'rt');
end
outFolder = fullfile(sbd, 'output'); % build full file name from parts in folder 'Output'
mkdir(outFolder); % create folder
f2d = fopen(fullfile(outFolder,'temp_01.asc'),'wt');
k = 0;
while ~feof(f1d)
str = fgetl(f1d);
[row,~,~,idx] = sscanf(str,'%d');
if row==1
k = k+1;
fclose(f2d);
fnm = fullfile(outFolder,sprintf('temp_%02d.asc',k));
f2d = fopen(fnm,'wt');
end
fprintf(f2d,'%s\n',str(idx+1:end));
end
fclose(f1d); %close the original TEST_A file
fclose(f2d); %close the new file
message = sprintf( 'Task Complete' );
uiwait(msgbox(message));
The error occurs in this line: for length(Files) It states that the first parenthesis is invalid
In your line
f1d = fopen((defaultFileName),'rt'); %open the original file to be read
but defaultFileName = fullfile(sbd, '*.*'); which is unlikely to exist as a file name so you cannot fopen() it.
And what is this weird code supposed to do:
for length(Files)
f1d = fopen((filePattern),'rt');
end
There is no loop index on the for statement, plus you just overwrite f1d a bunch of times. What's your thinking there?
Aaron Smith
Aaron Smith el 26 de Mayo de 2017
Editada: Aaron Smith el 26 de Mayo de 2017
The loop is meant to read all files of .asc in the folder. There is only one file but I assumed it would work fine because it will just read all the files regardless of if there is one or ten or two hundred. Where do I overwrite f1d? I'm not sure where you're referring to
@Aaron: This is not meaningful:
Files = dir(filePattern);
for length(Files)
f1d = fopen((filePattern),'rt');
end
for length(Files) is no valid Matlab code. You cannot open a pattern. Overwriting f1d in each iteration (if the loop would run) is not useful.
Simply delete these lines.
Aaron Smith
Aaron Smith el 26 de Mayo de 2017
Editada: Aaron Smith el 26 de Mayo de 2017
I removed the code you referred to and the dir() on filepattern. I have an invalid file identifier error again which from my experience means i am getting closer >:D But in this case it is back where I started before editing the code originally
sbd = uigetdir('C:\Users\c13459232\Documents\MATLAB'); % Generate command window to choose a folder
if ~isdir(sbd) % if the directory is not a valid path
errorMessage = sprintf('Error: the following file does not exist: \n%s', sbd); % print this error message
uiwait(warndlg(errorMessage)); % block the execution of program and wait to resume
return;
end
filePattern = fullfile(sbd, '*.asc');
Files = filePattern;
outFolder = fullfile(sbd, 'output'); % build full file name from parts in folder 'Output'
mkdir(outFolder); % create folder
f2d = fopen(fullfile(outFolder,'temp_01.asc'),'wt');
f1d = fopen((Files), 'rt');
k = 0;
while ~feof(f1d)
str = fgetl(f1d);
[row,~,~,idx] = sscanf(str,'%d');
if row==1
k = k+1;
fclose(f2d);
fnm = fullfile(outFolder,sprintf('temp_%02d.asc',k));
f2d = fopen(fnm,'wt');
end
fprintf(f2d,'%s\n',str(idx+1:end));
end
fclose(f1d); %close the original TEST_A file
fclose(f2d); %close the new file
message = sprintf( 'Task Complete' );
uiwait(msgbox(message));
Warning: Directory already exists.
Error using feof
Invalid file identifier. Use fopen to generate a valid file identifier.
Jan
Jan el 26 de Mayo de 2017
Editada: Jan el 26 de Mayo de 2017
Nobody told you to omit the dir for the filePattern, but fopen(filePattern) does not work. Now you code contains again:
Files = filePattern;
f1d = fopen((Files), 'rt');
As said already: This must fail. FOPEN requires a file name, not a pattern. I assume you need:
FileList = dir(filePattern);
FileName = {FileList.name};
FileName(ismember(FileName, {'.', '..'})) = []; % To be safe
File = fullfile(sbd, FileName{1});
[f1d, msg] = fopen(File, 'rt');
if f1d == -1
error('Cannot open file: "%s": %s', File, msg);
end
Always check the output of fopen and display the corresponding message. You see how tedious it is to debug a failing file opening. Never never never let the output of fopen unchecked. There are too many corresponding threads in this forum, which show that being lazy and saving these code lines can cost you days for debugging.
You can avoid the warning:
if ~exist(outFolder, 'dir')
mkdir(outFolder);
end
And? What did I told you? Better use:
if ~exist(outFolder, 'dir')
[Status, Msg] = mkdir(outFolder);
if Status ~= 1
error('Cannot create folder: "%s": "%s"', outFolder, Msg);
end
end
Thanks Jan, I had tried the fopen(filePattern) with the dir still in but the problem was that i was still trying to open files using file pattern rather than listing the files and then opening the first in the list. This is what my code looks like now and it appears to be working:
sbd = uigetdir('C:\Users\c13459232\Documents\MATLAB'); % Generate command window to choose a folder
if ~isdir(sbd) % if the directory is not a valid path
errorMessage = sprintf('Error: the following file does not exist: \n%s', sbd); % print this error message
uiwait(warndlg(errorMessage)); % block the execution of program and wait to resume
return;
end
filePattern = fullfile(sbd, '*.asc');
FileList = dir(filePattern);
FileName = {FileList.name};
FileName(ismember(FileName, {'.', '..'})) = []; % To be safe
File = fullfile(sbd, FileName{1});
[f1d, msg] = fopen(File, 'rt');
if f1d == -1
error('Cannot open file: "%s": %s', File, msg);
end
outFolder = fullfile(sbd, 'output'); % build full file name from parts in folder 'Output'
if ~exist(outFolder, 'dir')
[Status, Msg] = mkdir(outFolder);
if Status ~= 1
error('Cannot create folder: "%s": "%s"', outFolder, Msg);
end
end
f2d = fopen(fullfile(outFolder,'temp_01.asc'),'wt');
k = 0;
while ~feof(f1d)
str = fgetl(f1d);
[row,~,~,idx] = sscanf(str,'%d');
if row==1
k = k+1;
fclose(f2d);
fnm = fullfile(outFolder,sprintf('temp_%02d.asc',k));
f2d = fopen(fnm,'wt');
end
fprintf(f2d,'%s\n',str(idx+1:end));
end
fclose(f1d); %close the original TEST_A file
fclose(f2d); %close the new file
message = sprintf( 'Task Complete' );
uiwait(msgbox(message));
guidata(hObject, handles);
I have just a few more questions about why you included some stuff: The %to be safe line is just to insure that the filename is there, right?
What is the purpose of msg and the [status,msg] line in general?
Thanks again. I had been wallowing in fixing and crating errors for some time.
This line removed the entries '.' and '..' from the output of the dir() command. In your case they will not appear, because aou are searching for '*.asc'. But if you re-use the code snippets in other programs, this might be useful:
FileList = dir(fullfile(cd, '*.'));
fprintf('%s\n', FileList.name)
Then you see the '.' and '..', which are current folder and parent folder.
There is no general meaning of "status, msg". For the fopen and mkdir command, the first output is a flag to reply the success status and msg contains an error message in case of problem, such that the user do not have to guess, what the problem is. See:
doc fopen
doc mkdir
Thanks a million :)

Iniciar sesión para comentar.

Más respuestas (1)

Stephen23
Stephen23 el 25 de Mayo de 2017
Editada: Stephen23 el 25 de Mayo de 2017
How to read multiple files is explained extensively in the documentation, on this forum, and in the wiki:
etc
The first thing to decide is if you want to generate the file names, or if you want to read the names of existing files:
  • generate names: use sprintf and fullfile.
  • read names: use dir and fullfile.
You can find some examples with my FEX submission natsortfiles:

2 comentarios

Aaron Smith
Aaron Smith el 25 de Mayo de 2017
Editada: Aaron Smith el 25 de Mayo de 2017
Thanks Stephen. I am only processing a single file but i could use the code for importing multiple but is there no simpler way to simply select the folder and then matlab processes the file that is inside?. I am trying to read the file that exists inside the folder, not generate a file name
Stephen23
Stephen23 el 14 de Jun. de 2017
Editada: Stephen23 el 5 de Jul. de 2017
@Aaron Smith: and if you read my answer you will see that I covered that too:
"read names: use dir and fullfile."

Iniciar sesión para comentar.

Categorías

Productos

Etiquetas

Preguntada:

el 25 de Mayo de 2017

Editada:

el 5 de Jul. de 2017

Community Treasure Hunt

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

Start Hunting!

Translated by