문제

I'm trying to fetch an XML-document from a server, but the response I'm getting in clear text is just ÿþ<.

I found out, by reading the HEX-data of the NSData that what follows after those first three bytes is the whole response I wanted, but with a nullbyte in between every byte. Now, I could just strip the data from those bytes, but if I get the same data with Netcat, there are no nullbytes there, so I figured there is something wrong with my code.

I've sent the exact same headers that the iPad-simulator has sent, but everything seems normal from there. This is the code I'm using to fetch the XML-data:

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];

And these are the delegate methods I'm using.

- (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);
}

This is the response I'm getting from the server:

{ 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";
} }

This is the first part of the 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;">

I'm running the latest Xcode and running the code in the iOS simulator (Version 7.1 (463.9.41)) for iPad.

I really don't get this. I spent so much time trying to figure out why I only got three bytes, then later figured out I got everything, but with nullbytes in between everywhere. I do not have control over the server, so I can not change it's configuration.

EDIT: An NSLog of the data return this: (just the first couple of lines)

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
도움이 되었습니까?

해결책

The fffe at the start is a byte order mark that indicates that the response is is little endian UTF-16. (See this byte order mark table.) This is further confirmed if you look at the rest of your data, where 3c00 is the little endian UTF-16 representation of <, 3f00 is ?, 7800 is x, etc.

Thus:

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

is

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

You should therefore convert it to a string using:

NSString *myString = [[NSString alloc] initWithData:myData encoding:NSUTF16LittleEndianStringEncoding];

This will automatically handle the byte order mark, as well (eliminating that curious ÿþ at the start).


By the way, if you're ever unclear about the representation, you can always try saving the NSData to a file and then using stringWithContentsOfFile:usedEncoding:error:. Personally, I'd always first look for a the byte order mark or for obvious UTF-16 or UTF-32 data (which is generally pretty easy to identify in western languages), as we did above, but this can be useful sometimes:

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);
}

It doesn't always work, but sometimes it provides interesting clues.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top