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

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
 
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:
void __fastcall TForm1::Oeffnen1Click(TObject *Sender)
{
	TFileStream *Streamer;
    TReader* rd;

    if(OpenTextFileDialog1->Execute())
    {
    	Streamer = new TFileStream(OpenTextFileDialog1->FileName, fmOpenRead);

    	try
        {
            rd = new TReader(Streamer, 100);

            rd->ReadListBegin();
            this->Memo1->Text = rd->ReadString();
            rd->ReadListEnd();
        }
        __finally
		{
        	delete Streamer;
            delete rd;
		}
    }
}

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:
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:
void __fastcall TForm1::Oeffnen1Click(TObject *Sender)
{
	TFileStream *Streamer;
    char a[100];

    if(OpenTextFileDialog1->Execute())
    {
    	Streamer = new TFileStream(OpenTextFileDialog1->FileName, fmOpenRead);

    	try
        {
            Streamer->ReadBuffer(&a, 100);
            this->Memo1->Text = UTF8ToUnicodeString(a);
        }
        __finally
		{
        	delete Streamer;
		}
    }
}
 
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.
 
Wenn es nicht unbedingt TFileStream sein muss, dann versuch mal folgendes:

Code:
TStringList* sList = new TStringList;
String FileName = "C:\test.txt";      // oder was auch immer
sList->LoadFromFile(FileName , TEncoding::UTF8);

grüssle :)
 
Wenn es nicht unbedingt TFileStream sein muss...

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)
 
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.

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:
TStringList* sList = new TStringList;
String FileName = "C:\test.txt";      // oder was auch immer
sList->LoadFromFile(FileName , TEncoding::UTF8);

for( int i = 0; i < sList->Items->Count; i++ )
{
    Memo1->Lines->Add( sList->Strings[i] );
   // do something ...
}

// oder:
Edit1->Text = sList->Strings[15];

// oder ...

// und speichern:
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 :)
 
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.
 
ah super :) vielen dank.
... den member "items" gibt es beim c++ builder 2010 nicht, ...

stimmt, sollte:

Code:
for( int i = 0; i <sList->Count; i++ )    
{
    Memo1->Lines->Add( sList->Strings[i] );
   // do something ...
}
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 :)
 
Zurück