【问题标题】:Strange unicode characters when reading in file in node.js app在 node.js 应用程序中读取文件时出现奇怪的 unicode 字符
【发布时间】:2013-01-02 10:13:51
【问题描述】:

我正在尝试编写一个节点应用程序,它读取一组文件,将它们分成几行,然后将这些行放入一个数组中。很简单。它适用于很多文件,除了我正在使用的一些 SQL 文件。出于某种原因,当我拆分线路时,我似乎得到了某种 unicode 输出。该应用看起来像这样:

fs = require("fs");
var data = fs.readFileSync("test.sql", "utf8");
console.log(data);
lines = data.split("\n");
console.log(lines);

输入文件如下所示:

use whatever
go

输出如下:

��use whatever
go

[ '��u\u0000s\u0000e\u0000 \u0000w\u0000h\u0000a\u0000t\u0000e\u0000v\u0000e\u0000r\u0000',
  '\u0000g\u0000o\u0000',
  '\u0000' ]

如您所见,文件开头有某种无法识别的字符。把数据读进去直接输出后,除了这个字符外,看起来还可以。但是,如果我随后尝试将其分成几行,我会得到所有这些类似 unicode 的字符。基本上都是以“\u0000”开头的所有实际字符。

我不知道这里发生了什么,但它似乎与文件本身中的字符有关。如果我将文件的文本复制并粘贴到另一个新文件中并在新文件上运行应用程序,它工作正常。我认为在复制和粘贴过程中会删除导致此问题的任何原因。

【问题讨论】:

    标签: javascript node.js unicode utf-16 utf


    【解决方案1】:

    我在 Windows 命令提示符中执行了以下操作来转换字节顺序:

    type file.txt > file2.txt
    

    【讨论】:

    • 不仅我在解析 Apache 日志文件时使用此解决方案修复了问题,而且文件大小也减少到其原始大小的几乎一半。
    【解决方案2】:

    使用精简版的Iconv-lite

    var result= "";
    var iconv = require('iconv-lite');
    var stream = fs.createReadStream(sourcefile)
        .on("error",function(err){
            //handle error
        })
        .pipe(iconv.decodeStream('win1251'))
        .on("error",function(err){
            //handle error
        })
        .on("data",function(data){
            result += data;
        })
        .on("end",function(){
           //use result
        });
    

    【讨论】:

      【解决方案3】:

      您的文件是 UTF-16 Little Big Endian,而不是 UTF-8。

      var data = fs.readFileSync("test.sql", "utf16le"); //Not sure if this eats the BOM
      

      不幸的是 node.js 只支持 UTF-16 Little Endian 或 UTF-16LE(不能从阅读文档中确定,它们之间存在细微差别;即 UTF-16LE 不使用 BOM),所以你有使用iconv 或以其他方式将文件转换为UTF-8。

      例子:

      var Iconv  = require('iconv').Iconv,
          fs = require("fs");
      
      var buffer = fs.readFileSync("test.sql"),
          iconv = new Iconv( "UTF-16", "UTF-8");
      
      var result = iconv.convert(buffer).toString("utf8");
      

      【讨论】:

      • 哇,你成功了。谢谢你。所以只是出于好奇,你怎么知道这个文件是大端 UTF-16?有没有办法在节点中检测到它?我正在处理几个文件,但它们的编码方式并不相同。
      • @user1334007 因为偶数位置的空值,如果它们位于奇数位置,它将是小端。自动检测编码需要一些启发式方法,通过分析空位置来确定哪些 UTF-16 和 UTF-8 具有非常独特的模式。但是如果不尝试查看文本是否正确,则无法检测到大多数其他编码。
      • 仅供参考,我发现了一些看起来很有希望使用节点进行字符集检测的东西:github.com/mooz/node-icu-charset-detector。还没试过,但如果我能用,我会回来报告的。
      • @user1334007 是的,但请注意,无法可靠地检测编码。如果您有很多文件和/或无法手动检测它们,则值得尝试
      • 是的,我试过了,发现没有多大帮助。最后我用 .NET 重写了这个工具,效果更好。
      【解决方案4】:

      这可能是BOM(字节顺序标记)吗?确保在不使用 BOM 的情况下保存文件或包含删除 BOM 的代码。

      BOM 在文本编辑器中通常是不可见的。

      我知道 Notepad++ 有一个功能,您可以轻松地从文件中删除 BOMEncoding > Encode in UTF-8 without BOM.

      【讨论】:

      • 第一个字符的轮数是BOM。但是,删除它似乎并不能解决“\u0000”问题。
      • 我使用 Notepad++ 将我的文件转换为 UTF-8,然后使用 fs.readFileSync 读取文件以消除“SyntaxError: Unexpected token � in JSON at position 0”
      猜你喜欢
      • 1970-01-01
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多