Пути 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, если вам нужна переносимость.