10

ここにかなり新しいiPhone開発者。TCP/IPソケット接続を介してRS232コマンドを予期しているデバイスにRS232コマンドを送信するアプリを構築します。通信部分がダウンしているので、ASCIIコマンドを正常に送信できます。それは私が問題を抱えている16進コードコマンドです。

したがって、(この形式で)送信する次の16進データがあるとします。

\ x1C \ x02d \ x00 \ x00 \ x00 \ xFF \ x7F

これを、sendメソッドが期待するNSDataオブジェクトに変換するにはどうすればよいですか?

明らかに、これはこの16進データでは機能しません(ただし、標準のASCIIコマンドでは機能します)。

NSString *commandascii;
NSData *commandToSend;
commandascii = @"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];

まず、\ x 16進コードの一部はエスケープ文字であり、XCodeでコンパイルすると「入力変換が停止しました...」という警告が表示されます。また、NSStringEncodingは、明らかにこの16進文字列にも適していません。

したがって、最初の問題は、私が推測するこの16進文字列を格納する方法、次にNSDataに変換する方法です。

何か案は?

4

9 に答える 9

31

「000522 1C EA0100FF」のようなNSStringsの16進のコード。「コマンド」は16進数のNSStringです。

command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
for (int i = 0; i < ([command length] / 2); i++) {
    byte_chars[0] = [command characterAtIndex:i*2];
    byte_chars[1] = [command characterAtIndex:i*2+1];
    whole_byte = strtol(byte_chars, NULL, 16);
    [commandToSend appendBytes:&whole_byte length:1]; 
}
NSLog(@"%@", commandToSend);
于 2010-03-01T01:42:40.730 に答える
9

NSStringのカテゴリに実装されたデコーダの例を次に示します。

#import <stdio.h>
#import <stdlib.h>
#import <string.h>

unsigned char strToChar (char a, char b)
{
    char encoder[3] = {'\0','\0','\0'};
    encoder[0] = a;
    encoder[1] = b;
    return (char) strtol(encoder,NULL,16);
}

@interface NSString (NSStringExtensions)
- (NSData *) decodeFromHexidecimal;
@end

@implementation NSString (NSStringExtensions)

- (NSData *) decodeFromHexidecimal;
{
    const char * bytes = [self cStringUsingEncoding: NSUTF8StringEncoding];
    NSUInteger length = strlen(bytes);
    unsigned char * r = (unsigned char *) malloc(length / 2 + 1);
    unsigned char * index = r;

    while ((*bytes) && (*(bytes +1))) {
        *index = strToChar(*bytes, *(bytes +1));
        index++;
        bytes+=2;
    }
    *index = '\0';

    NSData * result = [NSData dataWithBytes: r length: length / 2];
    free(r);

    return result;
}

@end
于 2010-02-26T02:25:10.657 に答える
4

16進データをハードコーディングできる場合:

const char bytes[] = "\x00\x12\x45\xAB";
size_t length = (sizeof bytes) - 1; //string literals have implicit trailing '\0'

NSData *data = [NSData dataWithBytes:bytes length:length];

コードで16進文字列を解釈する必要がある場合(16進文字列がと呼ばれる変数inputDatalengthOfInputDataあり、の長さであると想定inputData):


#define HexCharToNybble(x) ((char)((x > '9') ? tolower(x) - 'a' + 10 : x - '0') & 0xF)

int i;

NSMutableData *data = [NSMutableData data];

for (i = 0; i < lengthOfInputData;)
{
    char byteToAppend;

    if (i < (lengthOfInputData - 3) &&
        inputData[i+0] == '\\' &&
        inputData[i+1] == 'x' &&
        isxdigit(inputData[i+2]) &&
        isxdigit(inputData[i+3]))
    {
        byteToAppend = HexCharToNybble(inputData[i+2]) << 4 + HexCharToNybble(input[i+3]);
        i += 4;
    }
    else
    {
        byteToAppend = inputData[i];
        i += 1;
    }

    [data appendBytes:&byteToAppend length:1];
}
于 2010-02-26T04:00:33.240 に答える
2

これは古いトピックですが、いくつかコメントを追加したいと思います。

•で文字列をスキャンするの[NSString characterAtIndex]はあまり効率的ではありません。UTF8でC文字列を取得し、aを使用してスキャンする*char++方がはるかに高速です。

NSMutableData時間のかかるブロックのサイズ変更を避けるために、容量を割り当てて割り当てることをお勧めします。NSDataはさらに優れていると思います(次のポイントを参照)

•mallocを使用してNSDataを作成する代わりに[NSData dataWithBytes]、最後に無料で、mallocを使用します。[NSData dataWithBytesNoCopy:length:freeWhenDone:]

また、メモリ操作(再割り当て、コピー、解放)も回避します。freeWhenDoneブール値は、NSDataにメモリブロックの所有権を取得し、解放されるときに解放するように指示します。

•これは、16進文字列をバイトブロックに変換する必要がある関数です。入力文字列のエラーチェックはそれほど多くありませんが、割り当てはテストされます。

入力文字列のフォーマット(0x、スペース、句読点の削除など)は、変換関数を使用しない方が適切です。入力に問題がないと確信しているのに、なぜ余分な処理を行うのに時間がかかるのでしょうか。

+(NSData*)bytesStringToData:(NSString*)bytesString
{
    if (!bytesString || !bytesString.length) return NULL;
    // Get the c string
    const char *scanner=[bytesString cStringUsingEncoding:NSUTF8StringEncoding];
    char twoChars[3]={0,0,0};
    long bytesBlockSize = formattedBytesString.length/2;
    long counter = bytesBlockSize;
    Byte *bytesBlock = malloc(bytesBlockSize);
    if (!bytesBlock) return NULL;
    Byte *writer = bytesBlock;
    while (counter--) {
        twoChars[0]=*scanner++;
        twoChars[1]=*scanner++;
        *writer++ = strtol(twoChars, NULL, 16);
    }
    return[NSData dataWithBytesNoCopy:bytesBlock length:bytesBlockSize freeWhenDone:YES];
}
于 2013-06-09T04:17:26.590 に答える
1

バイトをハードコーディングしたい場合は、次のようにします。

enum { numCommandBytes = 8 };
static const unsigned char commandBytes[numCommandBytes] = { 0x1c, 0x02, 'd', 0x0, 0x0, 0x0, 0xff, 0x7f };

実行時にこれらの円記号でエスケープされたバイトを取得している場合は、関数を試しstrunvisください

明らかに、これはこの16進データでは機能しません(ただし、標準のASCIIコマンドでは機能します)。

NSString *commandascii;
NSData *commandToSend;
commandascii = @"\x1C\x02d\x00\x00\x00\xFF\x7F";
commandToSend = [commandascii dataUsingEncoding:NSStringEncoding];

まず、\x16進コードの一部はエスケープ文字であり、XCodeでコンパイルすると「入力変換が停止しました...」という警告が表示されます。また、NSStringEncodingは、明らかにこの16進文字列にも適していません。

まず、小文字のcを使用したXcodeです。

次に、NSStringEncodingはタイプであり、エンコーディング識別子ではありません。そのコードはまったくコンパイルされるべきではありません。

さらに重要なことに、バックスラッシュエスケープはエンコーディングではありません。実際、それはエンコーディングとはほとんど無関係です。バックスラッシュと「x」はバイトではなく文字です。つまり、これらはバイトにエンコード(およびデコード)する必要があります。これはエンコードの仕事です。

于 2010-02-26T17:24:29.683 に答える
0

それを行う別の方法。

-(NSData *) dataFromHexString:(NSString *) hexstr
{
    NSMutableData *data = [[NSMutableData alloc] init];
    NSString *inputStr = [hexstr uppercaseString];

    NSString *hexChars = @"0123456789ABCDEF";

    Byte b1,b2;
    b1 = 255;
    b2 = 255;
    for (int i=0; i<hexstr.length; i++) {
        NSString *subStr = [inputStr substringWithRange:NSMakeRange(i, 1)];
        NSRange loc = [hexChars rangeOfString:subStr];

        if (loc.location == NSNotFound) continue;

        if (255 == b1) {
            b1 = (Byte)loc.location;
        }else {
            b2 = (Byte)loc.location;

            //Appending the Byte to NSData
            Byte *bytes = malloc(sizeof(Byte) *1);
            bytes[0] = ((b1<<4) & 0xf0) | (b2 & 0x0f);
            [data appendBytes:bytes length:1];

            b1 = b2 = 255;
        }
    }

    return data;
}
于 2014-04-22T09:48:01.733 に答える
0
-(NSData*) convertToByteArray:(NSString*) command {
    if (command == nil || command.length == 0) return nil;
    NSString *command1 = command;
    if(command1.length%2 != 0) {
        // to handle odd bytes like 1000 decimal = 3E8 with is of length = 3
        command1 = [NSString stringWithFormat:@"0%@",command1];
    }
    NSUInteger length = command1.length/2 ;
    NSMutableData *commandToSend = [[NSMutableData alloc] initWithLength:length];
    char byte_chars[3] = {'\0','\0','\0'};
    unsigned char whole_byte;
    for (int i=0; i<length; i++) {
        byte_chars[0] = [command1 characterAtIndex:i*2];
        byte_chars[1] = [command1 characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [commandToSend appendBytes:&whole_byte length:1];
    }
    NSRange commandRange = NSMakeRange(commandToSend.length - length, length);
    NSData *result = [commandToSend subdataWithRange:commandRange];
    return result;
}
于 2018-06-03T13:53:16.207 に答える
-1

これは非常に古いスレッドですが、Objective Cには、16進コードの文字列をASCII文字に簡単に変換できるエンコードスキームがあります。

1)文字列からを削除し\x、文字列にスペースを入れずに、文字列を次をNSData使用するように変換します。

[[NSData alloc] initWithData:[stringToBeConverted dataUsingEncoding:NSASCIIStringEncoding]];
于 2014-10-13T04:43:34.507 に答える
-3

16進データは、メモリ内の単なるバイトです。文字列と見なすことができます。これは、データの表示方法ですが、何でも表すことができるためです。試してください:(ブラウザに入力します。エラーが含まれている可能性があります)

NSMutableData *hexData = [[NSMutableData alloc] init];

[hexData appendBytes: 0x1C];
[hexData appendBytes: 0x02D];

等...

于 2010-02-26T02:16:08.840 に答える