- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
如何通过 MATLAB 引擎或 MEX C 接口(interface)访问 MATLAB 字符串的底层 unicode 数据?
这是一个例子。我们把unicode字符放在一个UTF-8编码的文件test.txt中,然后读取为
fid=fopen('test.txt','r','l','UTF-8');
s=fscanf(fid, '%s')
在 MATLAB 中。
现在,如果我首先执行 feature('DefaultCharacterSet', 'UTF-8')
,然后从 C engEvalString(ep, "s")
,然后作为输出我从文件中取回 UTF-8 格式的文本。这证明 MATLAB 在内部将其存储为 unicode。但是,如果我执行 mxArrayToString(engGetVariable(ep, "s"))
,我会得到 unicode2native(s, 'Latin-1')
在 MATLAB 中给我的结果:所有非拉丁 1 字符替换为字符代码 26。我需要的是以任何 unicode 格式(UTF-8、UTF-16 等)访问底层 unicode 数据作为 C 字符串,并保留非拉丁字符-1 个字符。 这可能吗?
我的平台是 OS X,MATLAB R2012b。
附录:documentation明确指出“[mxArrayToString()] 支持多字节编码字符”,但它仍然只给我原始数据的 Latin-1 近似值。
最佳答案
首先,让我分享一些我在网上找到的引用资料:
根据 mxChar
描述,
MATLAB stores characters as 2-byte Unicode characters on machines with multi-byte character sets
MBCS 一词仍然有点 ambiguous对我来说,我认为他们在这种情况下是指 UTF-16(尽管我不确定 surrogate pairs ,这可能是 UCS-2)。
更新: MathWorks 将措辞更改为:
MATLAB uses 16-bit unsigned integer character encoding for Unicode characters.
mxArrayToString
页面声明它确实处理多字节编码字符(unlinke mxGetString
仅处理单字节编码方案)。不幸的是,没有关于如何执行此操作的示例。
最后,这是一个thread在 MATLAB 新闻组上提到了几个与此相关的未记录的函数(您可以通过将 libmx.dll
库加载到像 Dependency Walker 这样的工具中自己找到它们Windows)。
这是我在 MEX 中做的一个小实验:
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char str_ascii[] = {0x41, 0x6D, 0x72, 0x6F, 0x00}; // {'A','m','r','o',0}
char str_utf8[] = {
0x41, // U+0041
0xC3, 0x80, // U+00C0
0xE6, 0xB0, 0xB4, // U+6C34
0x00
};
char str_utf16_le[] = {
0x41, 0x00, // U+0041
0xC0, 0x00, // U+00C0
0x34, 0x6C, // U+6C34
0x00, 0x00
};
plhs[0] = mxCreateString(str_ascii);
plhs[1] = mxCreateString_UTF8(str_utf8); // undocumented!
plhs[2] = mxCreateString_UTF16(str_utf16_le); // undocumented!
}
我在 C 代码中创建了三个字符串,分别用 ASCII、UTF-8 和 UTF-16LE 编码。然后,我使用 mxCreateString
MEX 函数(以及它的其他未记录版本)将它们传递给 MATLAB。
我通过查阅 Fileformat.info 网站得到了字节序列: A (U+0041) , À (U+00C0) , 和 水 (U+6C34) .
让我们在 MATLAB 中测试上面的函数:
%# call the MEX function
[str_ascii, str_utf8, str_utf16_le] = my_func()
%# MATLAB exposes the two strings in a decoded form (Unicode code points)
double(str_utf8) %# decimal form: [65, 192, 27700]
assert(isequal(str_utf8, str_utf16_le))
%# convert them to bytes (in HEX)
b1 = unicode2native(str_utf8, 'UTF-8')
b2 = unicode2native(str_utf16_le, 'UTF-16')
cellstr(dec2hex(b1))' %# {'41','C3','80','E6','B0','B4'}
cellstr(dec2hex(b2))' %# {'FF','FE','41','00','C0','00','34','6C'}
%# (note that first two bytes are BOM markers)
%# show string
view_unicode_string(str_utf8)
我正在使用 embedded Java capability查看字符串:
function view_unicode_string(str)
%# create Swing JLabel
jlabel = javaObjectEDT('javax.swing.JLabel', str);
font = java.awt.Font('Arial Unicode MS', java.awt.Font.PLAIN, 72);
jlabel.setFont(font);
jlabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
%# place Java component inside a MATLAB figure
hfig = figure('Menubar','none');
[~,jlabelHG] = javacomponent(jlabel, [], hfig);
set(jlabelHG, 'Units','normalized', 'Position',[0 0 1 1])
end
现在让我们从相反的方向开始工作(接受来自 MATLAB 的字符串到 C 中):
#include "mex.h"
void print_hex(const unsigned char* s, size_t len)
{
size_t i;
for(i=0; i<len; ++i) {
mexPrintf("0x%02X ", s[i] & 0xFF);
}
mexPrintf("0x00\n");
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
char *str;
if (nrhs<1 || !mxIsChar(prhs[0])) {
mexErrMsgIdAndTxt("mex:error", "Expecting a string");
}
str = mxArrayToString_UTF8(prhs[0]); // get UTF-8 encoded string from Unicode
print_hex(str, strlen(str)); // print bytes
plhs[0] = mxCreateString_UTF8(str); // create Unicode string from UTF-8
mxFree(str);
}
我们从 MATLAB 内部对此进行测试:
>> s = char(hex2dec(['0041';'00C0';'6C34'])'); %# "\u0041\u00C0\u6C34"
>> ss = my_func_reverse(s);
0x41 0xC3 0x80 0xE6 0xB0 0xB4 0x00 %# UTF-8 encoding
>> assert(isequal(s,ss))
最后我要说的是,如果出于某种原因您仍然遇到问题,最简单的方法是将非 ASCII 字符串转换为 uint8
数据类型在将其从 MATLAB 传递到您的引擎程序之前。
所以在 MATLAB 过程中做:
%# read contents of a UTF-8 file
fid = fopen('test.txt', 'rb', 'native', 'UTF-8');
str = fread(fid, '*char')';
fclose(fid);
str_bytes = unicode2native(str,'UTF-8'); %# convert to bytes
%# or simply read the file contents as bytes to begin with
%fid = fopen('test.txt', 'rb');
%str_bytes = fread(fid, '*uint8')';
%fclose(fid);
并使用引擎 API 访问变量:
mxArray *arr = engGetVariable(ep, "str_bytes");
uint8_T *bytes = (uint8_T*) mxGetData(arr);
// now you decode this utf-8 string on your end ...
所有测试均在运行 R2012b 且默认字符集的 WinXP 上完成:
>> feature('DefaultCharacterSet')
ans =
windows-1252
希望这有帮助..
在 MATLAB R2014a 中,许多未记录的 C 函数已从 libmx
库(包括上面使用的函数)中删除,并替换为在命名空间 下公开的等效 C++ 函数>matrix::detail::noninlined::mx_array_api
.
调整上述示例(如 here 所述)以在最新的 R2014a 版本上运行应该很容易。
关于matlab - 从 C 访问 MATLAB 的 unicode 字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14942097/
如何使用 SPListCollection.Add(String, String, String, String, Int32, String, SPListTemplate.QuickLaunchO
我刚刚开始使用 C++ 并且对 C# 有一些经验,所以我有一些一般的编程经验。然而,似乎我马上就被击落了。我试过在谷歌上寻找,以免浪费任何人的时间,但没有结果。 int main(int argc,
这个问题已经有答案了: In Java 8 how do I transform a Map to another Map using a lambda? (8 个回答) Convert a Map>
我正在使用 node + typescript 和集成的 swagger 进行 API 调用。我 Swagger 提出以下要求 http://localhost:3033/employees/sear
我是 C++ 容器模板的新手。我收集了一些记录。每条记录都有一个唯一的名称,以及一个字段/值对列表。将按名称访问记录。字段/值对的顺序很重要。因此我设计如下: typedef string
我需要这两种方法,但j2me没有,我找到了一个replaceall();但这是 replaceall(string,string,string); 第二个方法是SringBuffer但在j2me中它没
If string is an alias of String in the .net framework为什么会发生这种情况,我应该如何解释它: type JustAString = string
我有两个列表(或字符串):一个大,另一个小。 我想检查较大的(A)是否包含小的(B)。 我的期望如下: 案例 1. B 是 A 的子集 A = [1,2,3] B = [1,2] contains(A
我有一个似乎无法解决的小问题。 这里...我有一个像这样创建的输入... var input = $(''); 如果我这样做......一切都很好 $(this).append(input); 如果我
我有以下代码片段 string[] lines = objects.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.No
这可能真的很简单,但我已经坚持了一段时间了。 我正在尝试输出一个字符串,然后输出一个带有两位小数的 double ,后跟另一个字符串,这是我的代码。 System.out.printf("成本:%.2
以下是 Cloud Firestore 列表查询中的示例之一 citiesRef.where("state", ">=", "CA").where("state", "= 字符串,我们在Stack O
我正在尝试检查一个字符串是否包含在另一个字符串中。后面的代码非常简单。我怎样才能在 jquery 中做到这一点? function deleteRow(locName, locID) { if
这个问题在这里已经有了答案: How to implement big int in C++ (14 个答案) 关闭 9 年前。 我有 2 个字符串,都只包含数字。这些数字大于 uint64_t 的
我有一个带有自定义转换器的 Dozer 映射: com.xyz.Customer com.xyz.CustomerDAO customerName
这个问题在这里已经有了答案: How do I compare strings in Java? (23 个回答) 关闭 6 年前。 我想了解字符串池的工作原理以及一个字符串等于另一个字符串的规则是
我已阅读 this问题和其他一些问题。但它们与我的问题有些无关 对于 UILabel 如果你不指定 ? 或 ! 你会得到这样的错误: @IBOutlet property has non-option
这两种方法中哪一种在理论上更快,为什么? (指向字符串的指针必须是常量。) destination[count] 和 *destination++ 之间的确切区别是什么? destination[co
This question already has answers here: Closed 11 years ago. Possible Duplicates: Is String.Format a
我有一个Stream一个文件的,现在我想将相同的单词组合成 Map这很重要,这个词在 Stream 中出现的频率. 我知道我必须使用 collect(Collectors.groupingBy(..)
我是一名优秀的程序员,十分优秀!