Per CFileDialog und CFile Textdatei in TextBox lesen ?



  • Hi Leute,

    hab vor 2 Tagen mit der MFC angefangen und hab nu ein Prob.
    Ich möchte eine txtDatei beliebiger Grösse mit CFileDialog auswählen und miz CFile öffnen. Der Inhalt wird zunächst in ein TCHAR array eingelesen, bei dem ich ne Grösse angeben muss(dann klappts auch), wenn ichs auf den Heap schiebe um das Array dynymisch zu machen klappt nix mehr 😢

    Hier mal mein Code des Click ereignisses :

    void CFileDialogDlg::OnTextEinlesen() 
    {
    
    	CFile file;
    	TCHAR *str = new TCHAR[]; // Wenn Array feste Grösse hat funzts
    
    	char strFilter[] = { "txt Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
    	CFileDialog FileDlg(TRUE, ".txt", NULL, 0, strFilter);
    
    	if( FileDlg.DoModal() == IDOK )
    	{
    		 file.Open(FileDlg.GetFileName(), file.modeRead);
    		 file.Read(str, sizeof(str));
    	}
    	else
    		return;
    	file.Close();
    
     	m_stxtBox = str;
    
     	UpdateData(FALSE);
    }
    

    Vielen Dank für eure Hilfe
    ShadowEater 😉



  • TCHAR *str = new TCHAR[];
    

    Diese Zeile ist so unsinnig. Wenn du ein Array anlegen willst, musst du natürlich mitteilen, wie groß es sein soll. Da du new nutzt, muss der Wert nicht fest sein, sondern kann aus einer Variable stammen.
    Du musst also erst feststellen, wie lang der Text in der Datei ist und dann ein Feld entsprechender Größe anfordern.


  • Mod

    Mit CFile::GetLength kannst Du die Größe ermitteln der Datei (in Bytes)
    Du kanst dann mit new einen entsprechenden array anlegen. Und dann kannst Du CFile::Read durchführen.

    BTW: Nimm einfacher CStdioFile, dann hast Du mit Textdateien weniger Probleme.



  • Danke für deine Antwort (so früh schon ;))

    ist Cstdio moderner?
    Ich habs mit Getlength ver sucht aber es werden nur die ersten 5 Buchstaben in die Textbox geschrieben !
    Die Variable m_stxtBox = str ist vom Typ CString, muss ich da str casten,l wenn ja warum wenn str nur ein normales TCHAR array ist klappt doch auch alles nur wenn ich dynamisch machen will klappts nicht? 😞

    CFile file;
    	TCHAR *str = new TCHAR[];
    
    	char strFilter[] = { "txt Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
    	CFileDialog FileDlg(TRUE, ".txt", NULL, 0, strFilter);
    
    	if( FileDlg.DoModal() == IDOK )
    	{
    		 file.Open(FileDlg.GetFileName(), file.modeRead);
    		 file.Read(str, sizeof(str));
    	}
    	long lLength = file.GetLength();	 
    
    	str[lLength];
    	file.Close();
    
    	m_stxtBox = str;
    
     	UpdateData(FALSE);
    }
    

    ShadowEater 😉



  • Wie Pellaeon schon sagte: Du mußt schon beim new-Aufruf angeben, wieviel Speicher du benötigst. Außerdem mußt du die richtige Größe an Read() übergeben:

    CFile file;
        TCHAR* str;
        char strFilter[] = { "txt Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
        CFileDialog FileDlg(TRUE, ".txt", NULL, 0, strFilter);
    
        if( FileDlg.DoModal() == IDOK )
        {
            file.Open(FileDlg.GetFileName(), file.modeRead);
            str=new TCHR[file.GetLength()];
            file.Read(str, file.GetLength());
        }
        file.Close();
    
        m_stxtBox = str;
        delete[]str;
    
        UpdateData(FALSE);
    

    PS: Eigentlich könntest du dir das Kopieren auch ersparen und direkt in den Puffer des Zielstrings einlesen:

    if(FileDlg.DoModal()==IDOK)
    {
      file.Open(FileDlg.GetFileName(),file.modeRead);
      long size=file.GetLength();
      file.Read(m_stxtBox.GetBuffer(size),size);
      m_stxtBox.ReleaseBuffer();
    }
    


  • D*A*N*K*E CSToll,:) 🙂 🙂

    funktioniert hervorragend, auch die 2. Variante(gleich in den Zielbuffer einlesen). Bei der 1. Variante halt ich mir halt die Option offen noch was zu ordnen bzw zu parsen 😉
    Drei kleine Fragen hab ich aber noch :
    1. Wenn Du das Array str mit new auf den Heap schiebst, warum ausgerechnet in der Forschleife und nicht in der Deklaration, nach dem erzeugen des CFile Objekts?

    CFile file;
        TCHAR* str;
        char strFilter[] = { "txt Files (*.txt)|*.txt|All Files (*.*)|*.*||" };
        CFileDialog FileDlg(TRUE, ".txt", NULL, 0, strFilter);
    
        if( FileDlg.DoModal() == IDOK )
        {
            file.Open(FileDlg.GetFileName(), file.modeRead);
            str=new TCHR[file.GetLength()]; // <---???
            file.Read(str, file.GetLength());
        }
        file.Close();
    
        m_stxtBox = str;
        delete[]str;
    
        UpdateData(FALSE);
    

    2. Wenn ich das Prg. laufen lasse und der Text in die txtBox eingelesen wird, werden am Ende noch 4 undefinierte Zeichen angehängt Lean on me...ýýýý <---
    liegt das an einer fehlenfen 0 terminierung ?😕

    Die Datei hatt ich doch auch mit nem fstream Objekt einlesen können und dann einfach in CString parsen ?😕

    nochmal DANKE
    ShadowEater 😉



  • 1. Du kannst den Speicher erst dann anfordern, wenn du seine Größe kennst. Und die kannst du erst dann ermitteln, nachdem du die Datei geöffnet hast.
    (btw, wo siehst du in dem Code eine for-Schleife?)

    2. Ja, die fehlende Null-Terminierung könnte ein Problem sein. Und die Lösung ist recht einfach - ein Byte mehr anlegen und mit '\0' füllen.

    3. Klar kannst du auch fstream's verwenden, die funktionieren analog zu CFile (nur daß fstream keine eingebaute GetLength()-Methode hat)



  • 😉 Ich meinte IF - Abfrage 😉

    Danke für die Hilfe
    ShadowEater



  • Hat geklappt, es lag an der 0 - Terminierung 😉

    void CFileDialogDlg::OnTextEinlesen() 
    {
    
     CFile	file;								
     TCHAR*str = NULL;						
     char strFilter[] = { "txt Files (*.txt)|*.txt|All Files (*.*)|*.*||" }; 
     CFileDialog FileDlg(TRUE, ".txt", NULL, 0, strFilter); 
    
     if( FileDlg.DoModal() == IDOK )						
     { 
        file.Open(FileDlg.GetFileName(), file.modeRead);
        str = new TCHAR[(file.GetLength())+1];	// <---	Ein Byte mehr	
        str[(file.GetLength())] = '\0';             // <--- Nullterminator
        file.Read(str, file.GetLength());				
     } 
        file.Close();									
        m_stxtBox = str; 
        delete[]str;										
        UpdateData(FALSE);							
    }
    

    Ist die Cstdio und CStrings moderner im Gebrauch gegenüber TCHAR ? 😕

    ShadowEater



  • Was genau meinst du mit "CStdio"? Wenn du das CStdioFile meinst, dann vermutlich ja - das ist speziell für text(zeilen)orientierte Ein/Ausgabe vorgesehen. Und vor allem nutzt es CStrings, das heißt, daß du dich nicht mehr mit der Speicherverwaltung herumschlagen mußt.

    (Aber CStdioFile liest zeilenweise, das heißt bei größeren Dateien mußt du deinen Ergebnisstring stückweise einlesen, bis die Datei leer ist)



  • AHA werd mich damit beschäftigen.

    😉
    ShadowEater


Anmelden zum Antworten