UIImage not received correctly from server - ios

I am kind of new to objective-c so please help. i am receiving the image but not completely here is my code.
I am sure that the problems is here and not on the server side, but if you need me to post the code of the server side then ill do that.
uint8_t buf[3000000];
int len = 0;
len = [inputStream read:buf maxLength:3000000];
UIImage* fooo ;
NSMutableData *dataa=[[NSMutableData alloc] initWithLength:0];
do{
len = [inputStream read:buf maxLength:3000000];
if(len>0) current+=len;
}
while (len>-1);
[dataa appendBytes: (const void *)buf length:current];
fooo = [[UIImage alloc] initWithData:dataa];
[inputStream close];
[outputStream close];
server side
String FilePath=xxxxx.jpeg";
System.out.println (FilePath);
File file1=new
File(xxxxxx\\38.jpeg");
long v=file1.length();
byte [] mybytearray = new byte [(int)file1.length()];
FileInputStream fis = new
FileInputStream(FilePath);
BufferedInputStream bis = new
BufferedInputStream(fis);
bis.read(mybytearray,0,mybytearray.length);
os = connectionSocket.getOutputStream();//outpustream
System.out.println("Sending...");
os.write(mybytearray,0,mybytearray.length);
System.out.println("Sent");
os.flush();

Every time when stream comes you creating a new data and try to append.. but actually you are not appending all data to one data object you are doing this way NSMutableData *dataa=[[NSMutableData alloc] initWithLength:0]
I will prefer have an instance variable and do like this
if(!_data) {
_data = [[NSMutableData alloc] initWithLength:0];
}
Whole code should be like this, code is from apple documentation
switch(eventCode) {
case NSStreamEventHasBytesAvailable:
{
if(!_data) {
_data = [[NSMutableData data] retain];
}
uint8_t buf[1024];
unsigned int len = 0;
len = [(NSInputStream *)stream read:buf maxLength:1024];
if(len) {
[_data appendBytes:(const void *)buf length:len];
// bytesRead is an instance variable of type NSNumber .
[bytesRead setIntValue:[bytesRead intValue]+len];
} else {
NSLog(#"no buffer!");
}
break;
}
You should handle stream events. Stream will not bring data in one big chunk, so that's why we appending data here. Delegate method will be called with an event and you can set check on event.
When you got this event NSStreamEventEndEncountered close your stream object and create uiimage object
switch(NSStreamEventEndEncountered){
[stream close];
[stream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[stream release];
stream = nil; // stream is ivar, so reinit it
if (_data!=nil)
UIImage *image = [UIImage imageWithData:_data];
}

Related

iOS NSStream tcp server client can't communicate

I have an issue with the development of a tcp server/client in objective c with Bonjour.
On the server side I open correctly the streams and I use the handleEvent function to send and receive data. But I don't know what is the proper way to send and receive data. I read this excellent post : Correct way to send data through a socket with NSOutputStream
So I use a packet queued system to send data :
switch(eventCode) {
case NSStreamEventOpenCompleted: {
NSLog(#"Complete");
} break;
case NSStreamEventHasSpaceAvailable: {
if (stream == _outputStream)
[self _sendData];
} break;
...
- (void)_sendData {
flag_canSendDirectly = NO;
NSData *data = [_dataWriteQueue lastObject];
if (data == nil) {
flag_canSendDirectly = YES;
return;
}
uint8_t *readBytes = (uint8_t *)[data bytes];
readBytes += currentDataOffset;
NSUInteger dataLength = [data length];
NSUInteger lengthOfDataToWrite = (dataLength - currentDataOffset >= 1024) ? 1024 : (dataLength - currentDataOffset);
NSInteger bytesWritten = [_outputStream write:readBytes maxLength:lengthOfDataToWrite];
currentDataOffset += bytesWritten;
if (bytesWritten > 0) {
self.currentDataOffset += bytesWritten;
if (self.currentDataOffset == dataLength) {
[self.dataWriteQueue removeLastObject];
self.currentDataOffset = 0;
}
}
}
. So basically i just send separate my data on many packets. But I don't see how to reconstruct the data on the client side. And I think i didn't correctly understood the NSStreamEventHasBytesAvailable event. Because here I send many packets but this event on the client side is call only once. And when I reconstruct the data from the buffer the data appears to be corrupted. I would really appreciate if someone can clarify all this, the documentation is not really clear on this point (or maybe I miss a point ..) .
case NSStreamEventHasBytesAvailable: {
if (stream == _inputStream)
{
//read data
uint8_t buffer[1024];
int len;
while ([_inputStream hasBytesAvailable])
{
len = [_inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0)
{
NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding];
//NSData *theData = [[NSData alloc] initWithBytes:buffer length:len];
UnitySendMessage("AppleBonjour_UnityNetworkManager(Clone)", "OnLocalClientReceiveMessageFromServer", [output cStringUsingEncoding:NSUTF8StringEncoding]);
}
}
}
It seems, that you use two variables currentDataOffset -- an instance variable and a property -- for the same purpose. If you indeed need both of them, you should set 0 to currentDataOffset as well. But I think the fragment should look like:
readBytes += currentDataOffset;
NSUInteger dataLength = [data length];
NSUInteger lengthOfDataToWrite = MIN(dataLength - currentDataOffset, 1024);
NSInteger bytesWritten = [_outputStream write:readBytes maxLength:lengthOfDataToWrite];
if (bytesWritten > 0) {
currentDataOffset += bytesWritten;
if (currentDataOffset == dataLength) {
[self.dataWriteQueue removeLastObject];
currentDataOffset = 0;
}
}

operand of type const void where arihmetic or pointer type required

Why am i getting the error:
Operand if type const void where arithmentic or pointer type required to the following line:
//insert data at a specific position in a file
NSData *chunk = chunkContainer; // some data
NSUInteger insertPoint = chunkNo*512; // get the insertion point //
// make sure the file exists, if it does, do the following //
NSData *oldData = [NSData dataWithContentsOfFile:filePath];
// error checking would be nice... if (oldData) ... blah //
NSOutputStream *stream = [[NSOutputStream alloc] initToFileAtPath:filePath append:NO];
[stream open];
[stream write:(uint8_t *)[oldData bytes] maxLength:insertPoint]; // write the old data up to the insertion point //
[stream write:(uint8_t *)[chunk bytes] maxLength:[chunk length]]; // write the new data //
//THE NEXT LINE IS THE LINE I AM GEETING THE ERROR AT
[stream write:(uint8_t *)[oldData bytes][insertPoint] maxLength:([oldData length] - insertionPoint)]; // write the rest of old data at the end of the file //
[stream close];

Read integer from file IOS

I have a file that contains in the very first byte of data a number. In this case that number is 32. I have used a hex editor to confirm that (in hex) the value is "20" which equals 32 in decimal.
Can someone point me in the right direction of how to read it out of the file. I have tried about 6 different ways all of which have failed.
Lots of different ways. Here's one:
NSData *data = [NSData dataWithContentsOfFile:filename];
if ([data length] > 0)
{
const uint8_t *bytes = (const uint8_t *)[data bytes];
uint8_t byte = bytes[0];
NSLog(#"%d", byte);
}
or another:
NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:filename];
[stream open];
NSInteger bufferLen = 1;
uint8_t buffer[bufferLen];
NSInteger count = [stream read:buffer maxLength:bufferLen];
[stream close];
if (count > 0)
{
NSLog(#"%d", buffer[0]);
}

Massive allocations with with CFString while writing to NSOutputStream in iOS

I have problem with large number of allocations while writing to NSOutputStream. I am using few classes together that are supposed to stream data from AudioUnit to remote server. Code below:
AudioProcessor.m
Data *data = [Data sharedData]; //it's shared data I use to store information for the final socket
intFromBuffer = audioBufferList->mBuffers[0].mData;
NSUInteger length = audioBufferList->mBuffers[0].mDataByteSize;
NSMutableData *dataOut = [[NSMutableData alloc] initWithCapacity:0];
[dataOut appendBytes:(const void *)intFromBuffer length:length * sizeof(SInt16)];
[data setOutput:dataOut]; //it writes data to the shared data
Data.m
#implementation Data
NSMutableData *output;
NSMutableData *input;
#synthesize output;
#synthesize input;
+(id)sharedData {
static Data *sharedData = nil;
#synchronized(self) {
if (sharedData == nil) {
sharedData = [[self alloc] init];
}
return sharedData;
}
}
-(void) setOutput:(NSMutableData*)outputt{
output = outputt;
}
-(void) setInput:(NSMutableData*)inputt{
input = inputt;
}
#end
NetworkCommunication.m
- (void) observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
//NSLog(#"changed!!!!");
if ([keyPath isEqualToString:#"output"]) {
Data *data = [Data sharedData];
[self writeOut:data.output];
}
}
- (void)writeOut:(NSString *)s {
NSString *dataTo = [NSString stringWithFormat:#"%#\n", s];
NSData *data = [[NSData alloc] initWithData:[dataTo dataUsingEncoding:NSASCIIStringEncoding]];
[outputStream write:[data bytes] maxLength:[data length]];
}
It generally creates great amount of data, which in 2,5 min was about 200 MB in virtual memory. I tried to simply pass stringWithFormat: directly to my writeOut: function however it gives nothing, not idea how to deal with it.
If someone asks why I use stringWithFormat, simply because I need to put \n for server to read the message.
Any help much appreciated.
EDIT 1:
I tied it different way. In my AudioProcessor.m (because that's the data is created - in the recorder callback) I set it this way:
dataOut = [[NSMutableData alloc] initWithCapacity:0];
[dataOut appendBytes:(const void *)intFromBuffer length:length * sizeof(SInt16)];
net = [NetworkCommunication init];
const char *s = [dataOut bytes];
[[net outputStream] write:s maxLength:strlen(s)];
Now it generates insane allocations of type Malloc 1,00KB, and Malloc 2,00 KB with NSThread callStackSymbol and NSThread callStackReturnAddresses. What's still wrong?
Did you try sending C strings?
const char *s = [dataTo UTF8String];
[outputStream write:s maxLength:strlen(s)];

NSOutputStream not writing data properly

Using the NSStreamEventHasSpace available event, I am trying to write a simple NSString to to an NSOutputStream. Here is the contents of that event:
uint8_t *readBytes = (uint8_t *)[data mutableBytes];
readBytes += byteIndex; // instance variable to move pointer
int data_len = [data length];
unsigned int len = ((data_len - byteIndex >= 12) ?
12 : (data_len-byteIndex));
uint8_t buf[len];
(void)memcpy(buf, readBytes, len);
len = [output write:(const uint8_t *)buf maxLength:len];
NSLog(#"wrote: %s", buf);
byteIndex += len;
I pretty much took it right from Apple. The data is initialized in my viewDidLoad method with
data = [NSMutableData dataWithData:[#"test message" dataUsingEncoding:NSUTF8StringEncoding]];
[data retain];
The HasSpaceAvailable event is called twice. In the first one, the entire message is written with the characters "N." appended to it. In the second time, NSLog reports that a blank message was written (not null). Then, the EndEncountered event occurs. In that event, I have
NSLog(#"event: end encountered");
assert([stream isEqual:output]);
NSData *newData = [output propertyForKey: NSStreamDataWrittenToMemoryStreamKey];
if (!newData) {
NSLog(#"No data written to memory!");
} else {
NSLog(#"finished writing: %#", newData);
}
[stream close];
[stream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[stream release];
output = nil;
break;
I also got this from Apple. However, "No data written to memory!" is logged. No errors occur at anytime, and no data appears to have been received on the other end.
I seem to have fixed this by using low level Core Foundation methods instead of higher level NSStream methods. I used this article as a starting point:
http://oreilly.com/iphone/excerpts/iphone-sdk/network-programming.html
It covers input and output streams in great lenghts and has code examples.
Hope this helps.

Resources