为了账号安全,请及时绑定邮箱和手机立即绑定

文本解码器.prototype.ignoreBOM 未按预期工作

文本解码器.prototype.ignoreBOM 未按预期工作

手掌心 2022-09-29 17:26:44
我正在使用获取API来提取csv数据并尝试创建一个csv文件。但是,我看到前两个字符是BOM字符。ÿþ然而,我在解码期间设置,但它不起作用,我总是在CSV的开头看到ignoreBOM: trueÿþ下面是我的代码    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);      }任何帮助解决这个问题都会很棒。谢谢。
查看完整描述

1 回答

?
月关宝盒

TA贡献1772条经验 获得超5个赞

ignoreBOM 仅适用于 UTF-8 UTF-16BE 和 UTF-16LE 编码。

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

const littleEnd_BOM = new Uint8Array( [ 0xFF, 0xFE ] );

const as_CP1252 = new TextDecoder( 'iso-8859-1' ).decode( littleEnd_BOM );


console.log( as_CP1252 );

因此,代码中的第一个错误是您不想将文本解码器初始化为CP-1252,而是初始化为UTF-16LE。


现在,对于您确实设置了哪个值存在一些混淆,在您编写的某一点上将其设置为 ,而在代码段中将其设置为(默认值)。ignoreBOMtruefalse


如果希望 BOM 表保留在输出中,请将其设置为 。解析器将忽略该 BOM 标记,这意味着它将将其视为正常字符序列。true


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


请注意,即使 BOM 位于此处,它也可能不是从 DOM 字符串打印的:


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存储在 while 循环之外,以便它可以将以前的缓冲区保留在内存中。streamTextDecoder.decode()


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;

    }

  }

}


查看完整回答
反对 回复 2022-09-29
  • 1 回答
  • 0 关注
  • 102 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信