102

NSData オブジェクトを 16 進数の文字列にシリアル化するためのナイス ココアの方法を探しています。アイデアは、通知に使用される deviceToken をサーバーに送信する前にシリアル化することです。

私は次の実装を持っていますが、それを行うためのより短くて良い方法が必要だと考えています。

+ (NSString*) serializeDeviceToken:(NSData*) deviceToken
{
    NSMutableString *str = [NSMutableString stringWithCapacity:64];
    int length = [deviceToken length];
    char *bytes = malloc(sizeof(char) * length);

    [deviceToken getBytes:bytes length:length];

    for (int i = 0; i < length; i++)
    {
        [str appendFormat:@"%02.2hhX", bytes[i]];
    }
    free(bytes);

    return str;
}
4

15 に答える 15

208

これは私が書いた NSData に適用されるカテゴリです。NSData を表す 16 進数の NSString を返します。データの長さは任意です。NSData が空の場合、空の文字列を返します。

NSData+Conversion.h

#import <Foundation/Foundation.h>

@interface NSData (NSData_Conversion)

#pragma mark - String Conversion
- (NSString *)hexadecimalString;

@end

NSData+Conversion.m

#import "NSData+Conversion.h"

@implementation NSData (NSData_Conversion)

#pragma mark - String Conversion
- (NSString *)hexadecimalString {
    /* Returns hexadecimal string of NSData. Empty string if data is empty.   */

    const unsigned char *dataBuffer = (const unsigned char *)[self bytes];

    if (!dataBuffer)
        return [NSString string];

    NSUInteger          dataLength  = [self length];
    NSMutableString     *hexString  = [NSMutableString stringWithCapacity:(dataLength * 2)];

    for (int i = 0; i < dataLength; ++i)
        [hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];

    return [NSString stringWithString:hexString];
}

@end

使用法:

NSData *someData = ...;
NSString *someDataHexadecimalString = [someData hexadecimalString];

[someData description]これは、呼び出してからスペース、<、および > を削除するよりも「おそらく」優れています。キャラクターを剥ぎ取るのはあまりにも「ハッキー」に感じます。さらに、Apple が将来 NSData のフォーマットを変更するかどうかはわかりません-description

注:この回答のコードのライセンスについて、人々から連絡がありました。私はここに、この回答で投稿したコードの著作権をパブリック ドメインに捧げます。

于 2012-01-31T18:18:46.487 に答える
17

NSData の description プロパティを使用することは、文字列を HEX エンコードするための受け入れ可能なメカニズムと見なされるべきではありません。このプロパティは説明のみを目的としており、いつでも変更できます。注意として、iOS より前の NSData 記述プロパティは、そのデータを 16 進形式で返すことすらありませんでした。

解決策について口論して申し訳ありませんが、データのシリアライゼーション以外を目的とした API に便乗することなく、シリアライズに力を入れることが重要です。

@implementation NSData (Hex)

- (NSString*)hexString
{
    NSUInteger length = self.length;
    unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (length*2));
    unsigned char* bytes = (unsigned char*)self.bytes;
    for (NSUInteger i = 0; i < length; i++) {
        unichar c = bytes[i] / 16;
        if (c < 10) {
            c += '0';
        } else {
            c += 'A' - 10;
        }
        hexChars[i*2] = c;

        c = bytes[i] % 16;
        if (c < 10) {
            c += '0';
        } else {
            c += 'A' - 10;
        }
        hexChars[i*2+1] = c;
    }
    NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars length:length*2 freeWhenDone:YES];
    return [retVal autorelease];
}

@end
于 2012-01-25T19:53:10.383 に答える
1

いつでも[yourStringuppercaseString]を使用して、データの説明で文字を大文字にすることができます

于 2011-04-29T09:52:47.253 に答える
1

NSData を NSString にシリアライズ/デシリアライズするより良い方法は、Google Toolbox for Mac Base64 エンコーダ/デコーダを使用することです。パッケージ Foundation からファイル GTMBase64.m、GTMBase64.he GTMDefines.h をアプリ プロジェクトにドラッグするだけで、次のように実行できます。

/**
 * Serialize NSData to Base64 encoded NSString
 */
-(void) serialize:(NSData*)data {

    self.encodedData = [GTMBase64 stringByEncodingData:data];

}

/**
 * Deserialize Base64 NSString to NSData
 */
-(NSData*) deserialize {

    return [GTMBase64 decodeString:self.encodedData];

}
于 2011-06-09T10:31:30.503 に答える
1

可変長文字列で機能する答えが必要だったので、私がしたことは次のとおりです。

+ (NSString *)stringWithHexFromData:(NSData *)data
{
    NSString *result = [[data description] stringByReplacingOccurrencesOfString:@" " withString:@""];
    result = [result substringWithRange:NSMakeRange(1, [result length] - 2)];
    return result;
}

NSString クラスの拡張機能として最適です。

于 2010-12-02T19:51:26.640 に答える
0

に変更%08x%08Xて大文字を取得します。

于 2010-07-08T15:45:44.497 に答える
0
@implementation NSData (Extn)

- (NSString *)description
{
    NSMutableString *str = [[NSMutableString alloc] init];
    const char *bytes = self.bytes;
    for (int i = 0; i < [self length]; i++) {
        [str appendFormat:@"%02hhX ", bytes[i]];
    }
    return [str autorelease];
}

@end

Now you can call NSLog(@"hex value: %@", data)
于 2013-11-02T01:41:55.767 に答える
0

スウィフト + プロパティ。

bytesプロパティとして16進表現を使用することを好みます(およびプロパティと同じdescription):

extension NSData {

    var hexString: String {

        let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count: self.length)
        return buffer.map { String(format: "%02x", $0) }.joinWithSeparator("")
    }

    var heXString: String {

        let buffer = UnsafeBufferPointer<UInt8>(start: UnsafePointer(self.bytes), count: self.length)
        return buffer.map { String(format: "%02X", $0) }.joinWithSeparator("")
    }
}

アイデアはこの回答から借用されています

于 2016-06-30T13:38:12.903 に答える
-4
[deviceToken description]

スペースを削除する必要があります。

個人的には をbase64エンコードしますdeviceTokenが、それは好みの問題です。

于 2009-08-20T12:10:57.463 に答える