检查JavaScript字符串是否为有效的UTF-8格式

14

用户可以将内容复制并粘贴到textarea html输入框中,有时会粘贴无效的UTF-8字符,例如从包含制表符的RTF文件中复制和粘贴。

如何检查一个字符串是否是有效的UTF-8?


1
可能会对你有所帮助 https://dev59.com/KnrZa4cB1Zd3GeqP1VzM - Hadi J
看起来类似于在Javascript中验证用户的UTF-8名称 - Abhijit
2个回答

7

阐述

我认为你误解了“UTF-8字符”的意思;UTF-8是Unicode的一种编码方式,可以表示(不断增长的)Unicode标准中定义的任何字符、字形和字母单元。Unicode代码点比可能的UTF8字节值少,因此唯一的“无效UTF8字符”是UTF8字节序列,它们没有映射到任何Unicode代码点,但我假设这不是你所指的。

例如,从包含制表符的rtf文件中复制和粘贴。

RTF是一种独立于底层编码方案的格式化系统,你可以在ASCII、UTF-8、UTF-16和其他编码中使用RTF。关于你帖子中的HTML文本框,HTML中的<input type="text"><textarea>元素只支持纯文本,因此任何RTF格式都会在用户粘贴时自动删除,这就是为什么JS-heavy“rich-edit”和contenteditable组件在Web应用程序中很常见,尽管在这个答案中,我假设您没有在网页中使用富文本编辑器组件。

RTF文件中的制表符不是RTF功能:它们只是普通的 ASCII-style tab characters,即\t0x09,它们也出现在Unicode中,因此可以出现在UTF-8编码的文本中;此外,Web浏览器允许用户将它们粘贴到<input><textarea>中也是完全有效的。


Javascript(ECMAScript)本身是Unicode本地化的;也就是说,ECMAScript规范确实要求JS引擎在某些地方使用UTF-16表示,例如在抽象操作IsStringWellFormedUnicode中:

7.2.9静态语义学:IsStringWellFormedUnicode

抽象操作IsStringWellFormedUnicode接受参数字符串(一个String),并返回一个Boolean它将字符串解释为UTF-16编码的代码点序列,如6.1.4所述,并确定它是否是格式良好的UTF-16序列。

...但是规范的那一部分是为JS引擎程序员而设计的,而不是为在浏览器中编写JS的人设计的-实际上,我认为可以安全地假设,在Web浏览器中,任何和所有JS string值将始终是有效的字符串,可以始终被序列化为UTF-8和UTF-16,而且JS脚本不应关心字符串内容的实际内存编码。

你的问题

所以,考虑到你的问题是这样写的:

用户可以复制并粘贴HTML输入到文本区域,并且有时会粘贴无效的UTF-8字符,例如从包含选项卡的RTF文件复制和粘贴。

如何检查一个字符串是否是有效的UTF-8?

我将其解释为:

一个用户可以从类似WordPad的程序中复制RTF文本,并将其粘贴到Web浏览器中的HTML <textarea><input type="text">中,当它被粘贴时,RTF的纯文本表示仍然包含应用程序不应接受的某些字符,例如制表符之类的空格。

如何检测这些不需要的字符并通知用户-或删除这些不需要的字符?

...对此我的答案是:

我建议使用匹配非可见字符的正则表达式来剥离不需要的字符(从这里:Match non printable/non ascii characters and remove from text)。

let textBoxContent = document.getElementById( 'myTextarea' ).value;
textBoxContent = textBoxContent.replace( /[^\x20-\x7E]+/g, '' );
  • 表达式[^\x20-\x7E]匹配任何不在代码点范围内的字符0x20(32,普通空格字符' ')到0x7E(127,波浪符'~'字符),所有其他字符都将被删除,包括非拉丁文本。

  • 末尾的g开关使其成为全局查找和替换操作;如果没有g,则只会删除第一个不需要的字符。

  • 范围0x20-0x7E有效,因为Unicode的前127个代码点与ASCII相同,可以在此处查看:http://www.asciitable.com/


9
为了纠正这个回答中的一些误解,需要说明:UTF8不存在所谓的“字符”,作为一种编码方案,UTF8中存在“UTF8字节序列”来编码Unicode代码点,而这些字节序列可以受到字节序列中非法值的影响。同样地,Unicode作为“书写结构”与数字编码之间的正式映射,也有某些数字是不允许使用的。遇到包含非法字节序列的UTF8字节流或包含非法数字的已解码Unicode序列是完全可能的,因此:“无效的UTF-8字符”是存在的。 - Mike 'Pomax' Kamermans
@Mike'Pomax'Kamermans 我已经重写了我的答案来实现您的反馈,感谢您的建议。 - Dai
我进一步编辑了你的文本,因为如果段落的整个重点是解释答案是“是”,但问题的答案并不是他们想要知道的,那么这不是一个技术细节。 - Mike 'Pomax' Kamermans
@Mike'Pomax'Kamermans - Dai

2

一个想法:

function checkUTF8(text) {
    var utf8Text = text;
    try {
        // Try to convert to utf-8
        utf8Text = decodeURIComponent(escape(text));
        // If the conversion succeeds, text is not utf-8
    }catch(e) {
        // console.log(e.message); // URI malformed
        // This exception means text is utf-8
    }   
    return utf8Text; // returned text is always utf-8
}

4
escape 已被弃用,不应再使用它(因为它无法正确处理 Unicode)。 - Quentin
“text is not utf-8”是什么意思?这似乎意味着文本是ASCII编码?而在catch块中则是Unicode编码? - xeruf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接