Dart ffi - 使用 C 从文件中读取表情符号
Dart ffi - Reading emojis from file with C
我正在使用 UTF-8 编码保存一个文件,其中包含一些信息,包括来自 Dart 端的按钮名称,代码如下:
file.writeAsString([
name.length.toString(),
name + Constants.nativeFileDelimeter,
ids.length.toString(),
ids.join(" "),
].join(" "));
// Constants.nativeFileDelimeter is "|", it is used so that user can enter a name with whitespaces
我用 C 读取同一个文件,并使用 FFI 在 C 和 Dart 之间传递数据。
FILE *file;
file = fopen(filePath, "r");
if (!file) {
LOGE("Could not open %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
int32_t size;
if(fscanf(file, "%d ", &size) != 1){
LOGE("fscanf can not assign variables %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
// +1 because C strings ends with /0
*namePtr = new char[size + 1];
if (size != 0){
if(fscanf(file, "%[^|]|", *namePtr) != 1){
LOGE("fscanf can not assign variables %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
}
读取C保存的指针的Dart代码:
Pointer<Pointer<Utf8>> _namePtrPtr;
String get name => Utf8.fromUtf8(_namePtrPtr.value);
我的问题是这段代码有 0 个错误,它甚至可以与日文、俄语字符一起使用,但是当引入表情符号时,事情变得很奇怪。当我保存一个包含表情符号的文件并尝试用 C 和 Dart ffi 读取它时,我收到 Utf8.fromUtf8
抛出的奇怪错误。例如:
Unfinished UTF-8 octet sequence (at offset 48)
有时,相同的代码可以工作并呈现表情符号,但后来应用会随机崩溃。每次读取文件时抛出的异常似乎都不同,有时我没有异常但后来崩溃了!这是不一致的。我不知道我做错了什么,我希望它能与表情符号一起使用。谁能帮我解决这个问题?
在 Dart 中,String.length returns UTF-16 代码单元的数量。要在 C 中读取 UTF-8,您需要知道 UTF-8 字节数。因此,在 Dart 代码中输出 utf8.encode(name).length
而不是 name.length
(并导入 dart:convert
)。异常和崩溃可能是由于尺寸太短引发的未定义行为。
以文本格式单独存储数据大小容易出错。最好使用这种方法:
看来您使用的是 C++。在那里,您可以将文件打开为 std::ifstream
,创建一个 std::string name;
并使用 std::getline(file, name, '|');
读取具有动态大小的名称。您可以使用 *namePtr = strdup(name.c_str())
从 std::string
.
创建一个纯 C 字符串
我正在使用 UTF-8 编码保存一个文件,其中包含一些信息,包括来自 Dart 端的按钮名称,代码如下:
file.writeAsString([
name.length.toString(),
name + Constants.nativeFileDelimeter,
ids.length.toString(),
ids.join(" "),
].join(" "));
// Constants.nativeFileDelimeter is "|", it is used so that user can enter a name with whitespaces
我用 C 读取同一个文件,并使用 FFI 在 C 和 Dart 之间传递数据。
FILE *file;
file = fopen(filePath, "r");
if (!file) {
LOGE("Could not open %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
int32_t size;
if(fscanf(file, "%d ", &size) != 1){
LOGE("fscanf can not assign variables %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
// +1 because C strings ends with /0
*namePtr = new char[size + 1];
if (size != 0){
if(fscanf(file, "%[^|]|", *namePtr) != 1){
LOGE("fscanf can not assign variables %s!", filePath);
*operationState = MediaLoadState::FAILED_TO_LOAD;
goto cleanup;
}
}
读取C保存的指针的Dart代码:
Pointer<Pointer<Utf8>> _namePtrPtr;
String get name => Utf8.fromUtf8(_namePtrPtr.value);
我的问题是这段代码有 0 个错误,它甚至可以与日文、俄语字符一起使用,但是当引入表情符号时,事情变得很奇怪。当我保存一个包含表情符号的文件并尝试用 C 和 Dart ffi 读取它时,我收到 Utf8.fromUtf8
抛出的奇怪错误。例如:
Unfinished UTF-8 octet sequence (at offset 48)
有时,相同的代码可以工作并呈现表情符号,但后来应用会随机崩溃。每次读取文件时抛出的异常似乎都不同,有时我没有异常但后来崩溃了!这是不一致的。我不知道我做错了什么,我希望它能与表情符号一起使用。谁能帮我解决这个问题?
在 Dart 中,String.length returns UTF-16 代码单元的数量。要在 C 中读取 UTF-8,您需要知道 UTF-8 字节数。因此,在 Dart 代码中输出 utf8.encode(name).length
而不是 name.length
(并导入 dart:convert
)。异常和崩溃可能是由于尺寸太短引发的未定义行为。
以文本格式单独存储数据大小容易出错。最好使用这种方法:
看来您使用的是 C++。在那里,您可以将文件打开为 std::ifstream
,创建一个 std::string name;
并使用 std::getline(file, name, '|');
读取具有动态大小的名称。您可以使用 *namePtr = strdup(name.c_str())
从 std::string
.