使用Node.js检查文件是二进制还是ASCII格式?

29

我想知道使用Node.js如何最好地检查文件是二进制还是ASCII码?

似乎有两种不特定于node.js的方法:

  1. 检查MIME类型:如何检查PHP中的文件是否为ASCII或二进制 - 但这有其问题,例如预处理器通常没有被识别的MIME类型,在使用 mime 检查它们时会回退到application/octet-stream.

  2. 通过使用流缓冲区检查字节大小:如何将文件内容标识为ASCII或二进制 - 这似乎相当费力,并且还没有提供node.js示例。

那么是否已经有另一种方法呢?也许有一个我不知道的秘密node.js调用或模块吗?或者如果我必须自己做,那应该采用什么方式?

谢谢


你能定义一下“二进制文件”的含义吗?你测试的方式取决于你所指的具体含义,而且并没有普遍认可的定义。 - David Schwartz
假设一个图片,或者更具体地说,任何不是文本的东西。对此我很抱歉! - balupton
当然。问题在于似乎有几种方法,但我不确定其中任何一种如何移植到Node.js。您的建议听起来很好,因此我很乐意接受,并提供一个代码示例来说明如何执行此类检查 - 因为文档并没有清楚地说明这样的检查是如何进行的(这些字节是否为ASCII)。 - balupton
唯一的方法是检查是否存在大于127的字节,否则就不行。 - Gabriel Llamas
好问题!但是非ASCII文本文件怎么办?比如UTF-8或其他什么东西?我认为问题的意图是决定一个文件是否包含某种“文本”...还是不包含。有没有其他方法?即使是不太完美的策略?假设你正在创建某种“文件浏览器”,并且你想可能显示内容的“预览”(如果它是文本)。 - Nick Perkins
显示剩余4条评论
4个回答

15

2
如果您的意图确实是要识别一般文本文件而不是特定的ASCII编码,请考虑更新您的问题。 - maerics
21
CoffeeScript 阻止人们轻松提交补丁,因此您不必维护太多。 - André Fiedler
2
不管价值如何,istextorbinary现在是JavaScript。 - balupton
请注意,自从node.js引入了buffer.isUtf8(input)buffer.isAscii(input)的API函数后(添加于:node.js v19.4.0、v18.14.0以及v19.6.0、v18.15.0),现在可能会更容易一些。详情请参阅:https://nodejs.org/api/buffer.html#bufferisutf8input -- 还可以查看https://dev59.com/-n4QtIcB2Jgan1znrH_I - Mörre

5

ASCII定义了0-127的字符,因此,如果文件的全部内容都是该范围内的字节值,则可将其视为ASCII文件。

function fileIsAscii(filename, callback) {
  // Read the file with no encoding for raw buffer access.
  require('fs').readFile(filename, function(err, buf) {
    if (err) throw err;
    var isAscii = true;
    for (var i=0, len=buf.length; i<len; i++) {
      if (buf[i] > 127) { isAscii=false; break; }
    }
    callback(isAscii); // true iff all octets are in [0, 127].
  });
}
fileIsAscii('/usr/share/dict/words', function(x){/* x === true */});
fileIsAscii('/bin/ls', function(x){/* x === false */});

如果性能至关重要,则考虑根据链接答案编写自定义的C++函数。

3

我从谷歌来到这里,但是由于没有找到令人满意的答案,我采取了另一种方法,这对我很有效:

const string_to_test = "I am just a piece of text";
//const binary_to_test = "��˰!1�H��1�1����!H�=u�!�";
if(/\ufffd/.test(string_to_test) === true){
    console.log("I'm 'binary'");
}else{
    console.log("I'm proper text");
}

如果您尝试以普通方式(不使用十六进制编辑器)打开二进制数据,则会遇到一些渲染问题,这些问题会转化为一系列奇怪的字符“替换字符”(Replacement character),无法正常显示。

这只是一些编辑器和浏览器将二进制显示为文本的方式。JavaScript字符串本身(除非您从文本区域或其他读取二进制数据的文本中获取它)只会有0-255之间的值,永远不会有ufffd。Firefox不会转换为相同的字符。它使用特殊字体来显示字符代码值。 - aamarks
当您使用utf-8获取某些地方的文本并尝试在使用较旧代码页的页面中使用它时,该字符替换也可能出现缺少这些字符,因此它不一定是二进制的指示。 - aamarks
我该如何将二进制解码为图像?我在做这个过程中遇到了麻烦,以下是我的问题链接。 https://stackoverflow.com/questions/54939990/decode-binary-of-image-to-base64 - Shoib Mohammed A

0

或者通过管道传递转换器,并使用一次“数据”事件来设置编码...

const { Transform, pipeline } = require('stream'),
      { createReadStream, createWriteStream } = require('fs')

const parser = Transform({
    readableObjectMode: false ,
    writableObjectMode: false,
    transform(data, encoding,  callback) {
        callback(null, data)
    }
 })
parser.once('data', (chunk) => {
    let bin = /\ufffd/
    bin.test(chunk)
        ? parser.encoding = 'utf8'
        : parser.encoding = 'binary'
})
parser.on('data', (d) => parser._transform(d, 'binary', () => {}))
const file = createReadStream('./media-tests/uni.png')
const file2 = createWriteStream('./media-tests/uni2.png')
pipeline(file,parser, file2, ()=>{})

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