当转换通过GCDAsyncSocket重新接收的NSData时,有时它返回nil,但是使用python就可以了

时间:2014-05-07 01:00:40

标签: objective-c encoding nsstring nsdate

转换通过GCDAsyncSocket重新接收的NSData时,有时会返回nil

 - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        DDLogInfo(@"socket:%p didReadData:withTag:%ld", sock, tag);

        NSString *httpResponse = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

        httpResponse = [NSString stringWithUTF8String:[data bytes]];

        if(httpResponse==nil || [httpResponse isEqual:[NSNull null]]){
            DDLogInfo(@"server response:%@\n data=%lu\n", httpResponse,data.length);
        }

    }

但是当我从下面的日志中复制数据并使用python进行转换时就可以了。

bytes="72657370 6f6e7365 3a737461 742d726f ......"
bytes = bytes.replace(" ","");
ss = bytes.decode("hex");
print ss;

(lldb)po数据 < 72657370 6f6e7365 3a737461 742d726f 6f6d2c7b 22646e75 6d223a31 30302c22 6465736b 73223a5b 7b223122 3a312c22 32223a31 38307d2c 7b223122 3a322c22 32223a31 38307d2c 7b223122 3a332c22 32223a31 38307d2c 7b223122 3a342c22 32223a36 307d2c7b 2231223a 352c2232 223a3138 307d2c7b 2231223a 362c2232 223a3138 307d2c7b 2231223a 372c2232 223a3138 307d2c7b 2231223a 382c2232 223a3138 307d2c7b 2231223a 392c2232 223a3138 307d2c7b 2231223a 31302c22 32223a31 38307d2c 7b223122 3a31312c 2232223a 3138307d 2c7b2231 223a3132 2c223222 3a313830 7d2c7b22 31223a31 332c2232 223a3132 307d2c7b 2231223a 31342c22 32223a31 38307d2c 7b223122 3a31352c 2232223a 3138307d 2c7b2231 223a3136 2c223222 3a313830 7d2c7b22 31223a31 372c2232 223a3138 307d2c7b 2231223a 31382c22 32223a31 38307d2c 7b223122 3a31392c 2232223a 3138307d 2c7b2231 223a3230 2c223222 3a313830 7d2c7b22 31223a32 312c2232 223a3138 307d2c7b 2231223a 32322c22 32223a31 38307d2c 7b223122 3a32332c 2232223a 3138307d 2c7b2231 223a3234 2c223222 3a313830 7d2c7b22 31223a 32 352c2232 223a3138 307d2c7b 2231223a 32362c22 32223a31 38307d2c 7b223122 3a32372c 2232223a 3138307d 2c7b2231 223a3238 2c223222 3a313830 7d2c7b22 31223a32 392c2232 223a3138 307d2c7b 2231223a 33302c22 32223a31 38307d2c 7b223122 3a33312c 2232223a 3138307d 2c7b2231 223a3332 2c223222 3a313830 7d2c7b22 31223a33 332c2232 223a3138 307d2c7b 2231223a 33342c22 32223a31 38307d2c 7b223122 3a33352c 2232223a 3138307d 2c7b2231 223a3336 2c223222 3a313830 7d2c7b22 31223a33 372c2232 223a3138 307d2c7b 2231223a 33382c22 32223a31 38307d2c 7b223122 3a33392c 2232223a 3138307d 2c7b2231 223a3430 2c223222 3a313830 7d2c7b22 31223a34 312c2232 223a3138 307d2c7b 2231223a 34322c22 32223a31 38307d2c 7b223122 3a34332c 2232223a 3138307d 2c7b2231 223a3434 2c223222 3a313830 7d2c7b22 31223a34 352c2232 223a3138 307d2c7b 2231223a 34362c22 32223a31 38307d2c 7b223122 3a34372c 2232223a 3138307d 2c7b2231 223a3438 2c223222 3a313830 7d2c7b22 31223a34 392c2232 223a3138 307d2c7b 2231223a 35302c22 32223a31 38307d2c 7b223122 3a35312 Ç2232223a 3138307d 2c7b2231 223a3532 2c223222 3a313830 7d2c7b22 31223a35 332c2232 223a3138 307d2c7b 2231223a 35342c22 32223a31 38307d2c 7b223122 3a35352c 2232223a 3138307d 2c7b2231 223a3536 2c223222 3a313830 7d2c7b22 31223a35 372c2232 223a3138 307d2c7b 2231223a 35382c22 32223a31 38307d2c 7b223122 3a35392c 2232223a 3138307d 2c7b2231 223a3630 2c223222 3a313830 7d2c7b22 31223a36 312c2232 223a3138 307d2c7b 2231223a 36322c22 32223a31 38307d2c 7b223122 3a36332c 2232223a 3138307d 2c7b2231 223a3634 2c223222 3a313830 7d2c7b22 31223a36 352c2232 223a3138 307d2c7b 2231223a 36362c22 32223a31 38307d2c 7b223122 3a36372c 2232223a 3138307d 2c7b2231 223a3638 2c223222 3a313830 7d2c7b22 31223a36 392c2232 223a3138 307d2c7b 2231223a 37302c22 32223a31 38307d2c 7b223122 3a37312c 2232223a 3138307d 2c7b2231 223a3732 2c223222 3a313830 7d2c7b22 31223a37 332c2232 223a3138 307d2c7b 2231223a 37342c22 32223a31 38307d2c 7b223122 3a37352c 2232223a 3138307d 2c7b2231 223a3736 2c223222 3a313830 7d2c7b22 31223a37 372c2232 223a3138 307d2c7b 2231223a 37382c22 32223a31 38307d2c 7b223122 3a37392c 2232223a 3138307d 2c7b2231 223a3830 2c223222 3a313830 7d2c7b22 31223a38 312c2232 223a3138 307d2c7b 2231223a 38322c22 32223a31 38307d2c 7b223122 3a38332c 2232223a 3138307d 2c7b2231 223a3834 2c223222 3a313830 7d2c7b22 31223a38 352c2232 223a3138 307d2c7b 2231223a 38362c22 32223a31 38307d2c 7b223122 3a38372c 2232223a 3138307d 2c7b2231 223a3838 2c223222 3a313830 7d2c7b22 31223a38 392c2232 223a3138 307d2c7b 2231223a 39302c22 32223a31 38307d2c 7b223122 3a39312c 2232223a 3138307d 2c7b2231 223a3932 2c223222 3a313830 7d2c7b22 31223a39 332c2232 223a3138 307d2c7b 2231223a 39342c22 32223a31 38307d2c 7b223122 3a39352c 2232223a 3138307d 2c7b2231 223a3936 2c223222 3a313830 7d2c7b22 31223a39 372c2232 223a3138 307d2c7b 2231223a 39382c22 32223a31 38307d2c 7b223122 3a39392c 2232223a 3138307d 2c7b2231 223a3130 302c2232 223a3138 307d5d7d 0d0a0d0a

1 个答案:

答案 0 :(得分:0)

找出根本原因,那是因为当服务器发回一个坏的(格式不正确的)UTF8字符串时,函数" [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];"不能正确处理问题,但python可以。所以我自己实现函数将utf8字节数组转换为Unicode字节数组,同时删除坏的utf8字节,然后从unicode字节数组转换为字符串。下面是函数,希望能帮助别人遇到同样的问题。

+(NSData *)Utf82Unicode:(NSData *)utf8Data {

//-------------------------------------------------------------------------------------------
//参数有效性判断

if(utf8Data == nil) return nil;



int totalNum = 0;
Byte *p = [utf8Data bytes];
int insize = [utf8Data length];

int i=0;
while(i<insize)
{
    if (*p >= 0x00 && *p <= 0x7f)//说明最高位为'0',这意味着utf8编码只有1个字节!
    {
        p++;
        totalNum += 1;
        i++;
    }
    else if ((*p & (0xe0))== 0xc0)//只保留最高三位,看最高三位是不是110,如果是则意味着utf8编码有2个字节!
    {
        p++;
        p++;
        totalNum += 1;
                    i++;
                    i++;
    }
    else if ((*p & (0xf0))== 0xe0)//只保留最高四位,看最高三位是不是1110,如果是则意味着utf8编码有3个字节!
    {
        p++;
        p++;
        p++;
        totalNum += 1;
                    i++;
                    i++;
                    i++;
    }
}

Byte* outBytes = malloc(totalNum*2+2);

//for unicode 添加fffe头


outBytes[0]=0xff;
outBytes[1]=0xfe;



//------------------------------------------------
int resultsize = 0;

p = [utf8Data bytes];
Byte* tmp = (Byte *)outBytes;

tmp++;
tmp++;

//

while(resultsize<totalNum)
{
    if (*p >= 0x00 && *p <= 0x7f)//说明最高位为'0',这意味着utf8编码只有1个字节!
    {
        *tmp = *p;
        tmp++;
        *tmp = '\0';
        tmp++;
        resultsize += 1;
    }
    else if ((*p & 0xe0)== 0xc0)//只保留最高三位,看最高三位是不是110,如果是则意味着utf8编码有2个字节!
    {

        char t1 = 0;
        char t2 = 0;


        t1 = *p & (0x1f);//高位的后5位!(去除了头部的110这个标志位)
        p++;

        //检查是否utf8被异常截断
        if((*p & 0xc0)!=0x80){
            p--;
            t2=0x3f;
            *tmp = 'X';
            tmp++;
            *tmp='\0';
            tmp++;
        }else{
            t2 = *p & (0x3f);//低位的后6位!(去除了头部的10这个标志位)

            *tmp = t2 | ((t1 & (0x03)) << 6);
            tmp++;
            *tmp = t1 >> 2;//留下其保留的三位
            tmp++;
            resultsize += 1;
        }

    }
    else if ((*p & (0xf0))== 0xe0)//只保留最高四位,看最高三位是不是1110,如果是则意味着utf8编码有3个字节!
    {

        wchar_t t1 = 0;
        wchar_t t2 = 0;
        wchar_t t3 = 0;
        t1 = *p & (0x1f);
        p++;

        //检查是否utf8被异常截断
        if((*p & 0xc0)!=0x80){
            p--;
            *tmp = 'X';
            tmp++;
            *tmp='\0';
            tmp++;
        }else{
            t2 = *p & (0x3f);
            p++;

            if((*p & 0xc0)!=0x80){
                p--;
                *tmp = 'X';
                tmp++;
                *tmp='\0';
                tmp++;
            }else{
                t3 = *p & (0x3f);

                *tmp = ((t2 & (0x03)) << 6) | t3;
                tmp++;
                *tmp = (t1 << 4) | (t2 >> 2);
                tmp++;
            }

        }
        resultsize += 1;
    }
    p++;
}
/*不考虑结束符,如果考虑则打开此段!
 *tmp = '/0';
 tmp++;
 *tmp = '/0';
 resultsize += 2;
 */
NSData* dataOut = [NSData dataWithBytes:outBytes length:totalNum*2+2];
free(outBytes);
return dataOut;

}