简体   繁体   English

C:打开的文件太多

[英]C: Too many files open

This code opens a directory, and for every file in the directory it loops through every line of data inside the file, and then parses it to do some calculations and outputs the resulting data into a new file. 这段代码打开一个目录,并对该目录中的每个文件循环遍历文件中的每一行数据,然后对其进行解析以进行一些计算,并将结果数据输出到一个新文件中。

The problem is that I can only output a maximum of around 1021 files. 问题是我最多只能输出约1021个文件。 I'm closing all of the fopens after outputting all the data, so I'm not sure what I'm doing wrong. 输出所有数据后,我将关闭所有fopens ,所以我不确定自己做错了什么。

Shouldn't fclose() be closing the open files therefore this not happening? fclose()应该关闭打开的文件,因此不会发生吗?

int main(int argc, char *argv[])
{

 //sample data values
  double lat;
  double lon;  
  double convergence;   
  double pt_scale;        
  int    zone = 54;              
  double major_axis = 6378137.0000;        
  double flattening = (1/298.2572);        
  double zoneWidth = 6;         
  double centMeridian = -177;      
  double falseEast = FALSE_EASTING;         
  double falseNorth = FALSE_NORTHING;
  double scale = SCALE_FACTOR;  

  int max_size = 128;
  int current_size = max_size;
  char *pathStr = malloc(max_size);
  char *outPathStr = malloc(max_size);
  char coData[100]; //max length of line;
  long firstTerm, secondTerm; //terms we will split the line into, lat, lon, elevation.
  int counter = 0; //pos counter
  int d = EOF; //end of file ASCII
  char strIn[200];
  char* elevation;
  char strOut[200];
  char dirOut[200]; //sprintf must use a actual defined buffer otherwise there will be a buffer overflow.
  char* cchr;
  int j;
  _setmaxstdio(2048);
  printf("Please enter the path of the files: \n");
  getUserInput(pathStr, current_size, max_size); 
  printf("Please enter the output path of the files: \n");
  getUserInput(outPathStr, current_size, max_size);
  //loop through each file in the directory. Open the file, convert, then close it.
  //we will use dirent.h as it is cross platform so we wont have to worry about sharing issues
  DIR *dir; //new directory
  struct dirent *ent;
  dir = opendir(pathStr); //allcate it a path
  if(opendir(pathStr) == NULL)
  { printf("Error: %d (%s)\n", errno, strerror(errno));}
  int k;

  if(dir != NULL)
  {

         while((ent = readdir(dir)) != NULL) //loop through each file in the directory.
         {
                    //open the file and loop through each line converting it then outputing it into a new file
                if((!strcmp(ent->d_name,"..") || !strcmp(ent->d_name,".")) == 1)
                {
                        //dont want these directories
                        continue;
                }
                else
                {
                sprintf(strIn,"%s%s",pathStr,ent->d_name);    //get the file n
                FILE *fp = fopen(strIn, "r");
                if(fopen(strIn, "r") == NULL) //for inputting file
                { printf("Error: %d (%s)\n", errno, strerror(errno));
                                getchar();
                                  break; }

                sprintf(dirOut,"%s%d%s",outPathStr,counter,".geo");
                printf("%s \n",dirOut);
                FILE *fp2 = fopen(dirOut, "w"); //for outputting file
                if(fopen(dirOut, "w") == NULL)
                     { printf("Error: %d (%s)\n", errno, strerror(errno));
                      getchar();
                      break; }


                     while(fgets(coData, 100, fp) != NULL)//loop through line by line, allocate into 2 doubles and a string, pass the two coordinates and convert
                     {
                        //extract terms from coData                
                        char * pch; //pointer to array pos
                        char * pend;                          
                        pch = strtok(coData," ");                          
                        j = 0;

                            while(j <= 2) //We only want to split the first three parameters.
                            {
                                    //convert char array to double for co-oridinate conversion  

                                    if(j == 0)
                                    {
                                    firstTerm = atof(pch);         //latitude;           
                                    j++;
                                    continue;
                                    }
                                    if(j == 1)
                                    {
                                    pch = strtok(NULL, " ");
                                    secondTerm = atof(pch); //longitude
                                    j++;
                                    continue;
                                    }
                                    if(j == 2)
                                    {
                                    pch = strtok(NULL," ");
                                    elevation = pch; //elevation doesnt need to be converted because it isnt used in the coordinate conversion.
                                    break;
                                    }                                                               
                            }
                       grid2spheroid(&lat,&lon,&convergence,&pt_scale,firstTerm,secondTerm,zone,0, major_axis,flattening,zoneWidth,centMeridian,falseEast,falseNorth,scale);                                            
                       sprintf(strOut,"%f %f %s",lat,lon,elevation);
                       //printf("%d %d", lat, lon);                          
                       fputs(strOut,fp2);


                     }     //end of while        

                      fclose(fp2);
                      fclose(fp);
                      counter++;
                 }

                }
                closedir(dir);
  }
  free(pathStr); //finished using the path string so we can finish the 
  free(outPathStr);
  getchar(); 
  return 0;

 }

  void getUserInput(char *pathStr, int current_size, int max_size)
 {
 unsigned int i = 0;
 if(pathStr != NULL)
  {
              int c = EOF;

              //get the user input and reallocate the memory size if the input it too large.
              while((c = getchar()) != '\n' && c != EOF) //WHILE NOT END OF FILE OR NEW LINE (USER PRESSED ENTER)
              {
                   pathStr[i++] = (char)c;

                   if(i == current_size)
                   {
                        current_size = i+max_size;
                        pathStr = realloc(pathStr, current_size);
                   }    
              }
  }
}

You aren't closing all the files ;-) 您没有关闭所有文件;-)

FILE *fp = fopen(strIn, "r");
if(fopen(strIn, "r") == NULL) //for inputting file

Same applies to your output. 同样适用于您的输出。

I think you meant something more like: 我认为您的意思更像是:

FILE *fp = fopen(strIn, "r");
if(fp == NULL) //for inputting file
{
     // error handling.

No, no! 不,不! You're opening every file twice (and only closing once)! 您要打开每个文件两次 (并且只能关闭一次)!

  /* Bad! */
  dir = opendir(pathStr); //allcate it a path
  if(opendir(pathStr) == NULL)
  { printf("Error: %d (%s)\n", errno, strerror(errno));}
  int k;

  /* Correct */
  dir = opendir(pathStr); //allocate it a path
  if(!dir) { 
    printf("Error: %d (%s)\n", errno, strerror(errno));
    return;
  }

You're also doing the same thing with fopen(). 您也使用fopen()做同样的事情。 In both places :) 在两个地方:)

Just check the pointer ; 只需检查指针 ; don't call "fopen()" a second time; 不要第二次调用“ fopen()”; don't call "opendir()" a second time! 不要第二次调用“ opendir()”!

Also: please don't put code on the same line as your opening brace. 另外:请不要将代码与左大括号放在同一行。 OK? 好?

dir = opendir(pathStr); //allcate it a path
if(opendir(pathStr) == NULL)

(...)

FILE *fp2 = fopen(dirOut, "w"); //for outputting file
if(fopen(dirOut, "w") == NULL)

(...)

FILE *fp = fopen(strIn, "r");
if(fopen(strIn, "r") == NULL) //for inputting file

Here you open the file twice but only store the pointer once. 在这里,您两次打开文件,但只存储一次指针。 Change these to: 将它们更改为:

FILE *fp = fopen(strIn, "r");
if(fp == NULL) //for inputting file

and the other one in the same way. 和另一个以相同的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM