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

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

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

15.08.2008 14:59:11
5 ОТВЕТОВ

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

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

0
15.08.2008 15:38:05
Я не использую Какао и использую C ++, а не Objective-C. Если вы правы относительно предоставления строки UTF-8 функции fopen (), я мог бы преобразовать строку UTF-16 в UTF-8, но как это легко сделать в Mac OS X (опять же с использованием C / C ++).
Vincent Robert 17.09.2008 09:20:11
Не окончательный ответ, так как я полагаюсь на CFString вместо NSString, но основная идея та же. Спасибо.
Vincent Robert 21.01.2009 17:37:14

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

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

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

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

5
17.08.2008 08:51:44
Для тех, кто хочет попробовать это в коде, en.wikipedia.org/wiki/Unicode_equivalence#Example показывает два способа (разные коды символов) написания «é». Они будут выглядеть равными в файловых менеджерах Linux, которые показывают Unicode, когда обычно два файла с одинаковым именем не допускаются. Например, touch $'file-\u00e9' $'file-\u0065\u0301'в bashпокажут в ls: file-é file-é.
nh2 20.03.2018 15:10:54

@JKP:

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

Смотрите здесь . Quote:

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

2
2.10.2008 11:24:19
РЕШЕНИЕ

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

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

14
5.11.2008 15:07:26
если удаление избыточно, просто удалите
paulm 22.11.2016 18:02:33

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

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

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

0
27.12.2013 11:46:16