I'm looking for a way to get an int value from a binary file. So lets say i have this file "myfile.dat" where from my PC i stored a lot of stuff...
Now i need to read that file from my IPhone and show the data...
on the "myfile.dat" i have this (binary and all ints are little endian):
0-12: A signature string
13-16: An int number (note that length = 4)
So using NSData i know i can read from pos 13 to pos 16 and get those bytes... i can get the first 0-12 string correctly, but i cannot read pos 13-16 and convert it to an int value in Obj-C.... ;(
I have something like:
unsigned char bytes[length];
[_data getBytes:bytes range:NSMakeRange(offset, length)];
int32_t elem = OSReadLittleInt32(bytes, 0);
Now, im a newbie when it comes to Obj-C and C/C++... all my life i have been working with C# (sad)...
Can anyone help? THANKS IN ADVANCE!
Give this a try:
unsigned long bytes;
[_data getBytes: &bytes length: sizeof(unsigned long)];
NSLog(#"%i", NSSwapLittleLongToHost(bytes));
Related
I need to convert an UISlider value and my iPhones accelerometer data to a char in format char hexData = {0x00, 0x00, 0x01, 0xA0}. Any ideas on this?
The accelerometer values are signed (positive and negative) numbers, while the UISlider value spans from 0 to 100.
Thank you
well, i don't know what endianness the data is expected to be sent in; you may have to reverse the order.
but you should be able to get away with simple C manipulations such as the following.
char fourChar[4];
int* value = (int*)(&fourChar);
*value = (int)floatValueFromSlider; // or the simple values from your picker
[appNote sendCharArray:fourChar]; // assuming the method wants a char[] of only 4 characters
this will be in little-endian format. you will probably have to swap the bytes before sending, depending upon what the receiver expects. you can manipulate this further as necessary.
I can't write data at index above 128 in byte array.
code is given below.
private void Write1(APDU apdu) throws ISOException
{
apdu.setIncomingAndReceive();
byte[] apduBuffer = apdu.getBuffer();
byte j = (byte)apduBuffer[4]; // Return incoming bytes lets take 160
Buffer1 = new byte[j]; // initialize a array with size 160
for (byte i=0; i<j; i++)
Buffer1[(byte)i] = (byte)apduBuffer[5+i];
}
It gives me error 6F 00 (It means reach End Of file).
I am using:
smart card type = contact card
using java card 2.2.2 with jcop using apdu
Your code contains several problems:
As already pointed out by 'pst' you are using a signed byte value which works only up to 128 - use a short instead
Your are creating a new buffer Buffer1 on every call of your Write1 method. On JavaCard there is usually no automatic garbage collection - therefore memory allocation should only be done once when the app is installed. If you only want to process the data in the adpu buffer just use it from there. And if you want to copy data from one byte array into another better use javacard.framework.Util.arrayCopy(..).
You are calling apdu.setIncomingAndReceive(); but ignore the return value. The return value gives you the number of bytes of data you can read.
The following code is from the API docs and shows the common way:
short bytesLeft = (short) (buffer[ISO7816.OFFSET_LC] & 0x00FF);
if (bytesLeft < (short)55) ISOException.throwIt( ISO7816.SW_WRONG_LENGTH );
short readCount = apdu.setIncomingAndReceive();
while ( bytesLeft > 0){
// process bytes in buffer[5] to buffer[readCount+4];
bytesLeft -= readCount;
readCount = apdu.receiveBytes ( ISO7816.OFFSET_CDATA );
}
short j = (short) apdu_buffer[ISO7816.OFFSET_LC] & 0xFF
Elaborating on pst's answer. A byte has 2^8 bits numbers, or rather 256. But if you are working with signed numbers, they will work in a cycle instead. So, 128 will be actually -128, 129 will be -127 and so on.
Update: While the following answer is "valid" for normal Java, please refer to Roberts answer for Java Card-specific information, as well additional concerns/approaches.
In Java a byte has values in the range [-128, 127] so, when you say "160", that's not what the code is really giving you :)
Perhaps you'd like to use:
int j = apduBuffer[4] & 0xFF;
That "upcasts" the value apduBuffer[4] to an int while treating the original byte data as an unsigned value.
Likewise, i should also be an int (to avoid a nasty overflow-and-loop-forever bug), and the System.arraycopy method could be handy as well...
(I have no idea if that is the only/real problem -- or if the above is a viable solution on a Java Card -- but it sure is a problem and aligns with the "128 limit" mentioned.)
Happy coding.
Are there any built in utilities or macros in the objective-c libraries for iOS that will allow you to convert bytes to and from integers with respect to endianess?
Please don't tell me to use bit-shifting operations. I am trying to avoid writing custom code to do this if it already exists.
I would like the code to convert NSData* to primitive types (int, uint, short, etc) and to convert primitive types back to NSData*.
You can get the bytes from NSData by accessing the bytes property. Then just cast that to a pointer to whatever type you want. Obviously you'll need to ensure you know the endianness and size of what is in your NSData.
e.g.
#include <CFByteOrder.h>
// Bytes to uint32_t
NSData *data = <THE_DATA>;
void *bytes = [data bytes];
uint32_t *intBytes = (NSInteger*)bytes;
uint32_t swapped = CFSwapInt32BigToHost(*intBytes); ///< If the data in `data' is big endian
// uint32_t to bytes
uint32_t someInt = 1234;
uint32_t swappedInt = CFSwapInt32HostToBig(someInt); ///< If we want to store in big endian
NSData *data = [NSData dataWithBytes:&swappedInt length:sizeof(swappedInt)];
I think you want the CFSwapInt32* family of functions.
See Apple's docs.
I need to assign 2,554,416,000 to a variable. What would be the primitive to use, and what would be the object representation class to use? Thanks.
Chuck is right, but in answer to the "object representation", you want NSNumber used with the unsignedInt methods.
NSNumber *myNum = [NSNumber numberWithUnsignedInt:2554416000];
NSUInteger myInt = [myNum unsignedIntValue];
2,554,416,000 = 0x9841,4B80 ≤ 0xFFFF,FFFF (UINT_MAX), so uint32_t (unsigned int) or int64_t (long long).
A signed int32_t (int) cannot represent this because 0x9841,4B80 > 0x7FFF,FFFF (INT_MAX). Storing it in an int will make it negative.
This can be represented by a 32-bit unsigned integer (UINT_MAX is about 4 billion). That's actually what NSUInteger is on the iPhone, but if you want to be very specific about the bit width, you could specify a uint32_t.
You could store it in a regular int scaled down by 1000 if you wanted, if this represented a score that could never have the bottom 3 digits hold any info or something similiar. This would be a way to save a few bits and possibly an entire extra int of space, if that matters.
Can someone help me ? I have a NSString with #"12.34" and I want to convert it into a NSString with the same float number but in single precision 32bits binary floating-point format IEEE-754 : like #"\x41\x45\x70\xa4" (with hexa characters) or #"AEp¤"...
I'm sure it's something easy but after many hours of reading the doc without finding a solution...
Thank you !
As Yuji mentioned, it's not a good idea to encode an arbitrary byte sequence into an NSString(although it can contain null bytes), as encoding transformations can(and probably WILL) destroy your byte sequence. If you want access to the raw bytes of a float, you may want to consider storing them as an NSData object(though I suggest you think through your reasons for wanting this first). To do this:
NSString *string = #"10.23";
float myFloat = [string floatValue];
NSData *myData = [[NSData alloc] initWithBytes:&myFloat length:sizeof(myFloat)];
If you want to get the raw bytes of a float, you could cast it, like so:
NSString *str = #"12.34";
float flt = [str floatValue];
unsigned char *bytes = (unsigned char *)&flt;
printf("Bytes: %x %x %x %x\n", bytes[0], bytes[1], bytes[2], bytes[3]);
However the order in which these bytes are stored in the array depends on the machine. (See http://en.wikipedia.org/wiki/Endianness). For example, on my Intel iMac it prints: "Bytes: a4 70 45 41".
To make a new NSString from an array of bytes you can use initWithBytes:length:encoding: