`
Fangrn
  • 浏览: 821364 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

检测字节流是否是UTF8编码

阅读更多

几天前偶尔看到有人发帖子问“如何自动识别判断url中的中文参数是GB2312还是Utf-8编码”
也拜读了wcwtitxu使用巨牛的正则表达式检测UTF8编码的算法。
使用无数或条件的正则表达式用起来却是性能不高。
刚好曾经在项目中有类似的需求,这里把处理思路和整理后的源代码贴出来供大家参考
先聊聊原理:
UTF8的编码规则如下表
UTF8 Encoding Rule
看起来很复杂,总结起来如下:
ASCII码(U+0000 - U+007F),不编码
其余编码规则为
    •第一个Byte二进制以形式为n个1紧跟个0 (n >= 2), 0后面的位数用来存储真正的字符编码,n的个数说明了这个多Byte字节组字节数(包括第一个Byte)
    •结下来会有n个以10开头的Byte,后6个bit存储真正的字符编码。
    因此对整个编码byte流进行分析可以得出是否是UTF8编码的判断。
根据这个规则,我给出的C#代码如下:

/// <summary>
///   Determines whether the given <paramref name="inputStream"/>is UTF8 encoding bytes.
/// </summary>
/// <param name="inputStream">
///    The input stream.
///  </param>
/// <returns>
///   <see langword="true"/> if given bystes stream is in UTF8 encoding; otherwise, <see langword="false"/>.
/// </returns>
/// <remarks>
///   All ASCII chars will regards not UTF8 encoding.
/// </remarks>
public static bool IsTextUTF8(ref byte[] inputStream)
{
    int encodingBytesCount = 0;
    bool allTextsAreASCIIChars = true;

    for (int i = 0; i < inputStream.Length; i++)
    {
        byte current = inputStream[i];
        if ((current & 0x80) == 0x80)
        {                   
            allTextsAreASCIIChars = false;
        }
        // First byte
        if (encodingBytesCount == 0)
        {
            if ((current & 0x80) == 0)
            {
                // ASCII chars, from 0x00-0x7F
                continue;
            }
 
            if ((current & 0xC0) == 0xC0)
            {
                encodingBytesCount = 1;
                current <<= 2;
                // More than two bytes used to encoding a unicode char.
                // Calculate the real length.
                while ((current & 0x80) == 0x80)
                {
                    current <<= 1;
                    encodingBytesCount++;
                }
            }                   
            else
            {
                // Invalid bits structure for UTF8 encoding rule.
                return false;
            }
        }               
        else
        {
            // Following bytes, must start with 10.
            if ((current & 0xC0) == 0x80)
            {                       
                encodingBytesCount--;
            }
            else
            {
                // Invalid bits structure for UTF8 encoding rule.
                return false;
            }
        }
    }
    if (encodingBytesCount != 0)
    {
        // Invalid bits structure for UTF8 encoding rule.
        // Wrong following bytes count.
        return false;
    }
    // Although UTF8 supports encoding for ASCII chars, we regard as a input stream, whose contents are all ASCII as default encoding.
    return !allTextsAreASCIIChars;
}

 再附上单元测试代码:

/// <summary>
///This is a test class for EncodingHelperTest and is intended
///to contain all EncodingHelperTest Unit Tests
///</summary>
[TestClass()]
public class EncodingHelperTest
{
    /// <summary>
    ///  Normal test for this method.
    ///</summary>
    [TestMethod()]
    public void IsTextUTF8Test()
    {
        for (int i = 0; i < 1000; i++)
        {
            List<Char> chars = new List<char>();
            chars.Add('中');
 
            List<UnicodeCategory> temp = new List<UnicodeCategory>();
            Random rd = new Random((int)(DateTime.Now.Ticks & 0x7FFFFFFF));
 
            for (int j = 0; j < 255; j++)
            {
                char ch = (char)rd.Next(0xFFFF);
                UnicodeCategory uc = System.Globalization.CharUnicodeInfo.GetUnicodeCategory(ch);
                if (uc == UnicodeCategory.Surrogate || // Single surrogate could not be encoding correctly.
                    uc == UnicodeCategory.PrivateUse || // Private use blocks should be excluded.
                    uc == UnicodeCategory.OtherNotAssigned
                    )
                {
                    j--;
                }
                else
                {
                    chars.Add(ch);
                    temp.Add(uc);
                }
            }
 
            string str = new string(chars.ToArray());
 
            byte[] inputStream = Encoding.UTF8.GetBytes(str);
            bool expected = true;
            bool actual;
            actual = EncodingHelper.IsTextUTF8(ref inputStream);
            Assert.AreEqual(expected, actual, string.Format("UTF8_Assert Fails at:{0}", str));
 
            inputStream = Encoding.GetEncoding(932).GetBytes(str);
            expected = false;
 
            actual = EncodingHelper.IsTextUTF8(ref inputStream);
            Assert.AreEqual(expected, actual, string.Format("ShiftJIS_Assert Fails at:{0}", str));
        }
    }
 
    /// <summary>
    ///   Check with All ASCII chars
    /// </summary>
    [TestMethod]
    public void IsTextUTF8Test_AllASCII()
    {
        string str = "ABCDEFGHKLHSJKLDFHJKLHAJKLSHJKLHAJKLSHDJKLAHSDJKLHAJKLSDHJKLASHDJKLHASJKLDHJKLASD";
 
        byte[] inputStream = Encoding.UTF8.GetBytes(str);
        bool expected = false;
        bool actual;
        actual = EncodingHelper.IsTextUTF8(ref inputStream);
        Assert.AreEqual(expected, actual, string.Format("UTF8_Assert Fails at:{0}", str));
 
 
    }
}

 另:
如果是判断一个文件是否使用了UTF8编码,不一定非用这种方法,因为通常以UTF8格式保存的文件最初两个字符是BOM头,标示该文件使用了UTF8编码。
参考:
维基百科:http://en.wikipedia.org/wiki/UTF-8

 

其实java的操作也类似,有时间再写个

分享到:
评论

相关推荐

    字节流编码获取

    在IT领域,字节流(Byte Stream)是数据在计算机内部和网络中传输的基本单位,而编码则关乎数据如何被转换成字节流以便于处理和传输。在处理字节流编码时,我们通常会遇到诸如字符集、字节顺序标记(BOM)、解码与...

    易语言源码将文本转换为UTF-8码.rar

    例如,如果你已经知道或检测到源文本是GBK编码,你可以使用“转换编码”命令,将GBK编码的文本转换为UTF-8编码。 4. **写入UTF-8文本**:转换后的UTF-8编码文本需要保存到新的文件中,可以使用“写文本文件全部”...

    GBK 与 UTF-8 间编码转换

    编码转换的原理通常是读取原始编码的字节流,然后根据目标编码的规则重新分配字节。对于GBK到UTF-8的转换,首先需要将GBK编码的每个双字节视为一个独立的字符,然后查找对应的Unicode码点,最后按照UTF-8的规则将其...

    Convert_Utf8.zip_UTF8

    例如,我们可以创建一个`CharsetDetector`实例,然后使用它的`detect`方法来检测输入的字节流是否符合UTF8编码规范。如果需要转换,可以使用`CharsetEncoder`的`encode`方法将其他编码的字符转换为UTF8编码的字节...

    批量utf文件转utf8-bom

    "批量utf文件转utf8-bom"这个主题指的是将一批以UTF编码的文件转换为带有BOM(Byte Order Mark)的UTF-8编码。BOM是一个特殊的字节序列,用于标识文件的编码类型,对于UTF-8编码,BOM的字节序列为0xEF, 0xBB, 0xBF。...

    UTF8-无BOM转为UTF16LE

    首先,UTF8是一种广泛使用的变长Unicode字符编码,它能够表示Unicode字符集中的所有字符。UTF8的特点是前几个字节用于识别字符的范围,对于ASCII字符(英文字符和某些符号),UTF8只使用一个字节,这使得UTF8在处理...

    IDEA支持带BOM的UTF-8编码文件.rar

    BOM,即字节顺序标记,是UTF-8编码中可选的一部分,用于标识数据流的字节顺序。在大多数情况下,BOM在UTF-8编码中并不必要,因为它默认是小端序,但对于某些程序或系统,BOM可能有助于识别文件的编码方式。 在处理...

    UTF8.rar_UTF8_字符编码转换

    UTF-8是一种广泛使用的Unicode字符编码方案,它可以表示Unicode标准中的所有字符,且在互联网上被普遍采用。在这个压缩包中,我们有三个文件:UTF8.cpp、yufa100.txt和TestPrj.txt。 UTF8.cpp很可能是一个C++源代码...

    判断文本编码是否为UTF-8格式易语言源码例子-易语言

    UTF-8是一种广泛使用的字符编码标准,尤其在互联网上,几乎所有的网页都采用UTF-8编码。这个"判断文本编码是否为UTF-8格式易语言源码例子"是一个针对初学者的教程,旨在教授如何在易语言中识别和验证文本文件的编码...

    深入UTF8字符编码

    例如,Unicode字符集包含了许多字符,而UTF-8是Unicode的一个实现,规定了如何用8位字节来编码这些字符。 7. 实际应用: 在开发跨平台、多语言的应用时,理解UTF-8的细节非常关键。例如,数据库存储、网页设计、...

    Java解决UTF-8的BOM问题

    UTF-8是一种广泛使用的Unicode字符编码方式,它能够表示世界上几乎所有的字符。然而,UTF-8有一个特殊的形式,即带BOM(Byte Order Mark)的UTF-8,这个BOM在某些情况下可能会引发问题。本文将详细探讨Java中如何...

    pb12 gb转utf-8

    UTF-8是一种多字节的Unicode编码方式,可以表示世界上几乎所有的字符,包括各种语言的字符。它是互联网上最常用的字符编码格式,因为它兼容ASCII,并且在处理多种语言时具有良好的通用性。 转换“pb12 gb转utf-8”...

    UTF8编码和西里尔文编码转化源代码

    3. 重新编码:然后,根据目标编码方式,将字符序列重新编码为新的字节流。 4. 写入新文件:最后,将新编码的字节流写入目标文件。 在实际应用中,这个过程可能会涉及到更复杂的处理,比如错误检测和恢复,以及处理...

    utf-8 互转 gb2312 转码

    UTF-8(8位Unicode转换格式)是一种广泛使用的多字节字符编码方案,它兼容ASCII编码并能表示Unicode字符集中的所有字符。UTF-8最大的优点在于其前128个字符与ASCII编码完全一致,因此在英语为主的系统和网络中非常...

    Java源码编码转换器 GBK TO UTF8 UTF8 To GBK(无源码)

    GBK是中文环境下广泛使用的编码方式,而UTF-8是一种更为通用的多语言编码格式,支持全球各种字符集。由于历史原因或特定系统需求,开发者可能需要在两者之间进行转换。 这款工具的一大特点在于它能自动检测文件的...

    网页文件批量gbk转UTF8

    在实际操作中,GBK转UTF-8的过程包括读取GBK编码的文件,对每个字节流进行解码得到对应的字符,然后按照UTF-8的编码规则重新编码成新的字节流,最后将这个字节流写入新的文件。由于GBK和UTF-8编码方式的不同,直接...

    UTF-8编码格式转换

    2. **读取UTF-8**:在C/C++中,可以使用标准库如`fread`或`scanf`来读取文件内容,但由于它们默认处理的是字节流,因此需要额外的逻辑来识别UTF-8编码的字符边界。 3. **写入UTF-8**:类似地,`fwrite`和`fprintf`...

    utf-8 中文字符表

    在网络通信中,数据通常以字节流的形式传输,因此正确解析UTF-8编码的字符至关重要,避免因编码问题导致的信息丢失或误解。 总的来说,UTF-8中文字符表是一个非常实用的工具,它对于跨平台的Web开发和系统间的文本...

    gb转utf8,gb转utf8

    - **编码**:用`UTF-8`编码规则将Unicode字符序列重新编码成字节流。 - **写入文件**:将新的字节流写入新的`UTF-8`文件。 5. **工具与编程语言支持** 许多编程语言如Python、Java、JavaScript等都有内置函数...

Global site tag (gtag.js) - Google Analytics