Dateinamen und Zeichensatz



  • Tag zusammen,
    ich habe ein kleines Programm, welches unter anderem Dateinamen aus einer Textdatei auslesen und anschließend prüfen soll, ob diese vorhanden sind oder nicht. Sobald ich Sonderzeichen in den Dateinamen habe klappt das jedoch nicht mehr, was wohl daran liegt, dass ich von Zeichensätzen nicht viel Ahnung habe.
    Was mache ich?
    Ich lese eine komplette Verzeichnissstruktur rekursiv mit readdir() ein:

    DIR *dir;
    struct dirent *de;
    
    dir = opendir("/foo");
    while ( de = readdir(dir)!=NULL)
      ...
    

    und speichere das alles in einer Baumstruktur. Irgendwann später lese ich dann die Datei ein:

    FILE fp;
    char sz[1024];
    fp = fopen("filter.txt","r");
    while (fgets(sz,1024,fp)
    //... mit vorher eingelesenen Dateien vergleichen
    

    und suche nach den Einträgen in dem Baum.

    Zugegeben etwas umständlich. Wenn ich nur prüfen wollte ob die Datei vorhanden ist bräuchte ich hierfür nicht readdir(). Wäre schön, wenn ihr euch daran nicht stört 🙂
    Dateinamen mit einem Sonderzeichen (wie z.B. 'ä') die ich mit readdir() ermittelt habe enthalten statt des Sonderzeichens bei der Ausgabe über die Konsole nur ein Quadrat. Beim einlesen der Textdatei werden die Dateinamen auf der Konsole richtig ausgegeben.

    Wie kriege ich nun diese beiden wohl unterschiedlichen Zeichensätze zusammen? Wäre nett, wenn mir da jemand helfen könnte.

    Bei dem zugrunde liegenden System handelt es sich im Übrigen um Mac OS 10.7, sollte aber generell auf Unix-Systemen funktionieren.

    Grüße
    Chris



  • Chris_78 schrieb:

    Bei dem zugrunde liegenden System handelt es sich im Übrigen um Mac OS 10.7, sollte aber generell auf Unix-Systemen funktionieren.

    Ein Glück, dass du das sagst, das ist hier nämlich relevant. Unter Linux funktioniert es nämlich tatsächlich einfach so.

    Das Dateisystem HFS+ auf Mac OS X speichert Dateinamen immer in Unicode und normalisiert diese dabei sogar. Deswegen ist ein Vergleichen von Dateinamen mit Einträgen einer Textdatei eine enorm lästige Angelegenheit, falls du nicht einfach Byte-Vergleiche machst und sagst "die sind nicht identisch".

    Im Prinzip musst du erstmal rausfinden in welchem Encoding dir readdir unter Mac OS X für HFS+ die Namen liefert. Das sollte mit google recht schnell gehen. Wahrscheinlich wird es utf8 sein, weil heute im Prinzip niemand mehr eine locale ohne utf8 verwendet.

    Dann musst du irgendeine unicode-Bibliothek einbinden, damit du die Namen mit den Einträgen deiner Textdatei vergleichen kannst. Denn dafür brauchst du Unicode-Normalisierung, und das ist etwas, was man wirklich nicht selbst implementieren möchte.



  • Ok, folgendes habe ich mittlerweile rausgefunden:
    Der Dateiname den ich durch readdir() bekomme, und der Dateiname aus der Textdatei sind beide in UTF-8 kodiert. Anscheinend gibt es jedoch auch bei UTF-8 verschiedene Codierungen. MacOS liefert über readdir() wohl den Namen in NFD-Form, während ich ihn in der NFC-Form benötige.
    Für die Konvertierung habe ich die libicu gefunden. unorm_normalize() sollte wohl das machen was ich will. Also die lib installiert, header eingebunden und die Funktion aufgerufen. Dummerweise habe ich Probleme beim linken:

    Undefined symbols for architecture x86_64:
      "_unorm_normalize_48", referenced from:
          _ScanDir in cccoFBx4.o
    ld: symbol(s) not found for architecture x86_64
    collect2: ld returned 1 exit status
    

    gut, ich sollte gcc vielleicht auch sagen, welche lib er einbinden soll. Aber wie? -licu oder -libicu funktioniert leider nicht, da er die bibliotheken nicht findet. Wie komme ich an den richtigen Namen der Bibliothek, den ich übergeben muss? Oder renne ich gerade in die völlig falsche Richtung?


Anmelden zum Antworten