我有一个小问题。
我正在使用NodeJS作为后端。现在,用户拥有一个“传记”字段,用户可以在其中写一些关于他自己的东西。
假设此字段的最大长度为220,并将其作为输入:
♀️♀️♀️♀️♀️♀️⚕️⚕️
如您所见,没有220个表情符号(有37个表情符号),但是如果我在我的nodejs服务器中这样做的话
console.log(bio.length)
输入文本为bio时,我得到221。如何“解析”字符串输入以获得正确的长度?关于Unicode是否有问题?
已解决
我使用了这个库:https://github.com/orling/grapheme-splitter
我尝试过:
var Grapheme = require('grapheme-splitter');
var splitter = new Grapheme();
console.log(splitter.splitGraphemes(bio).length);
长度为37。效果很好!
答案 0 :(得分:3)
str.length
给出UTF-16单位的数量。由于可迭代协议将字符串拆分为代码点,因此以代码点(以字符为单位)获取字符串长度的Unicode验证方法为[...str].length
。
另请参阅:
What every JavaScript developer should know about Unicode
JavaScript has a Unicode problem
答案 1 :(得分:1)
function fancyCount2(str){
const joiner = "\u{200D}";
const split = str.split(joiner);
let count = 0;
for(const s of split){
//removing the variation selectors
const num = Array.from(s.split(/[\ufe00-\ufe0f]/).join("")).length;
count += num;
}
//assuming the joiners are used appropriately
return count / split.length;
}
答案 2 :(得分:1)
TL; DR有解决方案,但并非在每种情况下都有效。 Unicode感觉像是一门黑暗的艺术。
我看到的各种解决方案似乎都存在局限性,这个问题不仅限于表情符号,还涉及Unicode范围内的其他字符。如果使用combing characters,则考虑é可以存储为é或e +′。这甚至可能导致两个看起来相同的not being equal字符串。还要注意,在某些情况下,单个表情符号在存储时可以为11个字符,因此假设为UTF16,则为22个字节。
这种处理方式以及字符组合或显示的方式甚至可能在浏览器和操作系统之间有所不同。因此,尽管您可能认为自己已将其破解,但存在另一种环境可能破坏该漏洞的风险。请务必测试重要的地方。
现在,存在前端和后端问题:您解决了字符计数问题,因此对人类用户有效,现在您的单个表情符号就超出了数据库中分配的字段大小。对于诸如mongo之类的数据库而言,问题较少,但对于SQL数据库而言,字段分配是保守的,这可能是一个问题。这意味着您如何解决问题将取决于最困难的限制来自何处。
请注意,基本解决方案确实涉及将字符串转换为数组并获取长度,并接受限制:
Array.from(str)
当字符组合并处理astral planes时,这将崩溃。
一些高级方法,其中考虑到了局限性:
此外,考虑到问题的复杂性,也许值得一看,是否已经有一个流行的JS库已经解决了这个问题?在撰写本文时,我没有找到一个。希望这会在某个时候成为Javascript的核心。
其他要阅读的页面:
答案 3 :(得分:1)
答案 4 :(得分:0)
从下面的示例中可以看到,这与unicode编码有关,
有很多很棒的资源,例如我从这个例子中借鉴的资源。
https://blog.jonnew.com/posts/poo-dot-length-equals-two
console.log("❤️".length === 11);
答案 5 :(得分:0)
我建议使用 runes 包来完成正确的多字节字符串转换,否则你会遇到更多问题,例如如果使用 reducer 和更多来反转字符串。
看看这个很棒的小包:runes