题外话:关于C#读取文件编码那些事,能不改写一段代码进quicker呀。

动作需求 · 1060 次浏览
紫cm煞 创建于 2023-03-08 11:14

代码来源:NET(C#):关于正确读取中文编码文件 - 雪域月光 - 博客园 (cnblogs.com)

static void Main()
{
    PrintText("gb2312.txt");
    PrintText("unicode.txt");
}

//根据文件自动觉察编码并输出内容
static void PrintText(string path)
{
    var enc = GetEncoding(path, Encoding.GetEncoding("GB2312"));
    using (var sr = new StreamReader(path, enc))
    {
        Console.WriteLine(sr.ReadToEnd());
    }
}

/// <summary>
/// 根据文件尝试返回字符编码
/// </summary>
/// <param name="file">文件路径</param>
/// <param name="defEnc">没有BOM返回的默认编码</param>
/// <returns>如果文件无法读取,返回null。否则,返回根据BOM判断的编码或者缺省编码(没有BOM)。</returns>
static Encoding GetEncoding(string file, Encoding defEnc)
{
    using (var stream = File.OpenRead(file))
    {
        //判断流可读?
        if (!stream.CanRead)
            return null;
        //字节数组存储BOM
        var bom = new byte[4];
        //实际读入的长度
        int readc;

        readc = stream.Read(bom, 0, 4);

        if (readc >= 2)
        {
            if (readc >= 4)
            {
                //UTF32,Big-Endian
                if (CheckBytes(bom, 4, 0x00, 0x00, 0xFE, 0xFF))
                    return new UTF32Encoding(true, true);
                //UTF32,Little-Endian
                if (CheckBytes(bom, 4, 0xFF, 0xFE, 0x00, 0x00))
                    return new UTF32Encoding(false, true);
            }
            //UTF8
            if (readc >= 3 && CheckBytes(bom, 3, 0xEF, 0xBB, 0xBF))
                return new UTF8Encoding(true);

            //UTF16,Big-Endian
            if (CheckBytes(bom, 2, 0xFE, 0xFF))
                return new UnicodeEncoding(true, true);
            //UTF16,Little-Endian
            if (CheckBytes(bom, 2, 0xFF, 0xFE))
                return new UnicodeEncoding(false, true);
        }

        return defEnc;
    }
}

//辅助函数,判断字节中的值
static bool CheckBytes(byte[] bytes, int count, params int[] values)
{
    for (int i = 0; i < count; i++)
        if (bytes[i] != values[i])
            return false;
    return true;
}

上面代码,对于Unicode文本,GetEncoding方法会返回UTF16编码(更具体:还会根据BOM返回Big或者Little-Endian的UTF16编码),而没有BOM的文件则会返回缺省值GB2312编码。


回复内容
紫cm煞 2023-03-08 11:16
#1
  1. 歌词改格式  我自己写了一个,转出来全是乱码呀。
CL 回复 紫cm煞 2023-03-08 11:30 :

我之前找过库,要想效果比较好,都会比较大。也可以先用一些工具转换一下编码。

紫cm煞 2023-03-08 11:59
#2

好的 有批量转的工具推荐么?

咿呀杀杀 2023-03-08 14:22
#3

按道理歌词文件的编码格式都比较统一的,不需要用到自动识别吧。文件编码已知,从 A 编码 转换到 B 编码,事情就很简单了。

紫cm煞 回复 咿呀杀杀 2023-03-08 15:29 :

你看我的动作

需要保存的编码是固定的

咿呀杀杀 回复 紫cm煞 2023-03-08 15:33 :

歌词文件编码也是统一的吧?比如全是 UTF-8 ,或者全是 GB2312

紫cm煞 回复 咿呀杀杀 2023-03-08 15:35 :

不全是,有的有BOM头,有的又没有……

咿呀杀杀 回复 紫cm煞 2023-03-08 16:01 :

EmEditor 支持命令行调用

示例:自动检测编码 -> 另存为 UTF-8(无BOM)

"程序路径" "我只在乎你.lrc" /cp 1048576 /cps 65001 /ss- /sa "我只在乎你_new.lrc"

参考:FAQ: 怎么用命令行转换文件编码? (emeditor.org)

紫cm煞 回复 咿呀杀杀 2023-03-08 17:43 :

感谢,搞定了。

回复主贴