Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 219
  • Last Modified:

Opening files without specifing file names

I have a bunch of files in a directory that I want to read in. I don't want to have to enter the name of each file, I would rather have it read in the first file, do the work on it, then read in the next file, do the work on this, and so on...
0
llagreca
Asked:
llagreca
  • 6
  • 6
  • 4
  • +3
1 Solution
 
dircCommented:
You can use the opendir(), readdir(), and closedir() functions to determine which files are in the directory.
0
 
cookreCommented:
Presuming you want all files in the directory, use some flavor of find_first and find_next (depends on OS and runtime environment).

For example (DOS):


if (0==_dos_findfirst(TmpStr,_A_SUBDIR|_A_RDONLY|_A_HIDDEN|_A_SYSTEM,&FindBlock))
   {
   ProcessEntry(DirToScan,FindBlock);
   while (0==_dos_findnext(&FindBlock)) ProcessEntry(DirToScan,FindBlock);
   }
(Hope the formatting is legible)


One does something similar for Windows.
0
 
cookreCommented:
In MSVC 6, one uses _findfirst and _findnext.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
llagrecaAuthor Commented:
How can I use that to make my code go through each file separately and have each file individually accessed to do what is needed?
0
 
cookreCommented:
The findfirst initializes the processing of a directory and returns the first entry.  Subsequent calls to findnext return the next entry in the directory.  The entry name and various attributes are returned in the passed structure (FindBlock in the example).

In the example, I also pass the directory path to subroutine ProcessEntry so I can recreate the full path to the entry described in FindBlock.

Here's a bigger chunk of code:


void ProcessEntry(DirToScan,FindBlock)
char           DirToScan[];
struct _find_t FindBlock;

{
char          SubDirPath[_MAX_PATH+9];
extern void   ScanDir(char *);
char          CurFileName[_MAX_PATH+13];
unsigned long TmpULong;
unsigned int  TmpSecs;
unsigned int  TmpMins;

//
// Recurse on another directory
if (FindBlock.attrib & _A_SUBDIR)
   {
   //
   // Skip . and ..
   if ((0==strcmp(".",FindBlock.name)) || (0==strcmp("..",FindBlock.name))) return;
   //
   // Add directory to path
   strcpy(SubDirPath,DirToScan);
   strcat(SubDirPath,"\\");
   strcat(SubDirPath,FindBlock.name);
   ScanDir(SubDirPath);
   return;
   }
//
// Its a file
strcpy(CurFileName,DirToScan);
strcat(CurFileName,"\\");
strcat(CurFileName,FindBlock.name);



Here's where you fiddle with the file



return;
}





void ScanDir(DirToScan)
char *DirToScan;
{
char TmpStr[_MAX_PATH+5];
struct _find_t FindBlock;

//
// Add wild cards to path
if (DirToScan[strlen(DirToScan)-1]=='\\') DirToScan[strlen(DirToScan)-1]='\0';
strcpy(TmpStr,DirToScan);
strcat(TmpStr,"\\*.*");

//
// Scan this directory
if (0==_dos_findfirst(TmpStr
                     ,_A_SUBDIR|_A_RDONLY|_A_HIDDEN|_A_SYSTEM
                     ,&FindBlock))
   {
   ProcessEntry(DirToScan,FindBlock);
   while (0==_dos_findnext(&FindBlock)) ProcessEntry(DirToScan,FindBlock);
   }

return;
}


0
 
cookreCommented:
Yeah, the formatting abilities aren't quite what we might like, but I think this larger snippet, and your library's documentation, should give you what you need.
0
 
stochasticCommented:
llagreca,

cookre's answer is detailed and appropriate. But if you want to do this just once, I have a quick-and-dirty suggestion that should work. I am assuming all your files are in one directory.

1.
In a DOS box, give the command
   DIR /B > filelist.txt
This will create a file called filelist.txt with one filename per line. This may also contain "filelist.txt" itself, which you may have to remove with a text editor (notepad should do fine).

2. In your program, open this file filelist.txt. In a loop, read one line at a time (I would suggest fgets() call), so you will get one filename at a time into a string.

3. While you are still inside the loop, do whatever you want to do on this filename. (e.g. you can open that file, process it, close it).

Hope this is clear enough.

best of luck

- stochastic

0
 
makerpCommented:
/*
this function recursivly scan directries. you will need to change it so it gets the first file only.

i donr this in VC++ on NT 4.0
*/

#include <stdio.h>
#include <io.h>


int scan_path(char *path)
{
     char spath[256];
     struct _finddata_t ff;
     long fhandle;

     sprintf(spath,"%s\\*",path);
     fhandle=_findfirst(spath,&ff);
     if(fhandle==-1L)
     {
          printf("Bad path\n");
          return -1;
     }
     else
     {
          /* loop through each etry in the dir */
          while(!_findnext(fhandle,&ff))
  {
               /* if its a sub-dir then recursivly call our self*/
               if(ff.attrib&_A_SUBDIR)
               {
                     if(strcmp(ff.name,".."))
                     {
                            sprintf(spath,"%s\\%s",path,ff.name);
                            scan_path(path2);
                     }
               }
               else
               {
                     /* if its a file then */
                     if(ff.attrib^_A_SYSTEM)
                     {
                            printf("Found File %s\n",ff.name);
                     }
               }
          }
     }
     return 1;
}


0
 
makerpCommented:
if you just remove the subdir bit so you dont recursively call your self and put a function in the file bit passing your path/filename and you can process the file.
0
 
llagrecaAuthor Commented:
I would like to do what stochastic said to do, using filelist.txt in DOS, but I am running on a SUN box. What would the command be for the SUN to do the filelist.txt in DOS?
Thanks for your helf
0
 
P_MaheshCommented:
I agree with what 'stochastic' had suggested

In SUN you do :

ls > filelist.txt

Then the file 'filelist.txt' will have all the names of the files.
You give this command from the directory where the files are. and provided
the directory has only the files required for processing.

hope this helps.
0
 
llagrecaAuthor Commented:
Thank you very much the ls> filelist.txt worked.
One more question, how would i write the loop to read the next filename. I am just a beginner at C.
Thanks again.
0
 
stochasticCommented:
llagreca,

Sorry for assuming you were on a DOS / Windows machine. And sorry for not responding to your question quickly enough, but P_Mahesh gave you the precise answer. That's the beauty of EE! So many experts willing to help out! Thanks Mahesh; hope to see you around EE oftener.

- stochastic

0
 
llagrecaAuthor Commented:
I wrote the code to open filelist.txt and I can't open any of the files in the list. I think that it is reading past the filename into the blanks in the line. How can I correct this?
0
 
P_MaheshCommented:
Can you give the piece of code you wrote . It would be of more help.
Does the file "filelist.txt" contain all the names of the files ?
The directory from where you are executing should be the same, in which
the files are present.

 Meanwhile you can try the following logic ...

/*** I strongly advice you to go thru the syntax of each command. You shouldn't face any problems regarding the logic . I hope this is what you wanted and it works ***/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

main( )
{

    FILE *fpt;
    FILE *fpt1;

    /*** Assuming here that no filename is more than 30 chars ***/
    char filename[30];  
    int number=30;       /***   This number should be one more than the                                                                             number ***/
                       /***    of characters in the string you are reading ***/
    char filelist[10];
   
    strcpy( filelist, "filelist" );
     
    /*** Open the file 'filelist' for reading only ***/
    fpt = fopen( filelist, "r");

    /*** You can also use this loop to read the filenames
      while( feof( fpt )==NULL )
      {
          fgets( filename, number, fpt  );
          .
          .
     }
     fclose( fpt );  ***/
   
    /*** fgets returns null when end of file is reached ***/
    while( fgets( filename, number, fpt ) != NULL )
    {
       /*** For each run, the variable 'filename' will contain the
       name of file you want to process ***/
       
      /*** Open the file in read and updating . check that
            the mode "r+" is correct  ***/
       fpt1 = fopen( filename, "r+" );

       /*** Now the filename is open for processing ***/

       ...
       ...
       ...

      /*** After completion you need to close the file 'filename' ***/
      fclose( fpt1 );
   }

   /*** After all the names have been read from file "filelist" you have to           close  it.  ***/
   fclose( fpt );

}


 thanks,
mahesh.
0
 
stochasticCommented:
llagreca and mahesh,

my comments below relate to the code suggested by mahesh.

let me add a couple of comments:
a. strcpy( filelist, "filelist" );
   should probably have been
   strcpy( filelist, "filelist.txt" );

b. the fgets() function reads the whole line INCLUDING the end-of-line (newline) character, and it then adds a null character at the end. You will have to strip that newline character before you use the string as a valid filename. So after the statement
fgets(filename, number, fpt);
you should probably do
filename[strlen(filename)-1] = '\0';
to overwrite the newline with a null.
[to get strlen to work okay, you may need #include <string.h> or something. Mahesh has already put that]

c. Please keep the value of 'number' sufficiently large. It won't matter if it is much larger than actual filename length; but it will matter if it is smaller - you will get wrong results.
fgets() terminates when it finds a newline, so even if you have a large number, it will pick up only upto end of line.

For the newline reason above, your number should be at least 2 greater than the longest filename you will have. For example, if you have a filename called myfile.dat, the actual buffer size should be at least 10 for the filename + 1 for the newline + 1 for the string-terminating null = 12.

So just make 'number' big enough to avoid any possible problem. You can make it 128 or something.

d. llagreca, maybe you could insert a
printf("=%s=\n", filename); just after the fgets and the above fix, just to see what filename is actually being read. The '=' characters at both ends are just meant to be end-indicators in the screen output, so that you would know if any nonprintable character comes after the actual filename end. This will help you debug it.

Hope this works :-)

- stochastic          
0
 
llagrecaAuthor Commented:
Thank you so much for your help!!! Here is my code as it is right now. Remeber, I am not a good C programmer, just a beginner. I haven't looked at the suggestions made above yet, but I am going to do that right now. Again, thanks so mcuh!!


#include <stdio.h>                                                              
#define MAXLEN 25                                                              
                                                                               
                                                                               
/*  opens filelist.txt which is a list of the file names in a specific          
    dir and prints out each one  */                                            
                                                                               
                                                                               
main()                                                                          
{ FILE *fp, *fp1; char fileName[10];                                            
  char buffer[25]; int i; char buffer1[25]; int loc;                            
  printf("Enter file name: ");                                                  
  gets(fileName);                                                              
  if ((fp = fopen("filelist.txt", "r")) == NULL) printf("\n no open");          
  while(1)                                                                      
  {                                                                            
    fgets(buffer, MAXLEN, fp);                                                  
    printf("\nfileName  = %s", buffer1);                                        
    strcpy(buffer, buffer1);                                                    
                                                                               
     for (i = 0; i <MAXLEN; i++)                                                
    {                                                                          
       printf("\nbuffer[i] = %c", buffer[i]);                                  
       if (buffer[i] = ' ')                                                    
       { loc = i;                                                              
         buffer[i] = '\0';                                                      
       }                                                                        
       if (buffer[i] >= loc) buffer[i] = '\0';                                  
    }                                                                          
    if ((fp = fopen(buffer, "rb")) != NULL)                                    
    {                                                                          
       printf("\n opened file!!!");                                            
       fclose(fp1);                                                            
    }                                                                          
    else printf("\nDID NOT OPEN!!"); exit(0);                                  
   if (buffer[0] = '\0' ) break;                                                
                                                                               
    puts(buffer);                                                              
                                                                               
   }                                                                            
                                                                               
}  
0
 
stochasticCommented:
llagreca,

Just edited your code. I have not tested it myself, but I think it should work. Please tell me if there is still a problem.

(Sorry if the formatting is messed up. I just copy-pasted; I don't know why formatting gets disturbed)

- stochastic

#include <stdio.h>
#include <string.h>

#define MAXLEN 128
/*  opens filelist.txt which is a list of the file names in a specific          
    dir and prints out each one  */                                              
                                                                                 
                                                                                 
main()                                                                          
{ FILE *fp, *fp1; char buffer[128];                                            

  if ((fp = fopen("filelist.txt", "r")) == NULL) printf("\n no open");          
  while(1)                                                                      
  {                                                                              
    fgets(buffer, MAXLEN, fp);                                                  
    if (buffer == NULL) break;  /* exit when no more lines to read */
    buffer[strlen(buffer)-1] = '\0';
    printf("\nfileName is =%s=", buffer1);                                        
                                                                                 
    if ((fp1 = fopen(buffer, "rb")) != NULL)                                      
    {                                                                            
       printf("\n opened file!!!");                                              
       fclose(fp1);                                                              
    }                                                                            
    else printf("\nDID NOT OPEN!!"); exit(0);                                    
    puts(buffer);
                                                                                 
   }                                                                            
                                                                                 
}  
0
 
stochasticCommented:
Corrected the code and tested it!

- stochastic

#include <stdio.h>
#include <string.h>
#include <stdlib.h> /* you may not need this line on a Sun machine */

#define MAXLEN 128
/*  opens filelist.txt which is a list of the file names in a specific  
    dir and prints out each one  */  
 
 
main()
{ FILE *fp, *fp1; char buffer[128];

  if ((fp = fopen("filelist.txt", "r")) == NULL)
  {
 printf("\n no open");
 exit(0);
  }
  while(1)  
  {    
    if (fgets(buffer, MAXLEN, fp) == NULL) break;
  /* exit when no more lines to read */
    buffer[strlen(buffer)-1] = '\0';
    printf("\nfileName is =%s=", buffer);  
 
    if ((fp1 = fopen(buffer, "rb")) != NULL)    
    {  
       printf("\n opened file!!!");  
       fclose(fp1);  
    }  
    else printf("\nDID NOT OPEN!!"); /* exit(0); you can enable this later */
    puts(buffer);
 
   }  
 
}  
0
 
llagrecaAuthor Commented:
thank you, it works great. now though, i have problems reading in the data in the file. If i call the file individually, it works fine, but if I use this method, it doesn't work correctly.
Thanks
0
 
stochasticCommented:
I think in your earlier code, there was a possible confusion in the file pointers fp and fp1. Maybe that's the reason?

I feel confident you will now be able to figure out things.

best of luck

 -stochastic
0
 
P_MaheshCommented:
The problem in llagreca's previous code was that, even though he had
defined 2 file pointers 'fp' and 'fp1' but he was opened both the files
usinf 'fp' ..

 if ((fp = fopen(buffer, "rb")) != NULL)                                      
                       
He should have used 'fp1' instead of 'fp' in the above line.

- mahesh
         
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 6
  • 4
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now