异步NSURLConnection在每个字节之间接收空字节

时间:2014-04-14 20:01:10

标签: ios objective-c xml cocoa-touch nsurlconnection

我尝试从服务器获取XML文档,但我在明文中获得的响应只是ÿþ<

我发现,通过读取NSData的HEX数据,在前三个字节之后的内容是我想要的整个响应,但每个字节之间都有一个nullbyte。现在,我可以从这些字节中删除数据,但是如果我使用Netcat获得相同的数据,那么就没有nullbytes,所以我认为我的代码有问题。

我发送了与iPad模拟器发送的完全相同的标题,但从那里看起来一切正常。这是我用来获取XML数据的代码:

NSString *postData = @"SomePostData";
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *URLString = [NSString stringWithFormat:@"https://www.example.com/xmlexport?sessionid=%@", sessionID];
[request setURL:[NSURL URLWithString:URLString]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody:[postData dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];

这些是我正在使用的委托方法。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
myData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [myData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSString *myString = [[NSString alloc] initWithData:myData encoding:NSWindowsCP1252StringEncoding];
    NSLog(@"%@", myString);
}

这是我从服务器获得的回复:

{ URL: https://www5.whentowork.com/cgi-bin/w2wE.dll/mgrexportemplist?SID=2835115254228 } { status code: 200, headers {
    "Access-Control-Allow-Origin" = "*";
    "Content-Disposition" = "attachment;filename=empdata.xml";
    "Content-Encoding" = gzip;
    "Content-Type" = "application/x-msdownload";
    Date = "Mon, 14 Apr 2014 19:37:54 GMT";
    Server = "Microsoft-IIS/6.0";
    "Transfer-Encoding" = Identity;
    Vary = "Accept-Encoding";
} }

这是XML的第一部分:

<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<!-- Generated by Exmaple.com -->
<!DOCTYPE tutorial [
    <!ENTITY auml "&amp;auml;">
    <!ENTITY ouml "&amp;ouml;">
    <!ENTITY uuml "&amp;uuml;">
    <!ENTITY Auml "&amp;Auml;">
    <!ENTITY Ouml "&amp;Ouml;">
    <!ENTITY Uuml "&amp;Uuml;">

我正在运行最新的Xcode并在iOS模拟器(版本7.1(463.9.41))中运行iPad代码。

我真的不明白。我花了很多时间试图弄清楚为什么我只有三个字节,后来想通了我得到了所有东西,但是到处都是nullbytes。我无法控制服务器,所以我无法更改它的配置。

编辑:NSLog数据返回:(只是前几行)

fffe3c00 3f007800 6d006c00 20007600 65007200 73006900 6f006e00 3d002200 31002e00 30002200
20006500 6e006300 6f006400 69006e00 67003d00 22007700 69006e00 64006f00 77007300 2d003100 
32003500 32002200 20007300 74006100 6e006400 61006c00 6f006e00 65003d00 22007900 65007300 
22003f00 3e000d00 0a003c00 21002d00 2d002000 47006500 6e006500 72006100 74006500 64002000 
62007900 20005700 68006500 6e005400 6f005700 6f007200 6b002d00 2d003e00 0d000a00 3c002100 
44004f00 43005400 59005000 45002000 74007500 74006f00 72006900 61006c00 20005b00 0d000a00 
20002000 20002000 3c002100 45004e00 54004900 54005900 20006100 75006d00 6c002000 22002600 
61006d00 70003b00 61007500 6d006c00 3b002200 3e000d00 0a002000 20002000 20003c00 21004500 
4e005400 49005400 59002000 6f007500 6d006c00 20002200 26006100 6d007000 3b006f00 75006d00 
6c003b00 22003e00 0d000a00 20002000 20002000 3c002100 45004e00 54004900 54005900 20007500 
75006d00 6c002000 22002600 61006d00 70003b00 75007500 6d006c00 3b002200 3e000d00 0a002000 
20002000 20003c00 21004500 4e005400 49005400 59002000 41007500 6d006c00 20002200

1 个答案:

答案 0 :(得分:2)

开头的fffe是一个字节顺序标记,表示响应是小端UTF-16。 (请参阅this byte order mark table。)如果您查看其余数据,则会进一步确认,其中3c00<的小端UTF-16表示形式,3f00?7800x等。

因此:

fffe3c00 3f007800 6d006c00 20007600 65007200 73006900 6f006e00 3d002200
31002e00 30002200 20006500 6e006300 6f006400 69006e00 67003d00 22007700
69006e00 64006f00 77007300 2d003100 32003500 32002200 20007300 74006100
6e006400 61006c00 6f006e00 65003d00 22007900 65007300 22003f00 3e00

<?xml version="1.0" encoding="windows-1252" standalone="yes"?>

因此,您应该使用:

将其转换为字符串
NSString *myString = [[NSString alloc] initWithData:myData encoding:NSUTF16LittleEndianStringEncoding];

这将自动处理字节顺序标记(在开始时消除那个好奇的ÿþ)。


顺便说一句,如果您对表示不清楚,可以尝试将NSData保存到文件中,然后使用stringWithContentsOfFile:usedEncoding:error:。就个人而言,我总是首先寻找字节顺序标记或明显的UTF-16或UTF-32数据(通常很容易用西方语言识别),如上所述,但这有时很有用:

NSStringEncoding encoding;
NSError *error;
NSString *string = [NSString stringWithContentsOfFile:path usedEncoding:&encoding error:&error];
if (string) {
    NSLog(@"string   = %@", string);
    NSLog(@"encoding = %d", encoding);
} else {
    NSLog(@"stringWithContentsOfFile error: %@", error);
}

它并不总是有效,但有时它提供了有趣的线索。