txt-Datei erstellen



  • Hi,

    bevor ich mich auf die wilde Programmiererei stürze, wollte ich mir hier erst mal ein paar Tipps abholen. Ich wollte versuchen mit MFC eine Oberfläche zu erstellen, die in der Lage ist einen string in eine Text-Datei zu schreiben. Als übliches "speichern unter" wie man es halt so kennt. Kann mir jemand sagen wie ich das am besten mache?



  • Erstell ein SDI-Projekt und stell den View auf EditView um und schon hast du dein nen EditWindow was laden und Spiechern kann. Wird aber sicher nicht das sein was du suchst, also musst du entweder deine Frage präzisieren oder dich in die Grundlagen von MFC Einarbeiten. Denn wenn du ein SDI-Porjekt erstellen willst was dann auch noch mehrere Elemente enthält (edit, ListBox, Tree und so weiter) dann wirst du mit einer einfachen Beschreibung nicht sehr weit kommen

    Falls du noch gar nix mit MFC gemacht hast, solltest du dich vielleicht erstmal mit den Elementen beschäftigen und welche Handler wie und wo benutzt werden, da is laden und speichern erstmal das letzte was du brauchst.



  • sorry, meine Schuld, hier mein Quellcode bislang

    CFileDialog fileDlg( FALSE, _T("txt"), _T("*.txt"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY); 
    	CFileDialog dlgFile(TRUE);
    
    	fileDlg.DoModal();
    

    komme in den filedialog, 1.Argument auf FALSE zum speichern, datei-endung auf .txt

    aber leider wird keine datei erstellt... was hab ich vergessen?



  • du hast nix vergessen, CFileDialog stellt dir auch nur den Dialog dar in dem man den Pfad und den dateinamen auswählen kann, nicht mehr und nicht weniger, wenn der Dialog mit IDOK beendet wurde kannst du mit fileDlg.GetPathName() dir den pfad als CString zurück geben lasse und diesen dann mit der Klasse CFile Benutzen um eine Datei zu erzeugen und dann deine Daten in die Datei zu schreiben.

    CFileDialog fileDlg( FALSE, _T("txt"), _T("*.txt"), OFN_FILEMUSTEXIST | OFN_HIDEREADONLY);
        CFileDialog dlgFile(TRUE);
    
        if(fileDlg.DoModal() == IDOK)
    {
        CFile file;
        if(file.open(fileDlg.GetPathName(),CFile::modeRead) != 0)
        {
            //hier jetzt daten schreiben mit file.write(...)
        }
    }
    

    hab da mal schnell zur verdeutlichung nen beispiel hingebastelt, ob das wirklich jetzt läuft oder ich schreibfehler drin hab weis ich nicht, zumindest zeigt es dir wie das mit dem schreiben geht



  • Du musst erst noch eine Variable vom Typ CStdioFile deklarieren. Dann kannst du mit dem passenden Open Befehl die Argumente auf Create und modewrite stellen

    sollte ungefähr so aussehen:

    CFileDialog fileDlg( FALSE, _T("txt"), _T("*.txt")); 
    
    	fileDlg.DoModal(); 
    
    	CString Dateipfad = fileDlg.GetPathName();
    
    	CStdioFile Datei;
    
    	CString Ausgabe = _T("hello world");
    
    	int Laenge = Ausgabe.GetLength();
    	Datei.Open (Dateipfad, CFile::modeCreate | CFile::modeWrite); 
    
    	Datei.Write (Ausgabe, Laenge);	  
    	Datei.Close (); 
    }
    


  • Das von Stutzpeter funktionert fast perfekt.

    nur leider steht in der erstellten datei:

    h e l l o

    www? - weiß wer warum?



  • Ach richtig, SRY!

    bei dem Zeichensatz, den Windows u.a. bei CString verwendet, ist ein Zeichen 2 Byte lang. Normale ASCII und ANSI-Zeichen haben nur 1 Byte. Versuchst Du jetzt, die "breiten" Zeichen (wide chars) zu verschicken, werden jeweils zwei Bytes übertragen. Das obere Byte ist bei normalen Buchstaben und Zahlen 0x00 und wird für besondere Zeichensätze (Chinesisch etc.) einen Wert annehmen.

    Als Abhilfe gibt es nun 2 Möglichkeiten, entweder du multiplizierst deine Stringlänge mit 2:

    Datei.Write (Ausgabe, Laenge*2);
    

    oder du konvertierst den wide char zu ANSI:

    CStringA Ausgabe_Neu(Ausgabe);
    Datei.Write (Ausgabe_Neu, Laenge);
    

    geht beides 😉



  • weil du sicher ein unicode project hast und damit dein sting halt doppelt so lang ist, jeder buchstabe halt 2 byte, wenn du die länge verdoppelst dann passt das auch

    Stutzpeter 2. variante seh ich eher als workaround als einen lösungsansatz, auch wenns natürlich auch geht siehts unschön aus



  • Verstehe zwar nur Bahnhof aber danke euch beiden! nun läufts



  • wieso, sturzpeter hat doch alles gesagt, ansi ist 1 byte pro zeichen und unicode 2 byte pro zeichen, CString::GetLength() gibt dir die anzahl der zeichen zurück ohne betrachtung ob das nun unicode oder ansi ist. Bei unicode bedeutet dass, das du nur den halben spiecher raus schreibst, weil write ja nur die anzahl der bytes raus schreibt die du im sagst



  • @CTecS:

    in diesem Falle ja, aber spätestens wenns was über eine serielle Schnittstelle übertragen wird, kommt man mit der Multiplikation von 2 nicht mehr weiter. Dadurch würde zwar der vollständige String versendet und nicht nur die Hälfte, allerdings bleibt das obere Byte (0-Byte) weiterhin bestehen. Dadurch würden doppelt so viele Bytes wie benötigt übertragen...



  • na ja das kommt auch drauf an was die gegenseite empfangen möchte, wobei jetzt dein beispiel mit der seriellen schnittstelle doch etwas anwägig ist, hättest du netzwerk gesagt und traffic mit angesprochen dann hätte ich dir ja noch geglaubt aber wer benutzt heute noch die serielle schnittstelle um text drüber zu schaufeln?

    wobei wenn man das richtig machen will sollte man dann doch schon WideCharToMultiByte()

    USES_CONVERSION;
    CStringA text = W2A(_T("text"));
    

    benutzen.

    und nach reiflicher überlegung bin ich dazu gekommen das man die sache mit der länge mal 2 auch eleganter lösen kann

    Datei.Write (Ausgabe, Laenge*sizeof(TCHAR ));
    

    oder noch besser

    Datei.WriteString(Ausgabe);
    

    wobei selbst beiu Write man die länge weg lassen kann weil das abgeleidet ist von CFile und da kann man auch einen Cstring übergeben ohne die länge anzugeben.



  • stimmt, bin ich gerade nicht drauf gekommen.

    mit der seriellen schnittstelle geb ich dir auch recht, ist finde ich am einfachsten zu implementieren, und wir nutzen sie zum datenaustausch mit evaluation boards (fpga)



  • na ja wenn es keine andere möglichkeit zur anbindung gibt, ist das ja die einzige möglichkeit. Aber solange wie eine netzwerkverbindung möglich ist, würde ich diese bevorzugen und vom programieraufwand ist das sicher auch nicht viel mehr. aber wie gesagt kommt auch immer drauf an was man übertragen muss, denn ihr werdet doch sicher auch mit handshake arbeiten was bei TCP/IP ja schon inkusive ist.

    wobei ich zugebe das ich schon die wundersamsten sachen gesehen habe, da werden dann daten über UTP übertragen und ein protokoll drum rum gebastelt und das ganze noch gepollt anstatt ganz einfach TCP/IP zu benutzen.

    aber jetzt schweif ich irgendwie zu weit vom thema ab 😃



  • ich bins nochmal

    der Code von Sutztpeter funktioniert soweit,aber wenn ich in diesem dialog bin und klicke anstatt auf speichern auf abrechen, stürzt das programm ab.

    weiß wer warum?

    hier nochmal der code

    CFileDialog fileDlg( FALSE, _T("txt"), _T("*.txt")); 
    
    	fileDlg.DoModal();	
    
    	CString Dateipfad = fileDlg.GetPathName(); 
    
    	CStdioFile Datei;		
    	CString Inhalt_Eingabefeld;		
    
    	Eingabefeld.GetWindowTextW(Inhalt_Eingabefeld); 
    
    	Datei.Open (Dateipfad, CFile::modeCreate | CFile::modeWrite); 
    
    	Datei.WriteString (Inhalt_Eingabefeld);	  
    
    	Datei.Close ();
    


  • na weil du einfach net alles gelesen hast, du mu8sst schon fragen ob der filedialog mit IDOK beendet wird und dann den restr aus führen, denn wenn nicht hast du keinen pfad und dir klatscht alles an die wand, aber das gehört zu den grundlagen, sauberes Abfragen von rückgabewerten.

    CFileDialog fileDlg( FALSE, _T("txt"), _T("*.txt"));
    
        if(fileDlg.DoModal() == IDOK)   
     {
        CString Dateipfad = fileDlg.GetPathName();
    
        CStdioFile Datei;       
        CString Inhalt_Eingabefeld;       
    
        Eingabefeld.GetWindowTextW(Inhalt_Eingabefeld);
    
        Datei.Open (Dateipfad, CFile::modeCreate | CFile::modeWrite);
    
        Datei.WriteString (Inhalt_Eingabefeld);     
    
        Datei.Close ();
    }
    

Anmelden zum Antworten