Подтвердить что ты не робот

_wfopen эквивалент в Mac OS X

Я ищу эквивалент Windows _wfopen() в Mac OS X. Любая идея?

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

4b9b3361

Ответ 1

API POSIX в 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");

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

Ответ 2

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

  • Если путь исходил из фреймворков Mac OS X (например, Open Panel, будь то 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, чтобы не помещать несколько файлов с тем же именем (как пользователь их воспринимает) в том же каталоге.

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

Ответ 3

@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. Если это действительно так, оно задокументировано, и тогда должен быть способ передать кодировку вместе со строкой.

Ответ 4

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

Вы можете определенно вызвать fopen с помощью строки UTF-8, независимо от языка - не могу помочь с С++ на OSX, хотя - извините.

Ответ 5

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

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

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