如何在 dart / flutter 中将带有十六进制的 unicode 转换为 String
How to convert unicode with hex to String in dart / flutter
%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD
以上是十六进制字符串的unicode
需要将其转换为可读文本
解码后,上面的文字会 return வணக்கம் 意思是欢迎
如果你想要一个hard-coded字符串,如Flutter中的特殊字符所述
和 the Dart Language Tour 中,可以使用 \u
来指定 Unicode 代码点:
var welcome = '\u0BB5\u0BA3\u0B95\u0BCD\u0B95\u0BAE\u0BCD';
如果给定一个字符串 '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD'
并且需要在运行时动态 转换它,那么您将需要:
- 将字符串拆分为
%uXXXX
个组件。
- 将
XXXX
部分解析为十六进制整数以获取代码点。
- 从代码点构造一个
String
。
void main() {
var s = '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD';
var re = RegExp(r'%u(?<codePoint>[0-9A-Fa-f]{4})');
var matches = re.allMatches(s);
var codePoints = [
for (var match in matches)
int.parse(match.namedGroup('codePoint')!, radix: 16),
];
var decoded = String.fromCharCodes(codePoints);
print(decoded); // Prints: வணக்கம்
}
编辑 1
可以处理混合了编码代码点和未编码字符的字符串的调整版本:
void main() {
var s = '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD'
' hello world! '
'%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD';
var re = RegExp(r'(%u(?<codePoint>[0-9A-Fa-f]{4}))|.');
var matches = re.allMatches(s);
var codePoints = <int>[];
for (var match in matches) {
var codePoint = match.namedGroup('codePoint');
if (codePoint != null) {
codePoints.add(int.parse(codePoint, radix: 16));
} else {
codePoints += match.group(0)!.runes.toList();
}
}
var decoded = String.fromCharCodes(codePoints);
print(decoded); // Prints: வணக்கம் hello world! வணக்கம்
}
编辑 2
以上版本假定您的输入仅包含编码为 %uHHHH
(其中 H 是十六进制数字)的 Unicode 代码点和原始 ASCII 字符。但是,您的 new version of this question 表明您实际上需要处理以下混合情况:
- Unicode 代码点编码为
%uHHHH
。
- 原始(未编码)ASCII 字符。
- ASCII 字符编码为
%HH
。
处理第三种情况:
void main() {
var s = '%3Cp%3E%3Cb%3E%u0B87%u0BA8%u0BCD%u0BA4%u0BBF%u0BAF%u0BBE%u0BB5%u0BBF%u0BA9%u0BCD%20%u0BAA%u0BC6%u0BB0%u0BC1%u0BAE%u0BCD%u0BAA%u0BBE%u0BA9%u0BCD%u0BAE%u0BC8%u0BAF%u0BBE%u0BA9%20%u0BAE%u0B95%u0BCD%u0B95%u0BB3%u0BCD%20%u0BAA%u0BB4%u0B99%u0BCD%u0B95%u0BBE%u0BB2%u0BA4%u0BCD%u0BA4%u0BBF%u0BB2%u0BBF%u0BB0%u0BC1%u0BA8%u0BCD%u0BA4%u0BC7%20.........%20%u0BAA%u0BCB%u0BA9%u0BCD%u0BB1%u0BC1%20%u0BA4%u0BBE%u0BA9%u0BBF%u0BAF%u0B99%u0BCD%u0B95%u0BB3%u0BC8%20%u0BAE%u0BC1%u0B95%u0BCD%u0B95%u0BBF%u0BAF%20%u0B89%u0BA3%u0BB5%u0BBE%u0B95%u0BAA%u0BCD%20%u0BAA%u0BAF%u0BA9%u0BCD%u0BAA%u0B9F%u0BC1%u0BA4%u0BCD%u0BA4%u0BBF%u0BA9%u0BB0%u0BCD.%3C/b%3E%0A%3Col%20type%3D%22I%22%20style%3D%22font-weight%3Abold%3B%22%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B85%u0BB0%u0BBF%u0B9A%u0BBF%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B95%u0BC7%u0BB4%u0BCD%u0BB5%u0BB0%u0B95%u0BC1%20%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B93%u0B9F%u0BCD%u0BB8%u0BCD%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0BAA%u0BB0%u0BC1%u0BAA%u0BCD%u0BAA%u0BC1%3C/span%3E%3C/li%3E%3C/ol%3E%3C/p%3E';
var re = RegExp(
r'(%(?<asciiValue>[0-9A-Fa-f]{2}))'
r'|(%u(?<codePoint>[0-9A-Fa-f]{4}))'
r'|.',
);
var matches = re.allMatches(s);
var codePoints = <int>[];
for (var match in matches) {
var codePoint = match.namedGroup('asciiValue') ?? match.namedGroup('codePoint');
if (codePoint != null) {
codePoints.add(int.parse(codePoint, radix: 16));
} else {
codePoints += match.group(0)!.runes.toList();
}
}
var decoded = String.fromCharCodes(codePoints);
print(decoded);
}
打印:
<p><b>இந்தியாவின் பெரும்பான்மையான மக்கள் பழங்காலத்திலிருந்தே ......... போன்று தானியங்களை முக்கிய உணவாகப் பயன்படுத்தினர்.</b>
<ol type="I" style="font-weight:bold;">
<li><span style="font-weight:normal;"> அரிசி</span></li>
<li><span style="font-weight:normal;"> கேழ்வரகு </span></li>
<li><span style="font-weight:normal;"> ஓட்ஸ்</span></li>
<li><span style="font-weight:normal;"> பருப்பு</span></li></ol></p>
有些包可以呈现 HTML(例如 package:flutter_html
和可能的其他包)。否则我将考虑处理 HTML 超出此答案的范围,无论如何这都值得单独提问。
%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD
以上是十六进制字符串的unicode 需要将其转换为可读文本 解码后,上面的文字会 return வணக்கம் 意思是欢迎
如果你想要一个hard-coded字符串,如Flutter中的特殊字符所述
和 the Dart Language Tour 中,可以使用 \u
来指定 Unicode 代码点:
var welcome = '\u0BB5\u0BA3\u0B95\u0BCD\u0B95\u0BAE\u0BCD';
如果给定一个字符串 '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD'
并且需要在运行时动态 转换它,那么您将需要:
- 将字符串拆分为
%uXXXX
个组件。 - 将
XXXX
部分解析为十六进制整数以获取代码点。 - 从代码点构造一个
String
。
void main() {
var s = '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD';
var re = RegExp(r'%u(?<codePoint>[0-9A-Fa-f]{4})');
var matches = re.allMatches(s);
var codePoints = [
for (var match in matches)
int.parse(match.namedGroup('codePoint')!, radix: 16),
];
var decoded = String.fromCharCodes(codePoints);
print(decoded); // Prints: வணக்கம்
}
编辑 1
可以处理混合了编码代码点和未编码字符的字符串的调整版本:
void main() {
var s = '%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD'
' hello world! '
'%u0BB5%u0BA3%u0B95%u0BCD%u0B95%u0BAE%u0BCD';
var re = RegExp(r'(%u(?<codePoint>[0-9A-Fa-f]{4}))|.');
var matches = re.allMatches(s);
var codePoints = <int>[];
for (var match in matches) {
var codePoint = match.namedGroup('codePoint');
if (codePoint != null) {
codePoints.add(int.parse(codePoint, radix: 16));
} else {
codePoints += match.group(0)!.runes.toList();
}
}
var decoded = String.fromCharCodes(codePoints);
print(decoded); // Prints: வணக்கம் hello world! வணக்கம்
}
编辑 2
以上版本假定您的输入仅包含编码为 %uHHHH
(其中 H 是十六进制数字)的 Unicode 代码点和原始 ASCII 字符。但是,您的 new version of this question 表明您实际上需要处理以下混合情况:
- Unicode 代码点编码为
%uHHHH
。 - 原始(未编码)ASCII 字符。
- ASCII 字符编码为
%HH
。
处理第三种情况:
void main() {
var s = '%3Cp%3E%3Cb%3E%u0B87%u0BA8%u0BCD%u0BA4%u0BBF%u0BAF%u0BBE%u0BB5%u0BBF%u0BA9%u0BCD%20%u0BAA%u0BC6%u0BB0%u0BC1%u0BAE%u0BCD%u0BAA%u0BBE%u0BA9%u0BCD%u0BAE%u0BC8%u0BAF%u0BBE%u0BA9%20%u0BAE%u0B95%u0BCD%u0B95%u0BB3%u0BCD%20%u0BAA%u0BB4%u0B99%u0BCD%u0B95%u0BBE%u0BB2%u0BA4%u0BCD%u0BA4%u0BBF%u0BB2%u0BBF%u0BB0%u0BC1%u0BA8%u0BCD%u0BA4%u0BC7%20.........%20%u0BAA%u0BCB%u0BA9%u0BCD%u0BB1%u0BC1%20%u0BA4%u0BBE%u0BA9%u0BBF%u0BAF%u0B99%u0BCD%u0B95%u0BB3%u0BC8%20%u0BAE%u0BC1%u0B95%u0BCD%u0B95%u0BBF%u0BAF%20%u0B89%u0BA3%u0BB5%u0BBE%u0B95%u0BAA%u0BCD%20%u0BAA%u0BAF%u0BA9%u0BCD%u0BAA%u0B9F%u0BC1%u0BA4%u0BCD%u0BA4%u0BBF%u0BA9%u0BB0%u0BCD.%3C/b%3E%0A%3Col%20type%3D%22I%22%20style%3D%22font-weight%3Abold%3B%22%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B85%u0BB0%u0BBF%u0B9A%u0BBF%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B95%u0BC7%u0BB4%u0BCD%u0BB5%u0BB0%u0B95%u0BC1%20%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0B93%u0B9F%u0BCD%u0BB8%u0BCD%3C/span%3E%3C/li%3E%0A%3Cli%3E%3Cspan%20style%3D%22font-weight%3Anormal%3B%22%3E%20%u0BAA%u0BB0%u0BC1%u0BAA%u0BCD%u0BAA%u0BC1%3C/span%3E%3C/li%3E%3C/ol%3E%3C/p%3E';
var re = RegExp(
r'(%(?<asciiValue>[0-9A-Fa-f]{2}))'
r'|(%u(?<codePoint>[0-9A-Fa-f]{4}))'
r'|.',
);
var matches = re.allMatches(s);
var codePoints = <int>[];
for (var match in matches) {
var codePoint = match.namedGroup('asciiValue') ?? match.namedGroup('codePoint');
if (codePoint != null) {
codePoints.add(int.parse(codePoint, radix: 16));
} else {
codePoints += match.group(0)!.runes.toList();
}
}
var decoded = String.fromCharCodes(codePoints);
print(decoded);
}
打印:
<p><b>இந்தியாவின் பெரும்பான்மையான மக்கள் பழங்காலத்திலிருந்தே ......... போன்று தானியங்களை முக்கிய உணவாகப் பயன்படுத்தினர்.</b>
<ol type="I" style="font-weight:bold;">
<li><span style="font-weight:normal;"> அரிசி</span></li>
<li><span style="font-weight:normal;"> கேழ்வரகு </span></li>
<li><span style="font-weight:normal;"> ஓட்ஸ்</span></li>
<li><span style="font-weight:normal;"> பருப்பு</span></li></ol></p>
有些包可以呈现 HTML(例如 package:flutter_html
和可能的其他包)。否则我将考虑处理 HTML 超出此答案的范围,无论如何这都值得单独提问。