Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
精确的JSON文本编码检测_Json - Fatal编程技术网

精确的JSON文本编码检测

精确的JSON文本编码检测,json,Json,在RFC4627中,描述了当BOM不存在时识别Unicode编码的方法。这依赖于JSON文本中的前2个字符始终是ASCII字符。但在RFC7159中,规范将JSON文本定义为“ws-value-ws”;这意味着单个字符串值也是有效的。因此,第一个字符将是开头的引号,但随后可以是字符串中允许的任何Unicode字符。考虑到RFC7159也不鼓励使用BOM;并且不再描述从前4个八位字节(字节)检测编码的过程,应该如何检测它?UTF-32仍应如RFC4627中所述正常工作,因为第一个字符是四个字节,并

在RFC4627中,描述了当BOM不存在时识别Unicode编码的方法。这依赖于JSON文本中的前2个字符始终是ASCII字符。但在RFC7159中,规范将JSON文本定义为“ws-value-ws”;这意味着单个字符串值也是有效的。因此,第一个字符将是开头的引号,但随后可以是字符串中允许的任何Unicode字符。考虑到RFC7159也不鼓励使用BOM;并且不再描述从前4个八位字节(字节)检测编码的过程,应该如何检测它?UTF-32仍应如RFC4627中所述正常工作,因为第一个字符是四个字节,并且仍应为ASCII,但UTF-16呢?第二个(2字节)字符可能不包含零字节,以帮助识别正确的编码。

在看了几年前我所做的一个实现之后,我可以看出,考虑到以下假设,仅从一个字符就可以毫不含糊地检测给定的Unicode方案:

  • 输入必须是Unicode
  • 第一个字符必须是ASCII
  • 必须没有物料清单
考虑这一点:

假设第一个字符是
“[”
(0x5B)-ASCII码。 然后,我们可以得到这些字节模式:

UTF_32LE:    5B 00 00 00  
UTF_32BE:    00 00 00 5B
UTF_16LE:    5B 00 xx xx
UTF_16BE:    00 5B xx xx
UTF_8:       5B xx xx xx
其中“xx”是
EOF
或任何其他字节

我们还应该注意,根据RFC7159,最短的有效JSON只能是一个字符,也就是说,它可能是1、2或4字节,这取决于Unicode方案

如果有帮助的话,这里有一个C++实现:

namespace json {

    //
    //  Detect Encoding
    //
    // Tries to determine the Unicode encoding of the input starting at 
    // first. A BOM shall not be present (you might check with function 
    // json::unicode::detect_bom() whether there is a BOM, in which case 
    // you don't need to call this function when a BOM is present).
    //
    // Return values:
    // 
    //   json::unicode::UNICODE_ENCODING_UTF_8
    //   json::unicode::UNICODE_ENCODING_UTF_16LE
    //   json::unicode::UNICODE_ENCODING_UTF_16BE
    //   json::unicode::UNICODE_ENCODING_UTF_32LE
    //   json::unicode::UNICODE_ENCODING_UTF_32BE
    //
    //  -1:     unexpected EOF
    //  -2:     unknown encoding
    //
    // Note:
    // detect_encoding() requires to read ahead a few bytes in order to deter-
    // mine the encoding. In case of InputIterators, this has the consequences
    // that these iterators cannot be reused, for example for a parser.
    // Usually, this requires to reset the istreambuff, that is using the 
    // member functions pubseekpos() or pupseekoff() in order to reset the get 
    // pointer of the stream buffer to its initial position.
    // However, certain istreambuf implementations may not be able to set the    
    // stream pos at arbitrary positions. In this case, this method cannot be
    // used and other edjucated guesses to determine the encoding may be
    // needed.

    template <typename Iterator>    
    inline int 
    detect_encoding(Iterator first, Iterator last) 
    {
        // Assuming the input is Unicode!
        // Assuming first character is ASCII!

        // The first character must be an ASCII character, say a "[" (0x5B)

        // UTF_32LE:    5B 00 00 00
        // UTF_32BE:    00 00 00 5B
        // UTF_16LE:    5B 00 xx xx
        // UTF_16BE:    00 5B xx xx
        // UTF_8:       5B xx xx xx

        uint32_t c = 0xFFFFFF00;

        while (first != last) {
            uint32_t ascii;
            if (static_cast<uint8_t>(*first) == 0)
                ascii = 0; // zero byte
            else if (static_cast<uint8_t>(*first) < 0x80)
                ascii = 0x01;  // ascii byte
            else if (*first == EOF)
                break;
            else
                ascii = 0x02; // non-ascii byte, that is a lead or trail byte
            c = c << 8 | ascii;
            switch (c) {
                    // reading first byte
                case 0xFFFF0000:  // first byte was 0
                case 0xFFFF0001:  // first byte was ASCII
                    ++first;
                    continue;
                case 0xFFFF0002:
                    return -2;  // this is bogus

                    // reading second byte
                case 0xFF000000:    // 00 00 
                    ++first;
                    continue;
                case 0xFF000001:    // 00 01
                    return json::unicode::UNICODE_ENCODING_UTF_16BE;
                case 0xFF000100:    // 01 00
                    ++first;
                    continue;
                case 0xFF000101:    // 01 01
                    return json::unicode::UNICODE_ENCODING_UTF_8;

                    // reading third byte:    
                case 0x00000000:  // 00 00 00
                case 0x00010000:  // 01 00 00  
                    ++first;
                    continue;                    
                    //case 0x00000001:  // 00 00 01  bogus
                    //case 0x00000100:  // 00 01 00  na
                    //case 0x00000101:  // 00 01 01  na
                case 0x00010001:  // 01 00 01 
                    return json::unicode::UNICODE_ENCODING_UTF_16LE;

                    // reading fourth byte    
                case 0x01000000:
                    return json::unicode::UNICODE_ENCODING_UTF_32LE;
                case 0x00000001:
                    return json::unicode::UNICODE_ENCODING_UTF_32BE;

                default:
                    return -2;  // could not determine encoding, that is,
                                // assuming the first byte is an ASCII.
            } // switch
        }  // while 

        // premature EOF
        return -1;
    }
}
namespace-json{
//
//检测编码
//
//尝试确定从处开始的输入的Unicode编码
//首先,BOM不应存在(您可以通过功能检查)
//json::unicode::detect_bom()是否存在bom,在这种情况下
//当存在BOM表时,不需要调用此函数)。
//
//返回值:
// 
//json::unicode::unicode\u编码\u UTF\u 8
//json::unicode::unicode\u编码\u UTF\u 16LE
//json::unicode::unicode\u编码\u UTF\u 16BE
//json::unicode::unicode\u编码\u UTF\u 32LE
//json::unicode::unicode\u编码\u UTF\u 32BE
//
//-1:意外的EOF
//-2:未知编码
//
//注:
//detect_encoding()需要先读取几个字节才能确定-
//对编码进行挖掘。如果是InputIterator,则会产生以下后果
//这些迭代器不能被重用,例如对于解析器。
//通常,这需要重置istreambuff,即使用
//成员函数pubsekpos()或pupseeekoff()以重置get
//流缓冲区指向其初始位置的指针。
//但是,某些istreambuf实现可能无法设置
//任意位置的流pos。在这种情况下,无法使用此方法
//用于确定编码的猜测可能是
//需要。
模板
内联整数
检测_编码(迭代器优先,迭代器最后)
{
//假设输入是Unicode!
//假设第一个字符是ASCII!
//第一个字符必须是ASCII字符,例如“[”(0x5B)
//联合技术消防队:50亿
//UTF_32BE:00 5B
//联合技术消防队:5B 00 xx xx
//UTF_16BE:00 5B xx xx
//UTF_8:5B xx xx xx
uint32_t c=0xFFFFFF00;
while(第一个!=最后一个){
uint32_t ascii;
if(静态_转换(*第一)==0)
ascii=0;//零字节
否则如果(静态_转换(*第一个)<0x80)
ascii=0x01;//ascii字节
else if(*first==EOF)
打破
其他的
ascii=0x02;//非ascii字节,即前导字节或尾随字节

c=c有趣的问题。当然,确定Unicode方案更具挑战性。例如,一个单字节,其ASCII值是一个数字,也是一个有效的JSON:它是UTF-8中的一个数字。提出一个解决方案怎么样,我们可以讨论你的解决方案吗?恐怕我没有一个可靠的方案。显然是第一个t检查BOM以防万一。下一步检查UTF-32-如果前3个字节为零,则为UTF-32BE,否则如果第一个字节后的3个字节为零,则为UTF-32LE。到目前为止,我们应该能够依赖测试,但现在问题来了。要测试UTF-16,我们仍然必须查看4个字节。如果我们可以假设前2个字符是alwaYES ASCII,然后我们测试UTF 16BE的第一个和第三个字节,UTF 16LE的第二个和第四个字节。但是如果第二个字符可以是非ASCII,那么,如果我用C++实现了一个头来检测编码,它会有帮助吗?据我所知,您不需要BOM检测-但是我有一个实现了I。任何C++都能提供可靠的检测,谢谢。它也可以是伪代码,我需要的是测试的步骤。谢谢代码。我的原始代码遵循在FC4627中描述的程序,它在前4个字节中看如下:00 00×00 xx UTF 32 BE,00 XX 00 XX UTF 16BE,XX 00 00 00 UTF 32 LE,XX 00 x。x 00 UTF-16LE,xx xx xx xx UTF-8。RFC 7159允许单个字符串值,当使用UTF-16时,可以得到类似00 xx xx 00或xx 00 xx的值。因此,我只是将我的更改如下:00 00 00 xx UTF-32BE,xx 00 00 00 UTF-32LE,00 xx UTF-16BE,xx 00 UTF-16LE,所有其他UTF-8。据我所知,您的代码是uld按原样工作。