I have a ASCII file which I want to read byte by byte into a Byte buffer. I am clueless and confused between many aspects. Can anyone guide me with the correct way to do it?
Any help is appreciated.
I finaly got the answer here. So what I did is,
NSMutableString *bundlePath = [NSMutableString stringWithString:
[[NSBundle mainBundle]pathForResource:#"excercise1" ofType:nil]];
NSData *myData = [NSData dataWithContentsOfFile:bundlePath];
uint8_t * bytePtr = (uint8_t * )[myData bytes];
NSInteger totalData = [myData length] / sizeof(uint8_t);
NSLog(#"Data byte chunk: ");
for (int i = 0 ; i < totalData; i ++)
{
NSLog(#" %x", bytePtr[i]);
}
and it worked as I wanted it to be. I got the bytes in an array.
Related
I have 1 Hex file, i want to read this file and parse it to NSString.
I used this code to read hex file but it only prinf hex code in console:
-(void)readHexfile
{
NSData *data = [NSData dataWithContentsOfFile:#"path file"];
NSLog(#"Patch File: %#",data);
}
Do you have any suggestions? Thanks in advance
Use stringWithContentsOfFile:encoding:error: instead of dataWithContentsOfFile to read it as NSString.
There is no such a thing like a "hex file". Hex, or hexadecimal, is a numerical system that is quite suitable to display binary data in octets (8-bit bytes) in some way suitable for humans.
What you currently do is displaying the description of the NSData object onth the console in hex.
Some quick and dirty hack could be just to use the description of the NSData.
NSString *hexString = [data description];
This will create some overhead that you could strip of using string manipulation methods.
There are smater ways that may require more work.
On the contrary, if you are not interested in a hex representation then use stringWithContentsOfFile to read the file directly into an NSString object. You can then apply various encodings depending on how your file is actually encoded.
You'd read that using a NSScanner (convert your data to a string first using [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] (assuming your text is pure ASCII or UTF-8) or read it directly using +[NSString stringWithContentsOfFile:encoding:error:]). See also the String Programming Guide on how to use scanners.
Edit: So it seems you want to read a file with null-terminated strings. A naive and inefficient way to do that would be:
NSData *data = [NSData dataWithContentsOfFile:#"file.path"];
NSMutableArray *strings = [NSMutableArray array];
const char *rawData = [data bytes];
NSUInteger dataLength = [data length];
NSMutableData *currentString = [NSMutableData data];
for (NSUInteger i = 0; i < dataLength; i++) {
if (rawData[i] == 0) {
if ([currentString length] > 0) {
[strings addObject:[[[NSString alloc] initWithData:currentString encoding:NSUTF8StringEncoding] autorelease]];
}
[currentString release];
currentString = [NSMutableData data];
} else {
[currentString appendBytes:&rawData[i] length:1];
}
}
// Handle the last string if it wasn't null-terminated.
if ([currentString length] > 0) {
[strings addObject:[[[NSString alloc] initWithData:currentString encoding:NSUTF8StringEncoding] autorelease]];
}
// "strings" now is a list of strings.
I am trying to convert a string to a 32-bit unsigned, network (big-endian) byte order. I can't seem to figure out how to do this. In Ruby I accomplish this by string.unpack('N') - but can't seem how to manage this in Objective-C. Any suggestions? Thanks!
In Objective-C you would convert NSString to NSData. Then you can access the bytes from the NSData object.
NSString *str = #"😄 H€llö Wòrld";
NSData *data = [str dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSLog(#"%#", data);
// Output:
// <0001f604 00000020 00000048 000020ac 0000006c 0000006c 000000f6 00000020 00000057 000000f2 00000072 0000006c 00000064>
const uint8_t *bytes = [data bytes]; // pointer to converted bytes
NSUInteger length = [data length]; // number of converted bytes
How can I iterate through [NSData bytes] one by one and append them to an NSMutableString or print them using NSLog()?
Rather than appending bytes to a mutable string, create a string using the data:
// Be sure to use the right encoding:
NSString *result = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
If you really want to loop through the bytes:
NSMutableString *result = [NSMutableString string];
const char *bytes = [myData bytes];
for (int i = 0; i < [myData length]; i++)
{
[result appendFormat:#"%02hhx", (unsigned char)bytes[i]];
}
Update! Since iOS 7, there's a new, preferred way to iterate through all of the bytes in an NSData object.
Because an NSData can now be composed of multiple disjoint byte array chunks under the hood, calling [NSData bytes] can sometimes be memory-inefficient, because it needs to flatten all of the underlying chunks into a single byte array for the caller.
To avoid this behavior, it's better to enumerate bytes using the enumerateByteRangesUsingBlock: method of NSData, which will return ranges of the existing underlying chunks, which you can access directly without needing to generate any new array structures. Of course, you'll need to be careful not to go poking around inappropriately in the provided C-style array.
NSMutableString* resultAsHexBytes = [NSMutableString string];
[data enumerateByteRangesUsingBlock:^(const void *bytes,
NSRange byteRange,
BOOL *stop) {
//To print raw byte values as hex
for (NSUInteger i = 0; i < byteRange.length; ++i) {
[resultAsHexBytes appendFormat:#"%02x", ((uint8_t*)bytes)[i]];
}
}];
I have a NSData item that is holding a bunch of ints. How do I go about getting them out and into an NSArray?
The memory structure in the NSData is 32-bit int in little-endian order, one right after the other.
Sorry for the basic question, but still learning the obj-c way of doing things :)
You can use the functions defined in OSByteOrder.h to deal with endianness. Aside from that quirk, this is really just a matter of grabbing the byte buffer and iterating over it.
// returns an NSArray containing NSNumbers from an NSData
// the NSData contains a series of 32-bit little-endian ints
NSArray *arrayFromData(NSData *data) {
void *bytes = [data bytes];
NSMutableArray *ary = [NSMutableArray array];
for (NSUInteger i = 0; i < [data length]; i += sizeof(int32_t)) {
int32_t elem = OSReadLittleInt32(bytes, i);
[ary addObject:[NSNumber numberWithInt:elem]];
}
return ary;
}
Sounds like there are cleaner ways to do what you're trying to do, but this should work:
NSData *data = ...; // Initialized earlier
int *values = [data bytes], cnt = [data length]/sizeof(int);
for (int i = 0; i < cnt; ++i)
NSLog(#"%d\n", values[i]);
This answer is very similar to other answers above, but I found it instructive to play with casting the NSData bytes back to an int32_t[] array. This code works correctly on a little-endian processor (x64 in my case) but would be silently wrong on big-endian (PPC) because the byte representation would be big-endian.
int32_t raw_data[] = {0,1,2,3,4,5,6,7,8,9,10};
printf("raw_data has %d elements\n", sizeof(raw_data)/sizeof(*raw_data));
NSData *data = [NSData dataWithBytes:(void*)raw_data length:sizeof(raw_data)];
printf("data has %d bytes\n", [data length]);
int32_t *int_data_out = (int32_t*) [data bytes];
for (int i=0; i<[data length]/4; ++i)
printf("int %d = %d\n", i, int_data_out[i]);
[data release];
One possible solution below.
To take endianness into account, look up Core Endian Reference in the XCode doc set (you probably would use EndianS32_LtoN (32 bit litte endian to native endianness)).
int mem[]= {0x01, 0x02, 0x03, 0x04, 0xff};
NSData * data = [NSData dataWithBytes:mem length:sizeof(mem)*sizeof(int)];
NSMutableArray * ar = [NSMutableArray arrayWithCapacity:10];
/* read ints out of the data and add them to the array, one at a time */
int idx=0;
for(;idx<[data length]/sizeof(int);idx+=sizeof(int))
[ar addObject:[NSNumber numberWithInt:*(int *)([data bytes] + idx)]];
NSLog(#"Array:%#", ar);
ex:
NSData *data = [NSData dataWithContentsOfFile:filePath];
int len = [data length];
if len = 10000,
i hope i can convert 1000 to a NSData look like
char hoperesult[] = {0x10, 0x27, 0x00, 0x00}
and hoperesult[] must always 4 Bytes
So you want the length in 4 little-endian bytes, correct? I think this will do it:
unsigned int len = [data length];
uint32_t little = (uint32_t)NSSwapHostIntToLittle(len);
NSData *byteData = [NSData dataWithBytes:&little length:4];
(Note that most network protocols use big-endian, but you showed little-endian so that's what this does.)
I'm not 100% sure what you mean here, but I think you are attempting to fill hoperesult with the values found in the file at 'filePath'.
struct _hoperesult {
char data[4];
} *hoperesult;
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSUInteger len = [data length];
NSRange offset;
offset.location = 0;
offset.length = sizeof(_hoperesult);
NSData *hoperesultData;
while( (offset.location + offset.length) < len ) {
hoperesultData = [data subdataWithRange:offset];
// the equivalent of your char hoperesult[] content...
hoperesult = [hoperesultData bytes]
}
An instance of NSData can return a pointer to the actual bytes of data using the "bytes" method. It returns a (const void *). You could in theory simply cast [data bytes] to a char * and use the offset directly; or you can do like in the above code and return smaller chucks of NSData.
Hope that helps!