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]);
}
Related
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;
}
}
I am working on an iOS project
I have to read a huge file in chunks of 4KB
Here is what I have so far:
NSData *fileData= [self getBytesFromInput];
pj_str_t text;
int chunkSize = 4*1024;
int fileSize = [fileData length];
while (fileSize>0){
if (fileSize<=chunkSize) {
chunkSize = fileSize;
fileSize=0;
}
else fileSize = fileSize-chunkSize;
pj_strset(&text, (char*)[fileData bytes], MIN([fileData length], chunkSize); //takes the first chunk
//BUT HOW TO TAKE THE NEXT CHUNK OF DATA?
//do something with the &text ....
}
i would refactor the code so you are also loading the files in chunks, but you can access the later chunks by adding an offset to your byte-pointer:
int currentOffset = 0;
while (fileSize>0) {
...
char* bytePointer = (char*)[fileData bytes];
pj_strset(&text, bytePointer+currentOffset, MIN([fileData length], chunkSize);
currentOffset += chunkSize;
}
EDIT:
This should do the same thing but reading the file chunk for chunk:
NSString *yourFilePath;
NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:yourFilePath];
int chunksize = 4*1024;
pj_str_t text;
NSData *data;
while ((data = [fileHandle readDataOfLength:chunksize]) && [data length] > 0) {
pj_strset(&text, (char*)[data bytes], [data length]);
}
I have an application in which when I enter emailid,then emailid is converted into array of integers using md5 digest.
I have written the code for converting into array but the array is not getting generated in proper format. This is format which I need:
[2, -88, 14, -36, -128, -124, -32, -91, 0, 107, -41, -114, -118, 100,
-45, 45];
but my code is not retiring in this format.
This is my code:
static NSData* digest(NSData *data, unsigned char* (*cc_digest)(const void*, CC_LONG, unsigned char*), CC_LONG digestLength)
{
unsigned char md[digestLength];
(void)cc_digest([data bytes], [data length], md);
NSData* data1 = [NSData dataWithBytes:(const void *)md length:sizeof(unsigned char)*digestLength];
return [NSData dataWithBytes:md length:digestLength];
}
- (NSData *) md5
{
NSString *str =#"mitalee.yadav#gmail.com";
NSData *data = [str dataUsingEncoding:NSASCIIStringEncoding];
return digest(data, CC_MD5, CC_MD5_DIGEST_LENGTH);
}
in my appdidfinishlaunching I'm doing this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSData *dat = [self md5];
NSUInteger len = [dat length];
Byte *byteData= (Byte*)malloc(len);
[dat getBytes:byteData length:len];
}
but this is returning bytes in this format
<02a80edc 8084e0a5 006bd78e 8a64d32d>
Loop your byte array and do follow on it..
int result[16];
for(int i = 0; i < 16; i++)
{
Byte b = byteData[i];//0xDC;
result[i] = (b & 0x80) > 0 ? b - 0xFF -1 : b;
}
This will convert byte into signed int. I am sure that there must be optimised way.
I need to convert the contents of a single element in my uint8_t buffer to an NSString so that I can display it to a label on my iPhone app. I read in the contents of buffer OK from a TCP connection. I am not getting the proper encoding so that an element's value can be displayed correctly. For example, if buffer[4] has the contents of 0xFD or 253, how do I best get that transferred to the label? (The label is data1) Or is there a much simpler way? Thanks.
uint8_t buffer[64];
uint8_t tinybuffer[1];
int len;
// Read in contents from TCP connection, log dump, and display to label.
len = [inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
// Log dump
for(int i = 0; i < len; i++) {
NSLog(#"Returning byte %d : %x", i, buffer[i]);
}
NSLog(#"Finished Reading");
// Get data to the screen.
tinybuffer[0] = buffer[4];
NSString *str1 = [[NSString alloc] initWithBytes:tinybuffer length:1 encoding:NSUTF8StringEncoding];
_data1.text = str1;
NSString *str1 = [NSString stringWithFormat:#"%d", tinybuffer[0]];
should do what you want.
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.