größere Dateien(10 bis 200 MB) lesen



  • hallo
    ich habe ein programm geschrieben welches eine Datei öffnet und liest.
    folgende Code wurde für das öffnen zum Lesen implementiert.

    char  szfile[50]; 
      ifstream file;   
      do 
      {  
         file.clear();  //clear status flags des Inputstreams "file"
         cout<<"Dateiname inklusive Pfad eingeben: "; 
         cin>>szfile; 
    
         file.open(szfile,ios::in); // "file" wird geöffnet zum Lesen
    
         if(file.fail())         // Fehlertest durchführen   
         cout<<"Datei existiert nicht!"<<endl; 
    
      }while(file.fail());
    

    es funktioniert einwandfrei. Aber mein Problem ist: wenn ich größere Dateien ab 10Mb dann dauert es halt sehr lange!
    gibt´s Alternativen bzw. Funktionen die den Prozess beschleunigen oder spezielle func die die datei im Hintergrund liest ohne sie zu laden ?
    vielen Dank



  • memory mapped files



  • warum ist dein buffer nur 50 zeichen lang?



  • Wenn ich mich nicht verlesen hab dann ist "szfile" nur der Pfad der Datei und nicht der Inhalt. Aber ich denke vll sollte man doch eher MAX_PATH (= 255) als Länge benutzen, man weiss ja nicht wie lang der Pfad nun ist.



  • Man sollte vielleicht lieber std::string benutzen, dann ist die Pfadlänge schnuppe.



  • Ich sehe keinen Code, der eine Datei einliest. Wenn du wissen willst, warum das so lange dauert, solltest du den Einleseteil vielleicht auch posten. 😉
    Prinzipiell sollte dein Buffer zum Einlesen nicht zu klein sein, sonst ist der Overhead für jeden einzelnen Einlesevorgang zu groß und bremst das unnötig.



  • lilian schrieb:

    es funktioniert einwandfrei. Aber mein Problem ist: wenn ich größere Dateien ab 10Mb dann dauert es halt sehr lange!
    gibt´s Alternativen bzw. Funktionen die den Prozess beschleunigen oder spezielle func die die datei im Hintergrund liest ohne sie zu laden ?
    vielen Dank

    Was genau dauert lange. In deinem Beispiel zeigst du uns ja nicht wie du das File liest, nur wie du es öffnest und dabei kann man wirklich nicht viel optimieren.
    Kurt



  • hallo
    Danke für die zahlreichen Antworten.
    also beim Lesen habe die Funktion "getline" benutzt. also zeilenenweise lesen
    hier ist der ganze Code:

    int readFile()
    {
       //-------------- Existenztest der Datei  --------------------------
    	   char  szfile[50]; 
    	   ifstream file;   
    	   do 
    	   {  
    		  file.clear();  //clear status flags des Inputstreams "dat"
    		  cout<<"Dateiname inklusive Pfad eingeben: "; 
    		  cin>>szfile; 
    
    		  file.open(szfile,ios::in); // "dat" wird geöffnet zum Lesen
    
    		  if(file.fail())                     // Fehlertest durchführen   
    		  cout<<"Datei existiert nicht!"<<endl; 
             cout<<"\ndatei is open\n";
    	   }while(file.fail()); 
    	 //-------------------------------------------------------------------
    	   do
    	   {
    
    		   string strline,strl1,strl2,str3;	   
    		   int nrow; 
    		   do 
    		   {   
    			   if(bheader==false)
    			   {
    				 // string strline,strl;
    				  string str2= "time_record for";
    
    				  string str="Rec ";
    				 // int i=0;
    				  getline(file,strline);
    				  if(strline!="")
    				  {
    					  for(int k=0;k<15;++k)
    					  {
    						 strl1.resize(k+1);
    						 strl1[k]=strline[k];
    					  }
    					  if (str2 == strl1)     //  wenn strl1 == "time_record for"  
    					  {
    						  for(int m=16; m<strline.size(); ++m)
    						  {
    							 str3.resize(m-15);
    							 str3[m-16]=strline[m];
    						  }
    
    						  v_header.push_back(str3);	
    					  }
    
    					  for(k=0;k<4;++k)
    					  {
    						  strl2.resize(k+1);
    						  strl2[k]=strline[k];
    					  }
    					  if (str == strl2)         //  wenn strl == Rec  
    					  {
    						  getline(file,strline);
    						  for (nrow=0;nrow<6; ++nrow)    // nur die zweite und die vierte Zeile lesen
    						  {   
    							 getline(file,strline);
    							 if(nrow==1) 
    							 {
    
    								 string a, b, c, d, x, y;
    								 std::stringstream(strline)>>a>>b>>c>>d>>x;									  
    								// v_header.resize(++i);
    								 v_header.push_back(x);	 
    
    							 }
    							 if(nrow==3) 
    							 {
    								 string a, b, c, d, x, y;
    								 std::stringstream(strline)>>a>>b>>c>>d>>x>>y;									  
    
    								// v_header.resize(++i);
    								 v_header.push_back(y);	
    								 bheader=true;
    
    							 }
    
    						  }
    
    					  }
    				  }
    			  }
    		   }while(nrow!=6);
    
    		   if (nrow==6) 
    		   {
    			   int index=0;
    			   string s;
    			   do
    			   {
    				   getline(file,strline);
    				   for(int k=0;k<15;++k)
    				   {
    					 s.resize(k+1);
    					 s[k]=strline[k];
    				   }
    				   if (s=="time_record for")
    				   {
    					 //  printData();
    					   string a, b, c;
    					   std::stringstream(strline)>>a>>b>>c;									  
    					   v_header.push_back(c);
    
    					   nrow=0;
    					   bheader=false;
    					   chi++;
    					   continue;
    				   }
    				   string a,b,c,d,e,f;
    				   std::stringstream(strline)>>a>>b>>c>>d>>e>>f;
    				   if (a!="" && b!=""&& c!=""&& d!=""&& e!=""&& f!="")
    				   {
    					   mat_data.resize(chi+1);
    					   mat_data[chi].resize(index+6);
    					   mat_data[chi][index]   = a;
    					   mat_data[chi][index+1] = b;
    					   mat_data[chi][index+2] = c;
    					   mat_data[chi][index+3] = d;
    					   mat_data[chi][index+4] = e;
    					   mat_data[chi][index+5] = f;
    					   index=index+6;
    				   }
    
    			   }while(s!="time_record for" && !file.eof());
    		   }
    
           }while(!file.eof());
    	   file.close();
    
           return 0;
    }
    

    Danke



  • for(int k=0;k<15;++k) { 
        strl1.resize(k+1); 
        strl1[k]=strline[k]; 
    }
    

    Das machst du am besten durch Zuweisung eines Substrings(siehe Link). Jede Anwendung des []-Operators bei Strings ist ja schließlich ein Funktionsaufruf und jedes Resizen auch.

    string str2= "time_record for"; 
    string str="Rec ";
    

    Die beiden könntest du als const strings außerhalb deiner Einleseschleife definieren, sonst werden sie bei jedem Schleifendurchlauf erneut erzeugt.

    string a, b, c, d, x, y; 
    std::stringstream(strline)>>a>>b>>c>>d>>x;                 
    v_header.push_back(x);
    

    Da du die Strings a,b,c,d,y sowieso nicht benutzt, brauchst du sie auch nicht zu erzeugen. Ich weiß zwar nicht, ob es eine formatierte Ignore-Variante für Streams gibt (mit der Funktion ignore könntest du im Stream zeichenweise ignorieren, wenn die Anzahl immer gleich ist), aber so funktioniert es auch, da von links nach rechts ausgewertet wird:

    string x; 
    std::stringstream str(strline)
    str>>x>>x>>x>>x>>x;                 
    v_header.push_back(x);
    
    if (a!="" && b!=""&& c!=""&& d!=""&& e!=""&& f!="")
    

    Die String-Funktion empty wäre in dem Fall wohl besser geeignet. Es wird zwar bei deinem Vergleich nicht gleich ein String-Objekt ("") erstellt, eleganter ist empty aber doch.

    Vielleicht lässt sich da ja noch was optimieren, wenn du uns den Aufbau deiner Dateien verrätst.

    http://www.cppreference.com/cppstring/empty.html
    http://www.cppreference.com/cppstring/substr.html



  • lilian dein code ist total scheisse. programmier das nochmal neu bitte.



  • Danke
    @ masterofx32
    ich habe gemacht was du mir verbessert hast aber trotzdem der Leseprozess ist immer noch langsam.
    @ net
    was ist mit memory mapped files? könnte das Problem damit lösen? ich habe gegoogelt aber nichts gescheites! bitte hilft mir?
    vielen Dank



  • Wie sehen denn deine Eingabedateien aus und wie genau willst du sie verarbeiten?

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dngenlib/html/msdn_manamemo.asp



  • mit memory mapping von files kann man einen ausschnitt einer grossen datei in den (virtuellen) speicher abbilden und die datei dann mit ganz normalen speicherzugriffen bearbeiten. guckst du: http://www.catch22.net/tuts/bigmem01.asp



  • vielen Dank für die schnellen Antworten
    damit ihr einen Überblick folgendes sehen die einzulesende Dateien (sind zw. 10 und 200MB) aus:

    -1

    NONE
    LMS CADA-X TEST APPLICATION
    26-Apr-05 14:39:31
    -1
    -1
    164
    1 Metric SI
    1.00000000000000000D+00 1.00000000000000000D+00 1.00000000000000000D+00
    0.00000000000000000D+00
    -1
    -1
    58
    time_record for comp:1:+X response / invalid
    26-Apr-05 14:38:53
    Rec 4720 of test "100-abc"
    NONE
    1 0 4720 0 comp 1 1 NONE 0 0
    2 43008 1 0.00000e+00 2.44141e-04 0.00000e+00
    17 0 0 0 NONE s
    12 0 0 0 NONE g
    0 0 0 0 NONE NONE
    0 0 0 0 NONE NONE
    -6.16959e-02 1.49747e-02 4.19293e-02 -1.31778e-02 -5.81020e-02 -3.29444e-02
    2.99495e-03 1.85687e-02 5.39090e-03 3.59394e-02 -3.53404e-02 -4.13303e-02
    -3.17464e-02 2.33606e-02 4.19293e-02 -8.68535e-02 -4.73202e-02 -3.11474e-02
    0.00000e+00 9.58383e-03 -1.07818e-02 2.99495e-02 -6.58888e-02 -2.57565e-02
    -2.45586e-02 -5.98989e-04 4.79191e-03 -7.66706e-02 -5.63050e-02 -2.69545e-02
    -1.25788e-02 -2.93505e-02 -5.63050e-02 -3.53404e-02 -8.38585e-03 -4.19293e-03
    -1.25788e-02 -6.76858e-02 -4.01323e-02 -1.85687e-02 4.19293e-03 -1.19798e-03
    -4.91171e-02 -5.63050e-02 -2.15636e-02 6.58888e-03 2.33606e-02 -1.55737e-02

    -1
    -1
    58
    time_record for comp:2:+X response / invalid
    26-Apr-05 14:38:53
    Rec 4729 of test "100-ujb"
    NONE
    .........
    .............usw.

    alles was unterschrichen(ich habe die Unterschriche extra für euch hinzugefügt) wird in vektoren gespeichert und in einer extra-Datei geschrieben.
    Danke



  • ich habe beim googeln das Beispiel für file mapping gefunden

    //open a file, and set the first 99 characters as
    //uppercase using file mapping
    void fileExample2(){
        char* dataPointer;
        DWORD maxLen;
    
        HANDLE hFile=CreateFile(
            "hithere.txt",//name of the file
            GENERIC_READ | GENERIC_WRITE,//desired access
            FILE_SHARE_READ,//share mode
            NULL,//security attributes
            OPEN_ALWAYS,//creation disposition
            FILE_ATTRIBUTE_NORMAL,//flags and attr
            NULL);//template file
    
        //that's to avoid Windows killing the program
        maxLen=GetFileSize(hFile,NULL);
        maxLen=(maxLen>99)?99:maxLen;
    
        HANDLE hFM=CreateFileMapping(
            hFile,//handle
            NULL,//security
            PAGE_READWRITE,//flProtect
            0,0,//max size
            NULL);//name
    
        dataPointer=(char*)MapViewOfFile(
            hFM,FILE_MAP_ALL_ACCESS,0,0,0);
    
        CharUpperBuff(dataPointer,
            maxLen//don't pass the limit!
            );   
    
        UnmapViewOfFile(dataPointer);
    
        CloseHandle(hFM);
        CloseHandle(hFile);
    }
    

    wie kann ich das in meinem obigen programm implementieren bzw. mit meinem Code einbinden lassen?
    ich brauche dringend eure Hilfe. Danke sehr


Anmelden zum Antworten