将 SQL 中表情符号的字符串 unicode 表示形式转换为 Dart 中(或 PHP 中)的实际表情符号
Converting a String unicode representation of emoji in SQL to the actual Emoji in Dart (or in PHP)
我为此折腾了一天一夜。许多人的许多答案,但 none 对我的情况有效。很抱歉这个菜鸟问题,但我确实花了整个昨天直到清晨。
所以我把旧系统迁移到新系统。
本质上是从 SQL 服务器到 Firebase。使用新结构,所有新 uid 和客户端希望将来自旧 SQL 服务器的 unicode 数据转换为真正的表情符号。
所以它来自 SQL(在旧服务器中)=> PHP(在旧服务器中获取 SQL 数据)=> Flutter(在我的笔记本电脑中)=> Firebase(Firestore)。
在 SQL 服务器中有这样的字符串,例如:
Spring... fall...\ud83d\udc90...flowers!
然后从 SQL 数据库 return 中检索的 PHP 代码如下所示:
// Create Connection
$conn = new mysqli($servername, $username, $password, $dbname);
mysqli_set_charset($conn,'utf8mb4');
header("Access-Control-Allow-Origin: *");
$result = $conn->query($sql);
if($result->num_rows > 0) {
$db_data = array();
while($row = $result->fetch_assoc()) {
$db_data[] = $row;
}
// Send back the complete records as a json
echo json_encode($db_data, JSON_UNESCAPED_UNICODE);
}else{
http_response_code(405);
echo "Query error";
}
$result->free();
$conn->close();
return;
在 Dart (Flutter Web) 中,我得到了这样的数据:
final response = await http.get(urlRequest);
final rawRows = jsonDecode(response.body) as List<dynamic>;
rawRows.forEach((map) => print(map['description']));
这会打印出:Spring... fall...\ud83d\udc90...flowers!
我要的是Spring... fall......flowers!
我做了一个硬编码打印测试(即:print('Spring... fall...\ud83d\udc90...flowers!');
,它给出了我想要的结果(即:它将字符串的 \ud83d\udc90
部分变成)
我试过将它按原样发送到 Firebase,它仍然无法将 \ud83d\udc90
识别为表情符号。它像这样 Spring... fall...\ud83d\udc90...flowers!
存储在 Firebase 中。这完全可以理解,我想我们需要先转换它。
我也试过在 PHP 端使用转换器,如下所示:(thanks to Pedro Lobito)
function unicodeString($str, $encoding=null) {
if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
return preg_replace_callback('/\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}
然后PHP中的$db_data[] = $row;
部分改为$db_data[] = unicodeString($row);
但是这个解决方案只适用于部分表情符号而不适用于所有表情符号,例如上述情况。它显示 Spring... fall...?...flowers!
而不是。
所以现在我想尝试在 Dart 中转换它,因为我对它更熟悉。除非有人也可以在 PHP 中帮助解决它。
经过几天的努力,我终于找到了自己的解决方案。
所以我所做的就是使用RegEx
检测字符串中的序列并用表情符号替换它们。
- 声明用于检测 unicode 的正则表达式(在我的例子中,unicode 类似于 (\uXXX):
// To detect a single unicode
static const regEx1 = '\\u([0-9a-fA-F]{4})';
// To detect a 2-bytes unicode
static const regEx2 = '$regEx1$regEx1';
- 创建一个方法来检测每个 RegEx。然后,当找到一个模式时,将其替换为
jsonDecode
并在其中添加引号。像这样 jsonDecode('"${match.group(0)}"');
.
代码:
static String _regExEmojiUnicode(String text, String regEx) {
final regexCheck = RegExp(regEx, caseSensitive: false);
String newText = '';
int _lastEndText = 0;
int _lastEndNewText = 0;
regexCheck.allMatches(text).forEach((match) {
final start = match.start;
final end = match.end;
final String replacement = jsonDecode('"${match.group(0)}"');
String startString;
newText == ''
? startString = '${text.substring(0, start)}$replacement'
: startString =
'${newText.substring(0, _lastEndNewText)}${text.substring(_lastEndText, start)}$replacement';
_lastEndNewText = startString.length;
_lastEndText = end;
newText =
'$startString${text.substring(end)}';
});
if(newText == '') newText = text;
return newText;
}
- 创建一种方法来检查表情符号的不同情况:
static String replaceEmoji(String text) {
String newText = text;
// Checking for 2-bytes and single bytes emojis
if(newText.contains('\u'))
newText = _regExEmojiUnicode(newText, regEx2);
if(newText.contains('\u'))
newText = _regExEmojiUnicode(newText, regEx1);
return newText;
}
那么就可以了!!
我是匆忙做的,所以如果可以对 RegEx 模式或代码中的其他任何地方进行任何改进,我愿意接受任何建议。
谢谢
我为此折腾了一天一夜。许多人的许多答案,但 none 对我的情况有效。很抱歉这个菜鸟问题,但我确实花了整个昨天直到清晨。
所以我把旧系统迁移到新系统。 本质上是从 SQL 服务器到 Firebase。使用新结构,所有新 uid 和客户端希望将来自旧 SQL 服务器的 unicode 数据转换为真正的表情符号。
所以它来自 SQL(在旧服务器中)=> PHP(在旧服务器中获取 SQL 数据)=> Flutter(在我的笔记本电脑中)=> Firebase(Firestore)。
在 SQL 服务器中有这样的字符串,例如:
Spring... fall...\ud83d\udc90...flowers!
然后从 SQL 数据库 return 中检索的 PHP 代码如下所示:
// Create Connection
$conn = new mysqli($servername, $username, $password, $dbname);
mysqli_set_charset($conn,'utf8mb4');
header("Access-Control-Allow-Origin: *");
$result = $conn->query($sql);
if($result->num_rows > 0) {
$db_data = array();
while($row = $result->fetch_assoc()) {
$db_data[] = $row;
}
// Send back the complete records as a json
echo json_encode($db_data, JSON_UNESCAPED_UNICODE);
}else{
http_response_code(405);
echo "Query error";
}
$result->free();
$conn->close();
return;
在 Dart (Flutter Web) 中,我得到了这样的数据:
final response = await http.get(urlRequest);
final rawRows = jsonDecode(response.body) as List<dynamic>;
rawRows.forEach((map) => print(map['description']));
这会打印出:Spring... fall...\ud83d\udc90...flowers!
我要的是Spring... fall......flowers!
我做了一个硬编码打印测试(即:print('Spring... fall...\ud83d\udc90...flowers!');
,它给出了我想要的结果(即:它将字符串的 \ud83d\udc90
部分变成)
我试过将它按原样发送到 Firebase,它仍然无法将 \ud83d\udc90
识别为表情符号。它像这样 Spring... fall...\ud83d\udc90...flowers!
存储在 Firebase 中。这完全可以理解,我想我们需要先转换它。
我也试过在 PHP 端使用转换器,如下所示:(thanks to Pedro Lobito)
function unicodeString($str, $encoding=null) {
if (is_null($encoding)) $encoding = ini_get('mbstring.internal_encoding');
return preg_replace_callback('/\\u([0-9a-fA-F]{4})/u', create_function('$match', 'return mb_convert_encoding(pack("H*", $match[1]), '.var_export($encoding, true).', "UTF-16BE");'), $str);
}
然后PHP中的$db_data[] = $row;
部分改为$db_data[] = unicodeString($row);
但是这个解决方案只适用于部分表情符号而不适用于所有表情符号,例如上述情况。它显示 Spring... fall...?...flowers!
而不是。
所以现在我想尝试在 Dart 中转换它,因为我对它更熟悉。除非有人也可以在 PHP 中帮助解决它。
经过几天的努力,我终于找到了自己的解决方案。
所以我所做的就是使用RegEx
检测字符串中的序列并用表情符号替换它们。
- 声明用于检测 unicode 的正则表达式(在我的例子中,unicode 类似于 (\uXXX):
// To detect a single unicode
static const regEx1 = '\\u([0-9a-fA-F]{4})';
// To detect a 2-bytes unicode
static const regEx2 = '$regEx1$regEx1';
- 创建一个方法来检测每个 RegEx。然后,当找到一个模式时,将其替换为
jsonDecode
并在其中添加引号。像这样jsonDecode('"${match.group(0)}"');
.
代码:
static String _regExEmojiUnicode(String text, String regEx) {
final regexCheck = RegExp(regEx, caseSensitive: false);
String newText = '';
int _lastEndText = 0;
int _lastEndNewText = 0;
regexCheck.allMatches(text).forEach((match) {
final start = match.start;
final end = match.end;
final String replacement = jsonDecode('"${match.group(0)}"');
String startString;
newText == ''
? startString = '${text.substring(0, start)}$replacement'
: startString =
'${newText.substring(0, _lastEndNewText)}${text.substring(_lastEndText, start)}$replacement';
_lastEndNewText = startString.length;
_lastEndText = end;
newText =
'$startString${text.substring(end)}';
});
if(newText == '') newText = text;
return newText;
}
- 创建一种方法来检查表情符号的不同情况:
static String replaceEmoji(String text) {
String newText = text;
// Checking for 2-bytes and single bytes emojis
if(newText.contains('\u'))
newText = _regExEmojiUnicode(newText, regEx2);
if(newText.contains('\u'))
newText = _regExEmojiUnicode(newText, regEx1);
return newText;
}
那么就可以了!!
我是匆忙做的,所以如果可以对 RegEx 模式或代码中的其他任何地方进行任何改进,我愿意接受任何建议。
谢谢