12 unicode matlab low-level-io
鉴于以下代码尝试在当前MATLAB路径中创建2个文件夹:
%%
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);
Run Code Online (Sandbox Code Playgroud)
第一个mkdir调用成功而第二个调用失败,错误消息"文件名,目录名称或卷标语法不正确".但是,在"当前文件夹"GUI面板中手动创建文件夹([右键单击]⇒新文件夹⇒[粘贴名称])遇到没有问题.这种故障的出现在最MATLAB的低级别的I/O功能(中dir,fopen,copyfile,movefile等),我想使用所有这些功能.
环境是:
因此文件系统支持路径中的Unicode字符,MATLAB可以存储真正的Unicode字符串(而不是"假"它们).
优雅{1}的mkdir 官方文档通过声明调用该函数的正确语法来避免该问题:
mkdir('folderName')
Run Code Online (Sandbox Code Playgroud)
这表明该函数唯一官方支持的调用是使用字符串文字作为文件夹名称参数而不是字符串变量的调用.这也表明了eval我正在测试的方式,看看它是否像我写这篇文章一样有效.
我想知道是否有办法规避这些限制.我会对以下解决方案感兴趣:
不依赖于未记录/不支持的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'
Run Code Online (Sandbox Code Playgroud)
并非所有输出类型都需要与原始MATLAB函数互换,但需要在函数调用fileID之间保持一致(例如,在fopen和之间fclose).我会在获取/写入它们后立即更新此声明列表.
{1}对于"优雅"这个词的含义非常宽松.
如果您使用的是 Windows,请尝试使用 UTF-16,因为 NTFS 使用 UTF-16 进行文件名编码,并且 Windows 有两组 API:与所谓的“Windows 代码页”(1250、1251、1252 等)配合使用的 API 和使用C 的char数据类型和使用wchar_t. 后一种类型在 Windows 上的大小为 2 个字节,足以存储 UTF-16 代码单元。
您的第一次调用成功的原因是 Unicode 标准中的前 128 个代码点以 UTF-8 编码,与 128 个 ASCII 字符相同(这是为了向后兼容而设计的)。UTF-8 使用 1 字节代码单元(而不是 UTF-16 的 2 字节代码单元),并且通常 MATLAB 等软件不处理文件名,因此它们只需存储字节序列并将其传递给操作系统 API。第二次调用失败,因为表示代码点的 UTF-8 字节序列可能被 Windows 过滤掉,因为文件名中禁止使用某些字节值。在符合 POSIX 的操作系统上,大多数 API 都是面向字节的,并且该标准几乎阻止您在 API 中使用现有的多字节编码(例如 UTF-16、UTF-32),并且您必须使用char*1 字节的 API 和编码代码单位:
POSIX.1-2008 对可移植字符集中字符的编码值仅提出以下要求:
...
- 与 和 关联的编码值在实现支持的所有区域设置中应保持不变。
- 与可移植字符集的成员相关联的编码值均以单个字节表示。此外,如果该值存储在 C 语言类型 char 的对象中,则保证为正(NUL 除外,它始终为零)。
并非所有符合 POSIX 的操作系统都会验证除句点或斜杠之外的文件名,因此您几乎可以在文件名中存储垃圾。Mac OS X 作为 POSIX 系统,使用面向字节的 ( char*) API,但底层 HFS+在NFD (标准化形式 D)中使用UTF-16 ,因此在保存文件名之前会在操作系统级别完成一些处理。
Windows 不执行任何类型的 Unicode 规范化,并以 UTF-16(假设使用 NTFS)或 Windows 代码页(不知道它们如何在文件系统级别处理此问题 - 可能通过转换)中传递的任何形式存储文件名。
那么,这与 MATLAB 有什么关系呢?它是跨平台的,因此必须处理许多问题。其中之一是 Windows 具有char用于 Windows 代码页和文件名中某些禁止字符的 API,而其他操作系统则没有。他们可以实现依赖于系统的检查,但这会更难以测试和支持(我猜需要大量代码改动)。
我最好的建议是在 Windows 上使用 UTF-16,实施平台相关的检查,或者如果需要可移植性则使用 ASCII。