Unarchiving fails on NSArray of NSData
Unarchiving fails on NSArray of NSData
- Subject: Unarchiving fails on NSArray of NSData
- From: Seth Delackner <email@hidden>
- Date: Sat, 22 Mar 2003 04:47:38 +0000
I'm using OmniNetworking to establish a TCP connection between my client and
server. The client sends an archived (not keyed, for 10.1 compatibility)
NSArray containing several strings and 3 NSDatas. Two of the NSDatas are
optional, so if they are not selected I just encode @"nil" and put it in an
NSData.
If I send just the strings, 1 NSData containing a small file from [NSData
dataWithContentsOfFile:], and two NSData encodings of @"nil", it works just
fine. Yet sending the optional NSData from another file instead of @"nil",
again using [NSData dataWithContentsOfFile:], the Unarchiver bails.
I tried logging how many bytes the received NSData thought it contained, and
when it fails, it contains far too many bytes. I tried both just reading one
time and reading into a temporary NSData and appending to an NSMutableData
until the Socket is closed, with no luck.
Sample output on failure (when sent bytes was 12288):
got 1470464 bytes
Exception unarchiving: *** End of archive encountered prematurely at 228
Could not decode data, giving up.
A snippet of the server:
-(void)processConnection:(ONTCPSocket*)connectionTCPSocket {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSData* buffer = nil;
NSMutableData* data = [NSMutableData dataWithCapacity: 32768];
NSArray* values = nil;
unsigned int length;
NS_DURING {
buffer = [connectionTCPSocket readData];
[data appendData: buffer];
} NS_HANDLER {
NSLog(@"Exception receiving: %@", localException);
} NS_ENDHANDLER;
[connectionTCPSocket release]; connectionTCPSocket = nil;
NS_DURING{
NSLog(@"got %d bytes", [data bytes]);
values = [NSUnarchiver unarchiveObjectWithData: data];
} NS_HANDLER {
NSLog(@"Exception unarchiving: %@", localException);
values = nil;
} NS_ENDHANDLER;
And the client code follows. Note that reportData is always a small file,
fileData is a small file, screenData is a the data from a PICT pasteboard
[NSData dataWithData: bla bla]. If any of the NSDatas is nil, I encode the string @"nil" and use that, so that the unarchiving will be painless:
emptyFile = [@"nil" dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
if (sendFile && [[NSFileManager defaultManager] isReadableFileAtPath:filePath])
fileData = [NSData dataWithContentsOfFile: filePath];
if (nil == fileData)
fileData = [NSData dataWithData: emptyFile];
if ([sendScreenShot state] == NSOffState || nil == screenData)
screenData = [NSData dataWithData: emptyFile];
reportData = [NSData dataWithContentsOfFile: PROFILE_PATH];
if (nil == reportData)
reportData = [NSData dataWithData: emptyFile];
values = [NSArray arrayWithObjects:
[button1 title]
, [field1 string]
, [field2 string]
, (sendEmailAddress ? [emailAddress stringValue] : @"")
, ((sendFile && (nil != filePath)) ? filePath : @"")
, fileData
, screenData
, reportData // <-- always sent, works
, nil];
data = [NSArchiver archivedDataWithRootObject: values];
NSLog(@"will send %d bytes", [data length]);
values = nil;
hostAddress = [[host addresses] objectAtIndex:0];
NS_DURING {
tcpSocket = (ONTCPSocket *)[ONTCPSocket socket];
[tcpSocket connectToAddress:hostAddress port:FEEDBACK_PORT];
[tcpSocket write
Data:data];
} NS_HANDLER {
NSLog(@"exception sending data: %@", localException);
return NO;
} NS_ENDHANDLER;
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.