1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Textdatei (utf-8) einlesen, probleme mit vcl komponenten

Dieses Thema im Forum "Borland CBuilder und VCL" wurde erstellt von xFile, 19. Januar 2011.

  1. xFile

    xFile Mitglied

    hallo,

    ich arbeite mit dem c++ builder 2010 und möchte (muss) eine utf-8 kodierte datei einlesen.
    habe schon mehrere stunden damit verbracht etwas zu finden was mich weiterbringt, hoffe ihr könnt mir helfen.

    der vorgang ist recht einfach: menü -> datei öffnen -> datei auswählen ... nun befinde ich mich in meiner funktion TForm1::Oeffnen(TObject *Sender).

    ich habe nun schon versucht die datei mit TFileStream einzulesen und den inhalt dann einer textbox / memobox zuzuweisen, funktioniert jedoch nicht.
    ziel ist es, den inhalt zb in einer TEdit oder Memo box anzeigen zu lassen.

    weiterhin habe ich dann die datei mit den win32 funktionen eingelsen, inhalt liegt nun als char string vor (mehre bytes entsprechen halt einem zeichen), jedoch bekomme ich die nicht nach unicodestring konvertiert um diese dann einer komponente der vcl zuzuweisen.

    danke euch schon mal!

    gruß adam
     
  2. ComFreek

    ComFreek Mod | @comfreek Moderator

    Zeig doch den Code mit TFileStream, damit müsste es doch klappen.
     
  3. xFile

    xFile Mitglied

    der folgende code wirft eine Exception der Klasse EReadError: "Ungültiger Eigenschatfwert".
    Lasse ich den TReader weg und versuche es nur mit dem FileStream, dann weis ich nicht wie ich das in die Eigenschaft "Text" meiner Komponente bekommen soll.

    Code (Text):
    1. void __fastcall TForm1::Oeffnen1Click(TObject *Sender)
    2. {
    3.     TFileStream *Streamer;
    4.     TReader* rd;
    5.  
    6.     if(OpenTextFileDialog1->Execute())
    7.     {
    8.         Streamer = new TFileStream(OpenTextFileDialog1->FileName, fmOpenRead);
    9.  
    10.         try
    11.         {
    12.             rd = new TReader(Streamer, 100);
    13.  
    14.             rd->ReadListBegin();
    15.             this->Memo1->Text = rd->ReadString();
    16.             rd->ReadListEnd();
    17.         }
    18.         __finally
    19.         {
    20.             delete Streamer;
    21.             delete rd;
    22.         }
    23.     }
    24. }
    bzw. wie bekomme ich es hin, dass ich überhaupt eine Textdatei einlesen kann (mit den Borland Klassen)?
    Im o.g. Code funktioniert ja dies noch nicht einmal. Es gibt zwar die Möglichkeit den Inhalt einer Komponente direkt abzuspeichern, jedoch sind dann darin auch "Steuerzeichen / Informationen" enthalten. Ich muss eine Textdatei einlesen die ein Menüaufbau repräsentiert (ähnlich XML).
     
    Zuletzt bearbeitet: 20. Januar 2011
  4. xFile

    xFile Mitglied

    habe es nun irgendwie hinbekommen, ob diese Lösung schön ist, kann ich nicht beurteilen.
    Nun muss ich nur noch die ersten 3 Byte überspringen, denn da steht das Byte Order Mark.
    Falls ihr Änderungsvorschläge habt, wäre ich dankbar.

    Code (Text):
    1. void __fastcall TForm1::Oeffnen1Click(TObject *Sender)
    2. {
    3.     TFileStream *Streamer;
    4.     char a[100];
    5.  
    6.     if(OpenTextFileDialog1->Execute())
    7.     {
    8.         Streamer = new TFileStream(OpenTextFileDialog1->FileName, fmOpenRead);
    9.  
    10.         try
    11.         {
    12.             Streamer->ReadBuffer(&a, 100);
    13.             this->Memo1->Text = UTF8ToUnicodeString(a);
    14.         }
    15.         __finally
    16.         {
    17.             delete Streamer;
    18.         }
    19.     }
    20. }
     
  5. ComFreek

    ComFreek Mod | @comfreek Moderator

    Naja du kannst mit deiner Lösung nur 100 Zeichen einlesen.
    Ich würde zuerst auf ByteOrderMark (BOM) prüfen. Wenn es diese gibt entweder diese wegschneiden oder den Rest in eine andere Variable schreiben.
    Ich kenne mich leider nur ansatzweise in BCB 6 aus (nutze ihn aber auch nicht mehr), deshalb kann ich dir nur einen Ansatz verraten.
     
  6. GillBates

    GillBates Mitglied

    Wenn es nicht unbedingt TFileStream sein muss, dann versuch mal folgendes:

    Code (Text):
    1. TStringList* sList = new TStringList;
    2. String FileName = "C:\test.txt";      // oder was auch immer
    3. sList->LoadFromFile(FileName , TEncoding::UTF8);
    grüssle :)
     
  7. xFile

    xFile Mitglied

    hey,
    was benutzt du den grundsätzlich? hatte das auch mal mit StringList ausprobiert, aber habe dafür nur bsp. gefunden die direkt in eine komponente einlesen.

    gruß
    adam

    (mittlerweile funktioniert das einlesen bei mir mit filestream und auch das prüfen auf ByteOrderMark ist schon fertig)
     
  8. GillBates

    GillBates Mitglied

    Wenn möglich nutze ich TStringList. Ist einfach am bequemsten.
    Und TStringList hat rein gar nichts mit Komponenten zu tun. Ist nur ein Abbild der Datei im Speicher.
    Eben ein Array von Strings. Was du dann damit anstellt bleibt dir überlassen.

    Beispiel( Erweiterung meones Vorschlags ):

    Code (Text):
    1. TStringList* sList = new TStringList;
    2. String FileName = "C:\test.txt";      // oder was auch immer
    3. sList->LoadFromFile(FileName , TEncoding::UTF8);
    4.  
    5. for( int i = 0; i < sList->Items->Count; i++ )
    6. {
    7.     Memo1->Lines->Add( sList->Strings[i] );
    8.    // do something ...
    9. }
    10.  
    11. // oder:
    12. Edit1->Text = sList->Strings[15];
    13.  
    14. // oder ...
    15.  
    16. // und speichern:
    17. sList->SaveToFile(FileName , TEncoding::UTF8);
    mal so aus der Hüfte geschossen ;)


    Einfach mal die Online Hilfe, die SuFu hier, Google, ... bemühen. Lohnt sich.


    grüssle :)
     
  9. xFile

    xFile Mitglied

    ah super :) vielen dank.
    hast recht, damit ist es wirklich einfacher! den member "items" gibt es beim c++ builder 2010 nicht, aber habe das nun über "capacity" gelöst.
    er liest die strings (ein string = eine zeile) zwar von hinten nach vorne in der datei, aber das ist kein problem.

    problem hier ist nun folgendes: überprüfung auf gültige utf-8 datei mit BOM. habe das sonst so gemacht, dass ich die ersten 3 zeichen eingelesen habe um erstmal zu prüfen ob BOM vorhanden. bei stringlist schneidet er die ja direkt ab und decodiert die datei.
    soll ich dann jetzt trotzdem meine überprüfung weiterhin nutzen und danach mit stringlist arbeiten? dann würde ich aber einmal mit streamfile und dann zusätzlich mit stringlist arbeiten.
     
  10. GillBates

    GillBates Mitglied

    stimmt, sollte:

    Code (Text):
    1. for( int i = 0; i <sList->Count; i++ )    
    2. {
    3.     Memo1->Lines->Add( sList->Strings[i] );
    4.    // do something ...
    5. }
    heissen.

    Und für die Prüfung der BOM gibts zwar bestimmt elegantere Lösungen, aber wenns funktioniert dann ist das Ziel wohl erreicht.


    grüssle :)
     
Die Seite wird geladen...