14

我刚刚发现 Node(已测试:v0.8.23,当前 git:v0.11.3-pre)忽略其缓冲区处理中的任何解码错误,默默地用(Unicode 替换字符)替换任何非 utf8 字符,'\ufffd'而不是抛出异常非utf8输入。结果,fs.readFileprocess.stdin.setEncoding朋友为您掩盖了一大类错误的输入错误。

不会失败但确实应该失败的示例:

> notValidUTF8 = new Buffer([ 128 ], 'binary')
<Buffer 80>
> decodedAsUTF8 = notValidUTF8.toString('utf8') // no exception thrown here!
'�'
> decodedAsUTF8 === '\ufffd'
true

'\ufffd'是一个完全有效的字符,可以出现在合法的 utf8 中(作为 sequence ef bf bd),因此基于结果中显示的错误处理,monkey-patch 并非易事。

再深入一点,看起来这源于节点只是遵循 v8 的字符串,而这些字符串又具有上述行为,v8 没有任何外部世界充满了外国编码的数据。

是否有节点模块或其他方式可以让我捕获 utf-8 解码错误,最好有关于在输入字符串或缓冲区中发现错误的上下文?

4

3 回答 3

10

我希望你在那些年解决了这个问题,我有一个类似的问题,最终用这个丑陋的技巧解决了:

  function isValidUTF8(buf){
   return Buffer.compare(new Buffer(buf.toString(),'utf8') , buf) === 0;
  }

它来回转换缓冲区并检查它是否保持不变。

'utf8' 编码可以省略。

然后我们有:

> isValidUTF8(new Buffer('this is valid, 指事字 eè we hope','utf8'))
true
> isValidUTF8(new Buffer([128]))
false
> isValidUTF8(new Buffer('\ufffd'))
true

其中 '\ufffd' 字符被正确地视为有效的 utf8。

更新:现在这也适用于 JXcore

于 2015-08-28T20:28:12.773 回答
4

从节点 8.3 开始,您可以使用util.TextDecoder干净地解决这个问题:

const util = require('util')
const td = new util.TextDecoder('utf8', {fatal:true})
td.decode(Buffer.from('foo')) // works!
td.decode(Buffer.from([ 128 ], 'binary')) // throws TypeError

通过在全局命名空间中使用,这也适用于某些浏览器。TextDecoder

于 2019-01-30T23:34:58.500 回答
0

正如 Josh C. 上面所说:“npmjs.org/package/encoding”

来自 npm 网站:“编码是 node-iconv 和 iconv-lite 的简单包装,用于将字符串从一种编码转换为另一种编码。”

下载: $ npm install encoding

示例用法

var result = encoding.convert(new Buffer([ 128 ], 'binary'), "utf8");
console.log(result); //<Buffer 80>

访问站点: npm - encoding

于 2013-11-10T02:27:46.427 回答