JavaScript - 文件到字节数组
2020-08-20
2236
我正在尝试让一个脚本运行,该脚本名为 sfo.js 。
该仓库仅提到了这种用法:
keys = parse_sfo(Some_ArrayBuffer);
console.log(keys['TITLE']);
查看
sfo.js
,
parse_sfo
具有
sfoBytes
参数。
由此我得出结论,
sfoBytes
参数需要是文件字节的数组缓冲区。
我试图编写一个脚本,将 SFO 文件解析为字节数组:
<script src="sfo.js"></script>
<script>
function stringToArrayBuffer(str) {
var buf = [];
for (var i=0, strLen=str.length; i<strLen; i++) {
buf[i] = str.charCodeAt(i);
}
console.log(buf);
return buf;
}
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, false);
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var array = stringToArrayBuffer(response);
return array;
} else {
alert('Error!');
}
}
var data = testing('param.sfo');
var sfo = parse_sfo(data);
</script>
这会在控制台中引发错误:
Uncaught RangeError: byte length of Uint32Array should be a multiple of 4 at new Uint32Array (<anonymous>)
at readUint32At (sfo.js:20)
at parse_sfo (sfo.js:113)
at (index):29
我很确定我做错了什么。有人知道我该如何让脚本正常工作吗?
我有一个 param.sfo 的示例文件: https://filebin.net/gghosrp6u93jn7y8 (如果不允许链接到下载,请告诉我)
3个回答
好的,终于有了一个可行的示例。
我在互联网上找到了一个小的 param.sfo 文件。
注意:
- 文件阅读器有两个版本:本地和远程
- 在下面的代码片段中,您可以测试两者(我已将 param.sfo 添加为外部链接以测试“远程”)。要测试“本地”,您只需从 PC 中选择任何 sfo 文件即可。
- 结果,我显示了所有键,而不仅仅是“TITLE”(就像您的问题中那样)。然后您可以选择所需的键
function getSfoLocal(callback) {
// for now I use local file for testing
document.querySelector('input').addEventListener('change', function() {
var reader = new FileReader();
reader.onload = function() {
var arrayBuffer = this.result;
var array = new Uint8Array(arrayBuffer);
// var binaryString = String.fromCharCode.apply(null, array);
if (typeof callback === 'function') callback(array);
}
reader.readAsArrayBuffer(this.files[0]);
}, false);
}
function getSfoRemote(url, callback) {
var concatArrayBuffers = function(buffer1, buffer2) {
if (!buffer1) {
return buffer2;
} else if (!buffer2) {
return buffer1;
}
var tmp = new Uint8Array(buffer1.length + buffer2.length);
tmp.set(buffer1, 0);
tmp.set(buffer2, buffer1.byteLength);
return tmp.buffer;
};
fetch(url).then(res => {
const reader = res.body.getReader();
let charsReceived = 0;
let result = new Uint8Array;
reader.read().then(function processText({
done,
value
}) {
// Result objects contain two properties:
// done - true if the stream has already given you all its data.
// value - some data. Always undefined when done is true.
if (done) {
if (typeof callback === 'function') callback(result);
return result;
}
// value for fetch streams is a Uint8Array
charsReceived += value.length;
const chunk = value;
result = concatArrayBuffers(result, chunk);
// Read some more, and call this function again
return reader.read().then(processText);
});
});
}
function getSfo(type, url, callback) {
if (type === 'local') getSfoLocal(callback);
if (type === 'remote') getSfoRemote(url, callback);
}
getSfo('local', null, (data) => {
keys = parse_sfo(data);
console.log('LOCAL =', keys);
});
function goremote() {
getSfo('remote', 'https://srv-file9.gofile.io/download/Y0gVfw/PARAM.SFO', (data) => {
keys = parse_sfo(data);
console.log('REMOTE =', keys);
});
}
div { padding: 4px; }
<!--script src="https://rawcdn.githack.com/KuromeSan/sfo.js/c7aa8209785cc5a39c4231e683f6a2d1b1e91153/sfo.js" for="release"></script-->
<script src="https://raw.githack.com/KuromeSan/sfo.js/master/sfo.js" for="develop"></script>
<div>Local version: <input type="file" /></div>
<div>Remote version: <button onclick="goremote()">Go remote</button></div>
附言似乎我用于远程示例的
gofile.io
服务有时不可见。如果您有指向 param.sfo 的永久链接,请告诉我。但现在我必须
访问我的文件
,然后它才会可见。
Anton
2020-08-25
您正在使用一些已有 20 年历史的 JavaScript。 请使用 fetch 添加 TextEncoder 来确保自己的理智。
fetch(url).then(res => res.json().then(data => {
const encoder = new TextEncoder()
const bytes = encoder.encode(data)
parse_sfo(data)
})
Konrad
2020-08-20
sfoBytes 应该是 sfo 文件的实际数组缓冲区。它比您尝试的更简单,您不需要使用 stringToArrayBuffer 转换请求响应,因为您可以从 XMLHttpRequest 获取数组缓冲区。此外,SFO 文件不是文本文件,它是二进制文件,因此从字符串转换无论如何都行不通。
更改您的请求以获取 arraybuffer 响应类型应该这样做:
function testing(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = "arraybuffer";
request.send(null);
if (request.status === 200) {
console.log(request.response);
var response = request.response;
var sfo = parse_sfo(response);
} else {
alert('Error!');
}
}
Julien Grégoire
2020-08-23