_wfopen эквивалент под Mac OS X - PullRequest
16 голосов
/ 15 августа 2008

Я ищу эквивалент Windows _wfopen() под Mac OS X. Есть идеи?

Мне это нужно для портирования библиотеки Windows, которая использует wchar* для своего интерфейса File. Поскольку это межплатформенная библиотека, я не могу полагаться на то, как клиентское приложение получит путь к файлу и передаст его библиотеке.

Ответы [ 5 ]

14 голосов
/ 05 ноября 2008

POSIX API в Mac OS X можно использовать со строками UTF-8. Чтобы преобразовать строку wchar_t в UTF-8, можно использовать инфраструктуру CoreFoundation из Mac OS X.

Вот класс, который обернет сгенерированную UTF-8 строку из строки 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;
};

Использование:

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

Это будет работать для чтения или записи файлов.

5 голосов
/ 17 августа 2008

Вы просто хотите открыть дескриптор файла, используя путь, который может содержать символы Unicode, верно? Просто передайте путь в представлении файловой системы в fopen.

  • Если путь взят из стандартных платформ Mac OS X (например, панели Open, Carbon или Cocoa), вам не нужно будет выполнять какие-либо преобразования для нее, и вы сможете использовать ее как есть.

  • Если вы сами генерируете часть пути, вы должны создать CFStringRef из вашего пути и затем получить его в представлении файловой системы для передачи в API POSIX, такие как open или fopen.

Вообще говоря, вам не придется делать много этого для большинства приложений. Например, во многих приложениях файлы вспомогательных данных могут храниться в каталоге поддержки приложений пользователя, но если имена этих файлов являются ASCII, и вы используете стандартные API Mac OS X для поиска каталога поддержки приложений пользователя, вам не нужно сделать параноидальное преобразование пути, построенного с этими двумя компонентами.

Отредактировано, чтобы добавить: Я настоятельно рекомендую против произвольно преобразовывать все в UTF-8, используя что-то вроде wcstombs, потому что кодировка файловой системы не обязательно идентична сгенерированному UTF-8 , Mac OS X и Windows используют определенные (но разные) канонические правила декомпозиции для кодировки, используемой в путях файловой системы.

Например, им нужно решить, будет ли «é» сохраняться в виде одной или двух кодовых единиц (либо LATIN SMALL LETTER E WITH ACUTE, либо LATIN SMALL LETTER E, за которыми следует COMBINING ACUTE ACCENT). Это приведет к двум разным (и разной длине) байтовым последовательностям, и Mac OS X и Windows будут работать над тем, чтобы не помещать несколько файлов с одним и тем же именем (как их воспринимает пользователь) в один и тот же каталог.

Правила того, как выполнять эту каноническую декомпозицию, могут быть довольно сложными, поэтому вместо того, чтобы пытаться реализовать их самостоятельно, лучше оставить для функций, которые системные платформы предоставили вам для выполнения тяжелой работы.

2 голосов
/ 02 октября 2008

@ JKP:

Не все функции в MacOS X поддерживают UTF8, но имена файлов и пути к файлам могут быть UTF8, поэтому все функции POSIX, касающиеся доступа к файлам (open, fopen, stat и т. Д.), Принимают UTF8.

См. здесь . Цитата:

Как выглядит имя файла на уровне API зависит от API. Текущий углерод API обрабатывают имена файлов как массив Символы UTF-16; Ручка POSIX их как массив UTF-8, который является почему UTF-8 хорошо работает в терминале. Как он хранится на диске зависит от формат диска; HFS + использует UTF-16, но это не важно в большинстве случаев.

Некоторые другие функции POSIX также поддерживают UTF8. Например. функции, связанные с именами пользователей, именами групп или паролями пользователей, используют UTF8 для хранения информации (таким образом, имя пользователя может быть японским, а ваш пароль - китайским, нет проблем).

Но не все справляются с UTF8. Например. для всех строковых функций строка UTF8 - это просто обычная строка C, а символы выше 126 не имеют специального значения. Они не понимают концепцию нескольких байтов (символов в C), образующих один символ Unicode. То, как другие API обрабатывают передаваемый им указатель char *, отличается от API к API. Однако, как правило, большим пальцем можно сказать:

Либо функция принимает только строки C с чистыми символами ASCII (только в диапазоне от 0 до 126), либо она принимает UTF8. Обычно функции не допускают символы выше 126 и интерпретируют их в любой другой кодировке, кроме UTF8. Если это действительно так, то это задокументировано, и тогда должен быть способ передать кодировку вместе со строкой.

0 голосов
/ 27 декабря 2013

Я прочитал имя файла из файла конфигурации UTF8 через wifstream (используется буфер wchar_t ).

Реализация Mac отличается от Linux и Windows. wifstream читает каждый байт из файла в отдельную ячейку wchar_t в буфере. Таким образом, у нас есть 3 пустых байта, хотя open требует char string. Таким образом, программист может использовать функцию wcstombs для преобразования строки широких символов в многобайтовую строку.

API поддерживает UTF8. Для лучшего понимания используйте память наблюдателя и hex-редактор для вашего файла.

0 голосов
/ 15 августа 2008

Если вы используете Какао, это довольно просто с NSString. Просто загрузите данные UTF16, используя -initWithBytes: length: encoding: (или, возможно, -initWithCString: encoding :), а затем получите версию UTF8, вызвав UTF8String для результата. Затем просто вызовите fopen с новой строкой UTF8 в качестве параметра.

Определенно, вы можете вызывать fopen со строкой UTF-8, независимо от языка, но не можете помочь с C ++ в OSX - извините.

...