JavaScript FileReader读取文件不正确

3
我有一个简短的JavaScript函数,它可以获取上传的文件并显示其十六进制等效值。将原始文件和十六进制编辑器中的输出进行比较,可以发现它们部分不同但并非完全相同。
String.prototype.hexEncode = function(){
  var hex, i;

  var result = "";
  for (i = 0; i < this.length; i++) {
    hex = this.charCodeAt(i).toString(16);
    result += ("" + hex).slice(-4);
  }

  return result
}

function upload() {
  var file = document.getElementById("fileToUpload").files[0];
  var reader = new FileReader();
  reader.readAsText(file, "windows-1252");
  reader.onload = function (evt) {
    var program = evt.target.result.hexEncode();
    program = program;
    console.log(program);
  }
}

以下是原始文件和输出结果并排显示:

2A 2A 54 49 38 33 46 2A 1A 0A 0A 43 72 65 61 74
2A 2A 54 49 38 33 46 2A 1A AA 43 72 65 61 74 65

什么导致输出结果的差异?非常感谢您的帮助。

1
你试过使用.readAsArrayBuffer而不是.readAsText吗?后者可能会改变内容。 - Derek 朕會功夫
绝对不要尝试从readAsText结果生成十六进制转储,特别是使用非默认编码。你需要使用readAsArrayBuffer。 - Kaiido
预期结果是什么? - guest271314
输入和输出是相同的。 - Julian Lachniet
1个回答

4
使用JavaScript生成十六进制转储时,不应使用readAsText方法,该方法将把您的数据转换为UCS-2或UTF-16格式。相反,直接读取从readAsArrayBuffer方法获取的二进制数据,并从那里开始处理:

function hexDump(file) {
  return new Promise((res, rej) => {
    if (!(file instanceof Blob)) rej('wrong input');
    const reader = new FileReader();
    reader.onload = e => {
      res(hex(reader.result));
    };
    reader.onerror = e => rej('error while reading');
    reader.readAsArrayBuffer(file);
  });
  // gotten from https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest#Example
  function hex(buffer) {
    const hexCodes = [];
    const view = new DataView(buffer);
    for (let i = 0; i < view.byteLength; i += 4) {
      // Using getUint32 reduces the number of iterations needed (we process 4 bytes each time)
      let value = view.getUint32(i)
      // toString(16) will give the hex representation of the number without padding
      let stringValue = value.toString(16)
      // We use concatenation and slice for padding
      let padding = '00000000'
      let paddedValue = (padding + stringValue).slice(-padding.length).toUpperCase();
      hexCodes.push( // simple prettyfying
        paddedValue.slice(0,2),
        paddedValue.slice(2,4),
        paddedValue.slice(4,6),
        paddedValue.slice(6,8)
        );
    }
    return hexCodes.join(' ');
  }
}

// How to use it
inp.onchange = e => hexDump(inp.files[0].slice(0, 100)) // for demo I slice the file
    .then(hex => console.log(hex))
    .catch(e => console.error(e));
<input type="file" id="inp">


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