Anwendung reagiert nicht mehr



  • iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
          iFileLength = FileSeek(iFileHandle,0,2);
          FileSeek(iFileHandle,0,0);
          pszBuffer = new char[iFileLength+1];
          iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
          FileClose(iFileHandle);
    

    Das habe ich in der borland Hilfe gefunden.

    Nun meine Frage ist es besser,alles in eins, in einen string zu speichern.
    Um dann dort alles zusuchen?

    Ist es dann vom Speed her besser,wenn man char arrays, zum vergleichen nimmt?

    Und was ist wenn man eine Datei von 2 GB oder sowas öffnet?

    Stürzt der PC dann bedingslos ab?



  • Nicht, wenn der Rechner über ausreichend Speicher verfügt (physikalischen + virtuellen). Dauern tut es trotzdem, schliesslich lesen aktuelle Festplatten grademal 20 - 50 MB pro Sekunde (Dauertransferrate), und wenn der physikalische Speicher nicht ausreicht geht das Swappen los, was natürlich komplett kontraproduktiv ist (gleichzeitig die Datei von Platte lesen und die Swapdaten auf Platte schreiben).
    Du musst halt eine sinnvolle Grösse für den Puffer festlegen.

    Und was das Seeken betrifft: bei jedem Lesen wird der Dateizeiger automatisch um die Zahl der gelesenen Bytes weitergesetzt, es ist also allenfalls zu Beginn des Lesens ein Seek an den Anfang des Puffers erforderlich.



  • Hi,

    ohne sagen zu können, ob OpenFile oder TFileStream besser geeignet ist und unter Berücksichtigung, dass ich nur praktisch keine Dateizugriffe handhaben muß, da ich normalerweise alles über DBs mache...
    Man könnte es so lösen:

    AnsiString asFileNameAndPath = "c:\\sltest.txt";
    TFileStream* myfs = NULL;
    char* myfsbuf = NULL;
    int myfsbuf_size = 1024;
    int myfsbuf_read;
    try
    {
    	try
    	{
    		myfs = new TFileStream(asFileNameAndPath, fmOpenRead);
    		myfsbuf = new char[myfsbuf_size];
    		myfs->Position = 0;
    		do
    		{
    			myfsbuf_read = myfs->Read((void*) myfsbuf, myfsbuf_size);
    			// hier Daten auswerten
    		} while (myfsbuf_read == myfsbuf_size); // sobald der Puffer nicht mehr vollständig gefüllt wird, ist die Datei zu Ende
    	}
    	catch(...)
    	{
    		ShowMessage("Fehler beim Lesen der Datei.");
    	}
    }
    __finally
    {
    	if (myfs)
    		delete myfs;
    	if (myfsbuf)
    		delete[] myfsbuf;
    }
    

    Hierbei werden die Daten immer in 1 KB großen Blöcken eingelesen (myfsbuf_size)... Wenn Du myfsbuf_size testweise mal auf 1 setzt, wirst Du feststellen, dass das Lesen bereits deutlich länger dauert.

    Ich hoffe das hilft Dir weiter. Wie Du am besten vorgehst, hängt jedoch davon ab, was mit den Daten zu geschehen hat. Aber auch wenn Du immer nur ein 1 Byte aus der Datei brauchst, würde ich die Lösung über einen Puffer bevorzugen.

    Abschließend noch mal der Hiweis: Ich habe damit keinerlei praktische Erfahrung. Wenn also jemand einen besseren Vorschlag hat...



  • So mit buffer arbeiten habe ich mir auch überlegt.

    Nur ich hab dann einn Problem,wenn jetzt die Suchwerte über ein Buffer hinausgehen, habe ich ja eine Unterbrechung. Diese Unterbrechung ruft denn ja hervor das die zu suchende Werte nicht gefunden werden.

    Also halte ich die Idee mit den Buffer,hier eher als schlechtere Wahl.
    Und Jansens Idee finde ich auch gut,nur zweifel ich dran ob ich dann mein Zeitproblem löse, weil er denn ja bei einer 2GB Datei fast nur am swappen ist.
    Und diese Suchroutine ja mehr wie wie einmal läuft(jenachdem wieviel Werte er suchen muss), kann es sein das er auch mal 100 den Prozess durchläuft.
    Und wenn dann jeder Suchdurchgang,mehrere Minuten (so ca 10Min rum),braucht
    für eine Suche.
    10*100 Minuten sind nun wirklich beim besten Willen zuviel.

    Also ich weiss nicht,keine Lösung mehr,die mir helfen könnte.

    Wenn ich nochmal ein Geistesblitz kriege,setz ich mich ran.



  • Suchen über Puffergrenzen hinweg sollte auch gehen. Ist halt nur entspechend mehr Aufwand. Ich könnte mir eine Lösung mit 2 Puffern vorstellen. Wenn Du am Ende des ersten Puffers angekommen bist 'kopierst' (am besten nur einen Zeiger) Du den zweiten Puffer in den ersten und lädst das nächste KByte in den zweiten Puffer...



  • So ich habe jetzt die ganze datei in Char Array gepackt. So wie es Jansen meinte.

    Und jetzt liest der 12Minuten wieder diese brühmten 20Mb ein.
    Was mach ich den falsch?

    Den big.seekp(ios::beg);
    habe ich nachdem Fileöffnen gesetzt.
    In der Schleife arbeite ich nur noch mit big.get(byte);

    Und ich habe nix gefunden,was fstream mit Buffer kann.
    (fstream big("test.dat",ios::in|ios::out|ios::binary);)



  • Versuch doch bitte mal die Routine, die ich oben gepostet hab'. Die mit dem TFileStream. Einfach ein neues Projekt anlegen und den Code in eine Buttonfunktion legen.
    Du mußt dann nur noch in der ersten Zeile den Dateinamen ändern. Auf meinem Rechner dauert das Einlesen einer 200 MB Datei damit 6 bis 8 Sekunden (AMD XP2400+).

    EDIT: Jansen hat Dir (berechtigterweise) davon abgeraten, die ganze Datei in ein char-Array zu lesen. Der Vorschlag stammt von mir. Allerdings bin ich davon ausgegangen, dass die Datei nicht wesentlich größer als 20 MB wird...



  • Joe_M:
    Danke, ich wollte mich grad wundern, um was für eine Idee es gehen sollte. 😉

    the_hero99:
    Du solltest mal versuchen, das reine Einlesen der Datei vom Auswerten bzw. Vergleich der Daten trennen, um festzustellen, wo genau der Flaschenhals liegt.



  • Also wie sagte es ist nur noch eine for Schleife da

    fstream big("test.dat",ios::in|ios::out|ios::binary);
    big.seekp(ios::beg);
    for(i=1;i<=size;i++)//size Dateigrösse
    {
    big.get(einzel);
    }
    big.close();
    

    Wenn die zuende ist,wechselt die StatusBar den Text.

    Aber ich weiss nicht,warum das in einer Windows Anwendung so lahmt.
    In Konsolenanwendungen hatte ich auf diesen PC, 3,2 Gigabyte gelesen und geschrieben, in ca.40MIN.

    Und da habe ich die gleichen Befehle und Routinen beutzt.

    Aber da war auch eine starke Prozessor Auslastung zusehen.



  • Du liest immer noch JEDES BYTE EINZELN ein. Warum? Das ist genau der Punkt der Deine Routine bremst. Wo ist der Unterschied, ob das Zeichen direkt aus der Datei einliest, oder aus einem Puffer?

    Was die Suchfunktion selbst angeht, google mal nach Boyer-Moore-Horspool Algorithmus...



  • Ich bin zu dumm, ich hab keine deutschen Hilfen zu einer ander Fileopen Funktion gefunden.
    Ich weiss nicht wie ich da zb. 1024 bytes einlese,die in ein Array packe oder so.
    Ich muss doch alles einzeln einlesen.
    Ich hab 2 Dateien:
    In einer sind die Werte drin nachdem ich suche.
    00112233|§4§|ff001020|§4§|00008822|§4§|

    Das ist mein String 2 Zahlen ergeben immer ein Ascii Wert.
    Die 4 zwischen den § gibt so eine Joker Zeichen an,also 4 bytes überlesen dann weiter suchen.

    Und ich weiss echt nicht mehr,wie das anders Regeln kann.

    Ohne das jetzt bestehende zu verwerfen.



  • Joe_M. schrieb:

    <fullquote gelöscht>

    Ungefähr so würde es klappen die Daten in einem Rutsch einzulesen. Wo ist das Problem den Code zu kopieren und einzufügen? 🙄

    Edit:
    Zitate bitte auf das Notwendigste beschränken. Danke!



  • Also ich hab' jetzt hier keinen BCB zum nachsehen, aber auch fstream müßte eine Read-Funktion haben, mit der man eine definierte Anzahl Zeichen einlesen kann (obwohl sie möglicherweise nicht Read heißt...).

    Zu dem Suchproblem: Also suchst Du nicht nach einer Zeichenfolge, sondern nach mehreren Zeichenfolgen, die in einer bestimmten Relation zueinander stehen. Sehe ich das richtig? Hast Du dir den Boyer-Moore-Horspool Algorithmus schon angesehen?



  • Ich glaube ihr versteht mich nicht.
    Ich versteh nicht wie man, sowas im string suchen soll.
    Der String muss auch binär Werte aufnehmen können.
    Und ich glaube ich rall grad was total nicht.
    Ich brauch dann den Offset wo der String vorkommt.
    Den will ich in eine Datei schreiben,die Offset Angaben da,benötige ich um zB.
    zu sehen, wo welche Vorkomnisse waren.



  • ich glaube du solltest dir noch mal ein paar C++ Grundlagen zu Arrays/Strings durchlesen.

    Du kannst auch auf einen String vom Typ std::string oder AnsiString mittels dem Index-Operator zugreifen.

    Und so kann man damit beipielsweise arbeiten

    char c[21] = "Hallo, Welt!";
    char erg;
    for(int i = 0; i<as.Length(); ++i)
    {
       if(c[i] == '!')
       {
          reg = c[i];
       }
    }
    


  • the_hero99:
    Versteif dich nicht auf deinen kompletten Suchstring inklusive der "Joker".

    Finde erstmal nur den Teilstring bis zum ersten Joker. Wenn du den gefunden hast kannt du die Zahl-der-Joker-Zeichen überspringen und prüfen, ob die folgenden Zeichen mit dem zweiten Teilstring übereinstimmen. Wenn ja, dann machst du so weiter bis ggf. zum letzten Teilstring. Wenn nicht, dann kehrst du zur Suche nach dem ersten Teilstring zurück und machst da weiter.



  • @Pupetmaster das man mit ansistring spezielle Positionen anspringen kann,weiss ich ja.

    Daher war ja meine Idee die ganze Datei einzulesen, um die dann auszuwerten.
    (war meine allererste Idee).
    Nur wie ich sagte,habe ich da bedenken bei Datein von 2Gb oder mehr.

    Jetzt habe ich noch eine andere Idee,wie wär es wenn man den ganzen Kram wie schon gesagt Blockweise einliest,und dann immer die Blocks durchsucht(da gibt es ja zu ansistring gute Funktionen).

    Ob der Suchstring dann am Ende des Blocks beginnt,könnte man ja abfangen oder abfragen.

    Nur mein problem ist,ich habe nirgens eine gute Anleitung zu andere Fileopen Funktionen gefunden.
    Mal dies mal das,nie ne richtige Anleitung oder gute deutsche Erklärung.

    Wenn da vielleicht einer ein Link hätte,wäre ich sehr dankbar.



  • Die FAQ vom C++ Forum wäre hier angebracht. Und dann würde ich mich an das halten was Jansen in seinem letzten Post geschrieben hat!

    Oder du nimmst das Beispiel von Joe_M. Er arbeitet dort mit TFileStream (kann man nachlesen in der BCB-Hilfe)



  • Ich gebs auf.

    Ich komm mit den ganzen Mülllllllllllllll nicht mehr klar.

    ICH RALL DAS EINFACH NICHT.

    Sorry wenn das unhöflich war nur ich rall, das alles nicht.

    Ich kenn nur fstream mit get und put bzw.>> << mehr nicht.

    In Builder kann ich LoadFromfile und co.

    Aber ich versteh nur nicht, wie man da Offsets und Blocks lesen kann.

    die Beispiele von Joe_m sind sehr gut.
    Nur leider versteh ich nix was da passiert,bzw. wie ich da binär auslesen,einzelne zeichen schreibe,zum Offset springe usw.

    Wenn ich das könnte, wäre mir ja schon sehr geholfen.

    Auch wenn dann die ganze Suchroutine die ich geschrieben habe(200 Zeilen) hinfällig wäre.

    Ich denk mal wenn ich bis morgen das Problem nicht gelöst habe, lass ich es sein.
    Dann habe ich da über 5 tage rumgefummelt,ohne ein Ergebnis.



  • char pBuffer[1024];
    fstream FileBin("d:\\cdtemp\\streams\\test.dat",ios::in|ios::out|ios::binary); 
    if (FileBin.is_open()) 
    FileBin.seekp(ios::beg);
    { 
         FileBin.read(pBuffer, 1024); 
    
        // Hier string auswerten; 
    
    }
    

    Liege ich jetzt richtig, das ich so immer 1024 zeichen auf einmal einlese?

    Weil wenn es so ist,wäre ja mein verständnis Problem fast gelöst.


Anmelden zum Antworten