Вопрос

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

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

Это было полезно?

Решение

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");

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

Другие советы

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

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

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

@JKP:

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

Видеть здесь.Цитировать:

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top