如何在文件中写入/读取BigUint64Array



我试图将字符串中的内容编码为BigUint64,并将其写入文件以供进一步使用。BigInt不能使用JSON进行字符串化,所以我直接写为BigUint64Array。

然而,当我想读取文件并恢复BigUint64Array时,我收到了一个缓冲区,问题是我不知道如何将缓冲区转换为BigUint64阵列

const { writeFileSync, readFileSync } = require('node:fs')
const st = new Set([1n, 2n, 3n, 1n, 1n, 1n])
const A = BigUint64Array.from(st)
console.log(A)
writeFileSync('./abc', A)
let x = readFileSync('./abc')
x = BigUint64Array.from(x)
console.log(x)

当我尝试运行此代码时,我会收到

node .test.js
BigUint64Array(3) [ 1n, 2n, 3n ]
R:mahjongFYP22070test.js:9
x = BigUint64Array.from(x)
^
TypeError: Cannot convert 1 to a BigInt
at Function.from (<anonymous>)
at Object.<anonymous> (R:mahjongFYP22070test.js:9:20)
at Module._compile (node:internal/modules/cjs/loader:1159:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
at Module.load (node:internal/modules/cjs/loader:1037:32)
at Module._load (node:internal/modules/cjs/loader:878:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:23:47

writeFileSync允许您指定任何类型的数组,并将其缓冲区(数组的字节)写入文件,但从readFileSync返回的是Buffer,据我所知,没有直接的方法将该缓冲区的字节转换为BigUint64Array。但有一条非常接近的直接路径:通过Uint8Array,并使用该数组的缓冲区构建BigUint64Array(这样我们就不会额外复制数据):

function readBigUint64FromFileSync(fileName) {
const bytes = Uint8Array.from(readFileSync(fileName));
return new BigUint64Array(bytes.buffer);
}

这不会为从Uint8ArrayBigUint64Array的转换生成额外的副本,但它确实生成了一个副本(Buffer=>Uint8Array)。我们可以通过查看文件的大小、分配该大小的Uint8Array并将文件读取到其中来避免这种情况:

function readBigUint64FromFileSync(fileName) {
const { size } = statSync(fileName);
const bytes = new Uint8Array(size);
const handle = openSync(fileName);
try {
readSync(handle, bytes);
return new BigUint64Array(bytes.buffer);
} finally {
closeSync(handle);
}
}

如果你在一个文件可能由另一个进程主动写入的环境中这样做,你会想要实现某种保护,这样我们就看不到文件的一个版本的大小,而是看到文件的另一个版本。但如果没有,以上就足够了。

完整示例:

const { writeFileSync, openSync, statSync, readSync, closeSync } = require('node:fs');
function writeBigUint64ToFileSync(array, fileName) {
writeFileSync(fileName, array);
}
function readBigUint64FromFileSync(fileName) {
const { size } = statSync(fileName);
const bytes = new Uint8Array(size);
const handle = openSync(fileName);
try {
readSync(handle, bytes);
return new BigUint64Array(bytes.buffer);
} finally {
closeSync(handle);
}
}
const st = new Set([1n, 2n, 3n, 1n, 1n, 1n]);
const original = BigUint64Array.from(st);
writeBigUint64ToFileSync(original, "./abc");
console.log(original);
const fromFile = readBigUint64FromFileSync("./abc");
console.log(fromFile);
console.log(`Same? ${original.length === fromFile.length && original.every((n, i) => fromFile[i] === n)}`);

(或者,如果可以复制一份数据,则交换readBigUint64FromFileSync的更简单版本。)

您可以将BigInt转换为字符串,然后再将其提供给JSON.stringify(类似)

const st = new Set([1n, 2n, 3n, 1n, 1n, 1n])
const converted = Array.from(st.values()).map(current => current.toString());
writeFileSync('./abc', JSON.stringify(A));

要转换到另一个方向,只需执行BigInt(yourString)即可将它们转换回BigInts

最新更新