首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TextDecoder.prototype.ignoreBOM未按预期工作

TextDecoder.prototype.ignoreBOM未按预期工作
EN

Stack Overflow用户
提问于 2020-06-11 22:29:31
回答 1查看 518关注 0票数 0

我正在使用fetch api来提取csv数据,并试图创建一个csv文件。

但是,我看到前两个字符是ÿþ,它们是BOM字符。

然而,在解码设置ignoreBOM: true时,它不起作用,我总是在CSV开始时看到ÿþ

下面是我的代码

代码语言:javascript
复制
    const fetchData = await newPage.evaluate(async () => {
      let url = $('.csvLink').attr('href');
      console.log(`in here is the ${url}`);
      const stream = await fetch(url);
      let reader = stream.body.getReader();
      let receivedLength = 0;
      while(true) {
        const {done, value} = await reader.read();
        if (done) {
          break;
        }
        receivedLength += value.length;
        let v = new TextDecoder("ISO-8859-1", {fatal: false, ignoreBOM: false}).decode(value, {stream: true});
        await window.writeToStream(v, false);
      }

任何帮助来解决这个问题都是很棒的。谢谢。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-12 02:28:26

ignoreBOM 只适用用于UTF-8 UTF-16 and和UTF-16 and编码.

如果您在文件开头有一个BOM,那么它可能不会被编码为CP-1252,而是作为UTF编码,如果该BOM在CP-1252中被读取为ÿþ,那么甚至可能是UTF-16 in:

代码语言:javascript
复制
const littleEnd_BOM = new Uint8Array( [ 0xFF, 0xFE ] );
const as_CP1252 = new TextDecoder( 'iso-8859-1' ).decode( littleEnd_BOM );

console.log( as_CP1252 );

因此,代码中的第一个错误是,您不希望将TextDecoder初始化为CP-1252,而是将其初始化为UTF-16LE。

现在,对于您将ignoreBOM设置为哪个值存在一些困惑,您曾经编写过将其设置为true,而在代码片段中将其设置为false (默认值)。

如果希望的BOM保持在输出中,那么将其设置为true。解析器将忽略BOM标记,这意味着它将将其视为一个正常的字符序列。

另一方面,如果希望将其从输出中删除,则将其保留为false,解析器将对其进行特殊处理,并将其从输出中删除。

请注意,即使BOM在这里,也可能不会从DOMString中打印出来:

代码语言:javascript
复制
const UTF16LE_text = new Uint16Array(
      [ ..."\ufeffhello" ].map( (char) => char.charCodeAt(0) )
  );
// to check we really wrote a LE-BOM "FFFE"
const BOM = [ ...new Uint8Array( UTF16LE_text.buffer ).slice( 0, 2 ) ]
  .map( (v) => v.toString( 16 ) ).join('');
console.log( 'BOM:', BOM );

const ignoring_decoder = new TextDecoder( 'UTF-16LE', { ignoreBOM: true } );
const ignored = ignoring_decoder.decode( UTF16LE_text );
console.log( 'ignoreBOM:true  - text:', ignored );
console.log( 'ignoreBOM:true  - char at 0:', ignored.charCodeAt( 0 ) );

const removing_decoder = new TextDecoder( 'UTF-16LE' );
const removed = removing_decoder.decode( UTF16LE_text );
console.log( 'ignoreBOM:false - text:', removed );
console.log( 'ignoreBOM:false - char at 0:', removed.charCodeAt( 0 ) );

但是,您可能面临的另一个问题是,您正在读取获取的文本块,即随机大小的数据块。

文本不能这样处理,您需要从定义良好的字节位置解析它,才能正确地解析它。

幸运的是,TextDecoder.decode()方法有一个TextDecoder.decode()选项。使用它,解码器应该能够正确地读取流,但是要使此选项工作,您需要将TextDecoder存储在while循环之外,这样它就可以将前一个缓冲区保存在内存中。

代码语言:javascript
复制
const fetchData = await newPage.evaluate(async () => {
  let url = $('.csvLink').attr('href');
  const stream = await fetch(url);
  let reader = stream.body.getReader();
  let receivedLength = 0;
  // declare the decoder outside of the loop
  const decoder = new TextDecoder("UTF-16LE");
  while(true) {
    const {done, value} = await reader.read();
    receivedLength += value.length;
    // always use the same decoder
    const v = decoder.decode(value, {stream: true});
    await window.writeToStream(v, false);
    if (done) { 
      break;
    }
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62334608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档