Question

Je recherche l'équivalent de Windows _wfopen() sous Mac OS X.Une idée?

J'en ai besoin pour porter une bibliothèque Windows qui utilise wchar* pour son interface Fichier.Comme il s'agit d'une bibliothèque multiplateforme, je ne peux pas compter sur la façon dont l'application client obtiendra le chemin du fichier et le donnera à la bibliothèque.

Était-ce utile?

La solution

L'API POSIX sous Mac OS X est utilisable avec les chaînes UTF-8.Afin de convertir une chaîne wchar_t en UTF-8, il est possible d'utiliser le framework CoreFoundation de Mac OS X.

Voici une classe qui encapsulera une chaîne générée UTF-8 à partir d'une chaîne wchar_t.

class Utf8
{
public:
    Utf8(const wchar_t* wsz): m_utf8(NULL)
    {
        // OS X uses 32-bit wchar
        const int bytes = wcslen(wsz) * sizeof(wchar_t);
        // comp_bLittleEndian is in the lib I use in order to detect PowerPC/Intel
        CFStringEncoding encoding = comp_bLittleEndian ? kCFStringEncodingUTF32LE
                                                       : kCFStringEncodingUTF32BE;
        CFStringRef str = CFStringCreateWithBytesNoCopy(NULL, 
                                                       (const UInt8*)wsz, bytes, 
                                                        encoding, false, 
                                                        kCFAllocatorNull
                                                        );

        const int bytesUtf8 = CFStringGetMaximumSizeOfFileSystemRepresentation(str);
        m_utf8 = new char[bytesUtf8];
        CFStringGetFileSystemRepresentation(str, m_utf8, bytesUtf8);
        CFRelease(str);
    }   

    ~Utf8() 
    { 
        if( m_utf8 )
        {
            delete[] m_utf8;
        }
    }

public:
    operator const char*() const { return m_utf8; }

private:
    char* m_utf8;
};

Usage:

const wchar_t wsz = L"Here is some Unicode content: éà€œæ";
const Utf8 utf8 = wsz;
FILE* file = fopen(utf8, "r");

Cela fonctionnera pour lire ou écrire des fichiers.

Autres conseils

Vous souhaitez simplement ouvrir un descripteur de fichier en utilisant un chemin pouvant contenir des caractères Unicode, n'est-ce pas ?Il suffit de passer le chemin représentation du système de fichiers à fopen.

  • Si le chemin provient des frameworks Mac OS X d'origine (par exemple, un panneau ouvert, Carbon ou Cocoa), vous n'aurez pas besoin d'effectuer de conversion dessus et pourrez l'utiliser tel quel.

  • Si vous générez vous-même une partie du chemin, vous devez créer un CFStringRef à partir de votre chemin, puis l'obtenir dans la représentation du système de fichiers pour le transmettre aux API POSIX telles que open ou fopen.

D'une manière générale, vous n'aurez pas à faire beaucoup de choses pour la plupart des applications.Par exemple, de nombreuses applications peuvent avoir des fichiers de données auxiliaires stockés dans le répertoire Application Support de l'utilisateur, mais tant que les noms de ces fichiers sont ASCII et que vous utilisez les API standard de Mac OS X pour localiser le répertoire Application Support de l'utilisateur, vous n'avez pas besoin faire un tas de conversions paranoïaques d'un chemin construit avec ces deux composants.

Modifié pour ajouter : Je mettrais fortement en garde contre convertir arbitrairement tout en UTF-8 en utilisant quelque chose comme wcstombs car l'encodage du système de fichiers n'est pas nécessairement identique à l'UTF-8 généré.Mac OS X et Windows utilisent tous deux des règles de décomposition canoniques spécifiques (mais différentes) pour l'encodage utilisé dans les chemins du système de fichiers.

Par exemple, ils doivent décider si "é" sera stocké sous forme d'une ou deux unités de code (soit LATIN SMALL LETTER E WITH ACUTE ou LATIN SMALL LETTER E suivi de COMBINING ACUTE ACCENT).Cela entraînera deux séquences d'octets différentes – et de longueurs différentes – et Mac OS X et Windows évitent de placer plusieurs fichiers portant le même nom (tel que l'utilisateur les perçoit) dans le même répertoire.

Les règles sur la façon d'effectuer cette décomposition canonique peuvent devenir assez compliquées, donc plutôt que d'essayer de l'implémenter vous-même, il est préférable de laisser aux fonctions que les frameworks système vous ont fournies le soin de faire le gros du travail.

@JKP :

Toutes les fonctions de MacOS X n'acceptent pas UTF8, mais les noms de fichiers et les chemins de fichiers peuvent être UTF8, donc toutes les fonctions POSIX traitant de l'accès aux fichiers (open, fopen, stat, etc.) acceptent UTF8.

Voir ici.Citation:

À l'approche d'un nom de fichier au niveau de l'API dépend de l'API.Les noms de fichiers de carbone API actuels comme un tableau de caractères UTF-16;Les POSIX les gèrent comme un tableau d'UTF-8, c'est pourquoi UTF-8 fonctionne bien dans le terminal.La façon dont elle est stockée sur le disque dépend du format de disque;HFS + utilise UTF-16, mais ce n'est pas important dans la plupart des cas.

Certaines autres fonctions POSIX gèrent également UTF8.Par exemple.les fonctions traitant des noms d'utilisateur, des noms de groupe ou des mots de passe utilisateur utilisent UTF8 pour stocker les informations (ainsi un nom d'utilisateur peut être japonais et votre mot de passe peut être chinois, pas de problème).

Mais tous ne gèrent pas UTF8.Par exemple.pour toutes les fonctions de chaîne, une chaîne UTF8 n'est qu'une chaîne C normale et les caractères supérieurs à 126 n'ont aucune signification particulière.Ils ne comprennent pas le concept de plusieurs octets (caractères en C) formant un seul caractère Unicode.La façon dont les autres API gèrent le pointeur char * qui leur est transmis est différente d'une API à l'autre.Cependant, en règle générale, vous pouvez dire avec le pouce :

Soit la fonction n'accepte que les chaînes C avec des caractères ASCII purs (uniquement compris entre 0 et 126), soit elle acceptera UTF8.Habituellement, les fonctions n'autorisent pas les caractères supérieurs à 126 et les interprètent dans un autre codage que UTF8.Si tel était réellement le cas, cela est documenté et il doit alors y avoir un moyen de transmettre l'encodage avec la chaîne.

Si vous utilisez Cocoa, c'est assez simple avec NSString.Chargez simplement les données UTF16 en utilisant -initWithBytes:length:encoding :(ou peut-être -initWithCString:encoding:) puis obtenez une version UTF8 en appelant UTF8String sur le résultat.Ensuite, appelez simplement fopen avec votre nouvelle chaîne UTF8 comme paramètre.

Vous pouvez certainement appeler fopen avec une chaîne UTF-8, quelle que soit la langue - mais je ne peux pas vous aider avec C++ sur OSX - désolé.

J'ai lu le nom du fichier à partir du fichier de configuration UTF8 via wifstream (il utilise wchar_t tampon).

L'implémentation Mac est différente de Linux et Windows.wifstream lit chaque octet du fichier pour séparer la cellule wchar_t dans le tampon.Nous avons donc 3 octets vides, même si ouvrir a besoin carboniser chaîne.Ainsi, le programmeur peut utiliser toilettes fonction pour convertir une chaîne de caractères large en chaîne multi-octets.

L'API prend en charge UTF8.Pour une meilleure compréhension, utilisez Memory Watcher et l'éditeur hexadécimal pour votre fichier.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top