私はNSDataオブジェクトを持っています。長さは4バイトです。これらの4バイトは、を使用して別のNSDataオブジェクトから抽出しています。
fourByteData=[completeData subdataWithRange:NSMakeRange(0, 16)];
私の最初の質問は、上記のステートメントで完全なデータの最初の4バイトが提供されるかどうかです。
はいの場合、これらのすべてのバイトを同等のintに変換する方法。
268566528は期待する値ですか、それとも528を期待する値ですか?正しい値が528の場合、バイトオーダーはビッグエンディアンですが、CPUはリトルエンディアンなので、バイトを逆にする必要があります。
したがって、正しい値が528である必要がある場合は、次のようになります。
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));
また、ネットワーク標準の順序はビッグエンディアンであることに注意してください。
そのステートメントは、4ではなく、最初の16バイトのデータを提供します。最初の4バイトを取得するには、ステートメントを次のように変更する必要があります。
fourByteData = [completeData subdataWithRange:NSMakeRange(0, 4)];
NSDataオブジェクトから整数にデータを読み取るには、次のようにします。
int theInteger;
[completeData getBytes:&theInteger length:sizeof(theInteger)];
整数に変換するだけの場合は、最初の4バイトを取得する必要はありません。上記の2行とcompleteData
レシーバーから直接これを行うことができます
範囲はオフセット0から16バイトなので、16バイトのデータは取得されません。
4バイトのNSData
インスタンスがある場合は、次のような単純な型キャストを実行できます。
int value = *(int*)([data bytes]);
- (unsigned)parseIntFromData:(NSData *)data{
NSString *dataDescription = [data description];
NSString *dataAsString = [dataDescription substringWithRange:NSMakeRange(1, [dataDescription length]-2)];
unsigned intData = 0;
NSScanner *scanner = [NSScanner scannerWithString:dataAsString];
[scanner scanHexInt:&intData];
return intData;
}
int numberOfChunks = [self parseIntFromData:data];
iOS整数は、LSB(最下位バイト)を最初のバイトに、MSBを最後のバイトに格納します。私はそれらすべてをテストするための変換ルーチンを持っています。ここをチェックして、
テスト...
int i = 2342342;
NSData * d1 = [Util dataFromInt:i]; // {[MSB], ..., ... ,[LSB]} <0023bdc6>
NSData * d2 = [NSData dataWithBytes:&i length:4]; // {[LSB], ..., ... ,[MSB]} <c6bd2300>
int ci1 = [Util intFromData:d1];
int ci2 = [Util intFromDataReverse:d2];
Util.m
+ (NSData *) dataFromInt:(int)num {
unsigned char * arr = (unsigned char *) malloc(sizeof(num) * sizeof(unsigned char));
for (int i = sizeof(num) - 1 ; i >= 0; i --) {
arr[i] = num & 0xFF;
num = num >> 8;
}
NSData * data = [NSData dataWithBytes:arr length:sizeof(num)];
free(arr);
return data;
}
// {[MSB], ..., ... ,[LSB]}
+ (int) intFromData:(NSData *)data
{
int intSize = sizeof(int); // change it to fixe length
unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
[data getBytes:buffer length:intSize];
int num = 0;
for (int i = 0; i < intSize; i++) {
num = (num << 8) + buffer[i];
}
free(buffer);
return num;
}
// {[LSB], ..., ... ,[MSB]}
+ (int) intFromDataReverse:(NSData *)data
{
int intSize = sizeof(int);// change it to fixe length
unsigned char * buffer = malloc(intSize * sizeof(unsigned char));
[data getBytes:buffer length:intSize];
int num = 0;
for (int i = intSize - 1; i >= 0; i--) {
num = (num << 8) + buffer[i];
}
free(buffer);
return num;
}
これは、デバイスのエンディアン表記に関連して、変換するデータのエンディアン表記に依存します。 エンディアンのウィキ
シンプルにするために、2つの方法を確認する必要があります。
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32BigToHost(*(int*)([data4 bytes]));
または
NSData *data4 = [completeData subdataWithRange:NSMakeRange(0, 4)];
int value = CFSwapInt32LittleToHost(*(int*)([data4 bytes]));
そして、データを解析するときに、どちらがより意味があるかを確認してください。
_vertexData
はNSData
であり、バッファ内でどのデータ(タイプ)が予期されるかがわかっているので、このブロックをNSDataの.length
プロパティ。この例では、各データブロックは2バイト(--8 x float値を格納)であり、5番目のfloat値からログを記録することに興味がありました。
float a,b,c,d; //prepare some values, no need to initialize
// loop thru assuming 8 floats are stored after each other
for (NSUInteger v = 0; v < _vertexData.length; v += sizeof(float)*8 ) {
// set a starting point for the range, here the 5th float
NSUInteger shift = v + (sizeof(float)*4);
// store result in a..
[_vertexData getBytes:&a range:NSMakeRange(shift,sizeof(a))];
// increase the starting point by the size of data before
shift += sizeof(a);
[_vertexData getBytes:&b range:NSMakeRange(shift,sizeof(b))];
shift += sizeof(b);
[_vertexData getBytes:&c range:NSMakeRange(shift,sizeof(c))];
shift += sizeof(c);
[_vertexData getBytes:&d range:NSMakeRange(shift,sizeof(d))];
fprintf(stderr, "r%f, g%f, b%f, a%f \n", a,b,c,d );
}
これはもっと短く書くことができたかもしれませんが、明確にするために、ミスリードのキャストをあまり使用していません
多分これは誰かを助ける