Пути Unicode с MATLAB

Учитывая следующий код, который пытается создать 2 папки в текущем пути MATLAB:

%%
u_path1 = native2unicode([107, 97, 116, 111, 95, 111, 117, 116, 111, 117], 'UTF-8');  % 'kato_outou'
u_path2 = native2unicode([233 129 142, 230 184 161, 229 191 156, 231 173 148], 'UTF-8');  % '過渡応答'

mkdir(u_path1);
mkdir(u_path2);

первый вызов mkdir завершается успешно, а второй терпит неудачу, при этом появляется сообщение об ошибке "Имя файла, имя каталога или синтаксис метки тома". Однако создание папок вручную на панели "Текущая папка" ([правый клик] и rArr; New Folder → [имя пасты]) не вызывает проблем. Такие сбои появляются в большинстве низкоуровневых функций ввода/вывода MATLAB (dir, fopen, copyfile, movefile и т.д.), И я хотел бы использовать все эти функции.

Среда:

  • Win7 Enterprise (32 бит, NTFS)
  • MATLAB R2012a

Таким образом, файловая система поддерживает символы Unicode в пути, а MATLAB может хранить истинные строки Unicode (а не "подделывать" их).

Официальная документация mkdir элегантно {1} устраняет проблему, заявив, что правильный синтаксис для вызова функции:

mkdir('folderName')

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

Интересно, есть ли способ обойти эти ограничения. Меня бы интересовали решения, которые:

  • не полагаются на недокументированные/неподдерживаемые материалы MATLAB;

  • не связаны с общесистемными изменениями (например, с изменением информации локали операционной системы);

  • может в конечном итоге полагаться на не-родные библиотеки MATLAB, так как полученные обработчики/объекты могут быть преобразованы в собственные объекты MATLAB и управляются как таковые;

  • может в конечном итоге полагаться на манипуляции с путями, которые могли бы сделать их пригодными для использования стандартными функциями MATLAB, даже если Windows специфична (например, пути с короткими именами).

Позже отредактируйте

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

function  listing = dir(folder);
function  [status,message,messageid] = mkdir(folder1,folder2);
function  [status,message,messageid] = movefile(source,destination,flag);
function  [status,message,messageid] = copyfile(source,destination,flag);
function  [fileID, message] = fopen(filename, permission, machineformat, encoding);
function  status = fclose(fileID);
function  [A, count] = fread(fileID, sizeA, precision, skip, machineformat);
function  count = fwrite(fileID, A, precision, skip, machineformat);
function  status = feof(fileID);
function  status = fseek(fileID, offset, origin);
function  [C,position] = textscan(fileID, varargin);  %'This one is going to be funny'

Не все типы вывода должны быть взаимозаменяемы с оригинальными функциями MATLAB, однако должны быть согласованы между вызовами функций (например, fileID между fopen и fclose). Я собираюсь обновить этот список объявлений с помощью реализаций, как только я их получу/напишу.


{1} для очень свободных значений слова "элегантный".

Ответ 1

Некоторая полезная информация о том, как MATLAB обрабатывает имена файлов (и символы в целом), доступна в комментариях это сообщение недокументированногоMatlab (тем более Стив Эддинс, который работает в MathWorks). Короче:

"MathWorks начала конвертировать всю обработку строк в базу кода MATLAB в UTF-16.... и мы приблизились к ней пошагово"

- Стив Эддинс, декабрь 2014 года.

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

Ниже приведен список функций, которые были протестированы пользователями на разных платформах в соответствии с функциональными возможностями, которые были запрошены в вопросе:

  • Следующая команда создает каталог с символами UTF16 в своем имени ( "תיקיה" на иврите в этом примере) из MATLAB:

    java.io.File(fullfile(pwd,native2unicode(...
              [255 254 234 5 217 5 231 5 217 5 212 5],'UTF-16'))).mkdir();
    

    Протестировано:

    • Windows 7 с MATLAB R2015a Dev-iL
    • OSX Yosemite (10.10.4) с MATLAB R2014b Matt
  • Следующие команды также, похоже, успешно создают каталоги:

    mkdir(native2unicode([255 254 234 5 217 5 231 5 217 5 212 5],'utf-16'));
    mkdir(native2unicode([215,170,215,153,215,167,215,153,215,148],'utf-8'));
    

    Протестировано:

    • Windows 10 с MATLAB R2015a с feature('DefaultCharacterSet') = > windows-1255 на Dev-iL
    • OSX Yosemite (10.10.4) с MATLAB R2014b Matt
      Значение feature('DefaultCharacterSet') здесь не влияет, потому что кодировка явно определена в команде native2unicode.
  • Следующие команды успешно открывают файл с символами Unicode как по своему имени, так и по содержанию:

    fid = fopen([native2unicode([255,254,231,5,213,5,209,5,229,5],'utf-16') '.txt']);
    txt =  textscan(fid,'%s');
    

    Протестировано:

    • Windows 10 с MATLAB R2015a с feature('DefaultCharacterSet') = > windows-1255 на Dev-iL. Примечание. Отсканированный текст отображается правильно в представлении "Переменные". Текстовый файл можно редактировать и сохранять из редактора MATLAB с символами UTF.
    • OSX Yosemite (10.10.4) с MATLAB R2014b Matt
      Если для textscan feature('DefaultCharacterSet') установлено значение utf-8, вывод celldisp(txt) отображается правильно. То же самое относится к представлению "Переменные".

Ответ 2

Попробуйте использовать UTF-16, если вы находитесь в Windows, потому что NTFS использует UTF-16 для кодирования имени файла, а Windows имеет два набора API-интерфейсов: те, которые работают с так называемыми "Windows Codepages" (1250, 1251, 1252 и т.д.). ) и используйте тип данных C char и те, которые используют wchar_t. Последний тип имеет размер 2 байта в Windows, которого достаточно для хранения кодовых блоков UTF-16.

Причина, по которой ваш первый вызов работал, состоит в том, что первые 128 кодовых точек в стандарте Unicode кодируются в UTF-8 идентично 128 символам ASCII (что сделано специально для обратной совместимости). UTF-8 использует 1-байтовые кодовые единицы (вместо 2-байтовых кодовых блоков для UTF-16), и обычно программное обеспечение, такое как MATLAB, не обрабатывает имена файлов, поэтому им нужно просто хранить байтовые последовательности и передавать их в OS API. Второй вызов завершился неудачно, поскольку байтовые последовательности UTF-8, представляющие кодовые точки, вероятно, отфильтрованы Windows, потому что некоторые байтовые значения запрещены в именах файлов. В совместимых с POSIX операционных системах большинство API-интерфейсов являются байт-ориентированными, а стандартный почти не позволяет использовать существующие многобайтовые кодировки в API (например, UTF -16, UTF-32), и вы должны использовать API char* и кодировки с 1-байтовыми кодовыми единицами:

POSIX.1-2008 помещает только следующие требования к закодированному значения символов в переносном наборе символов:

...

  • Закодированные значения, связанные с и должны быть инвариантными по всем локалям, поддерживаемым реализацией.
  • Закодированные значения, связанные с элементами переносимого набора символов, представлены в одиночном байте. Более того, если значение сохраняется в объекте типа C-типа char, он гарантированно будет положительным (кроме NUL, который всегда равен нулю).

Не все совместимые с POSIX операционные системы проверяют имена файлов, отличные от периода или слэша, поэтому вы можете хранить мусор в именах файлов. Mac OS X, как система POSIX, использует байт-ориентированные (char*) API, но базовый HFS + использует UTF-16 в NFD (форма нормализации D), поэтому некоторая обработка выполняется на уровне ОС перед сохранением имени файла.

Windows не выполняет какой-либо нормализации Unicode и сохраняет имена файлов в любой форме, которую они передают в UTF-16 (при использовании NTFS) или Windows Codepages (не уверен, как они справляются с этим на уровне файловой системы - возможно, путем преобразования).

Итак, как это относится к MATLAB? Ну, это кросс-платформенный и из-за этого приходится иметь дело со многими проблемами. Один из них заключается в том, что Windows имеет char API для Windows Codepages и некоторых запрещенных символов в именах файлов, в то время как другие операционные системы этого не делают. Они могли бы выполнять зависящие от системы проверки, но это было бы намного сложнее протестировать и поддержать (много ошибок, которые я думаю).

Лучше всего использовать UTF-16 для Windows, реализовать проверки на платформе или использовать ASCII, если вам нужна переносимость.