50

BEncoding ObjC クラスを使用してファイルをデコードしようとしてい.torrentます。

NSData *rawdata = [NSData dataWithContentsOfFile:@"/path/to/the.torrent"];
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];

私が次のものを手に入れたときNSLog torrent

{
    announce = <68747470 3a2f2f74 6f727265 6e742e75 62756e74 752e636f 6d3a3639 36392f61 6e6e6f75 6e6365>;
    comment = <5562756e 74752043 44207265 6c656173 65732e75 62756e74 752e636f 6d>;
    "creation date" = 1225365524;
    info =     {
        length = 732766208;
        name = <7562756e 74752d38 2e31302d 6465736b 746f702d 69333836 2e69736f>;
        "piece length" = 524288;
....

nameを NSStringに変換するにはどうすればよいですか? 私が試してみました..

NSData *info = [torrent valueForKey:@"info"];
NSData *name = [info valueForKey:@"name"];
unsigned char aBuffer[[name length]];
[name getBytes:aBuffer length:[name length]];
NSLog(@"File name: %s", aBuffer);

..データを取得しますが、その後にユニコードのごみが追加されているようです:

File name: ubuntu-8.10-desktop-i386.iso)

私も試しました(ここから)..

NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];

..しかし、これはランダムな文字の束を返すようです:

扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳

最初の方法 (Apple のドキュメントに記載されているように) がほとんどのデータを正しく返し、いくつかの追加バイトが返されるという事実は、BEncoding ライブラリのエラーである可能性があると思います..しかし、ObjC に関する知識が不足している可能性が高くなります故障して..

4

10 に答える 10

100

これは、もう一度強調すべき重要な点だと思います。それは、

NSString *content = [NSString stringWithUTF8String:[responseData bytes]];

と同じではありません。

NSString *content = [[NSString alloc]  initWithBytes:[responseData bytes]
              length:[responseData length] encoding: NSUTF8StringEncoding];

1 つ目は NULL で終了するバイト文字列を想定していますが、2 つ目はそうではありません。上記の 2 つのケースcontentでは、バイト文字列が正しく終了していない場合、最初の例では NULL になります。

于 2009-03-02T23:39:24.243 に答える
20

どうですか

NSString *content = [[[NSString alloc] initWithData:myData
                                           encoding:NSUTF8StringEncoding] autorelease];
于 2011-02-10T01:24:16.877 に答える
19
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];

NSLog torrent を実行すると、次のようになります。

{
    ⋮
}

それは NSData ではなく、NSDictionary になります。

unsigned char aBuffer[[name length]];
[name getBytes:aBuffer length:[name length]];
NSLog(@"File name: %s", aBuffer);

..データを取得しますが、その後にユニコードのごみが追加されているようです:

File name: ubuntu-8.10-desktop-i386.iso)

いいえ、問題なくファイル名を取得しました。単に間違って印刷しただけです。%snull で終わる C 文字列を取ります。データ オブジェクトのバイトは null で終了しません (バイトは単なるバイトであり、どのエンコーディングでも文字であるとは限りません。文字として null である 0 は完全に有効なバイトです)。もう 1 文字を割り当て、配列の最後の文字を 0 に設定する必要があります。

size_t length = [name length] + 1;
unsigned char aBuffer[length];
[name getBytes:aBuffer length:length];
aBuffer[length - 1] = 0;
NSLog(@"File name: %s", aBuffer);

しかし、NSData オブジェクトのデータを null で終了するのは間違っています (本当にC 文字列が必要な場合を除きます)。すぐに正しい道に着きます。

私も試してみました […]..

NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];

..しかし、これはランダムな漢字を返すようです:

扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳

これは、バイトが UTF-8 であり、(通常) 1 バイトで 1 文字をエンコードするためです。

unicharでありstringWithCharacters:length:、UTF-16 を受け入れます。そのエンコーディングでは、1 文字は (通常) 2 バイトです。(したがって、 による除算sizeof(unichar): バイト数を 2 で割り、文字数を取得します。)

つまり、「これが UTF-16 データです」と言うと、2 バイトごとに文字が作成されました。バイトの各ペアは、1 文字ではなく 2 文字であると想定されていたため、ゴミが発生しました (ほとんどが CJK 表意文字であることが判明しました)。


UTF-8 でエンコードされた文字列stringWithUTF8String:よりも単純であることを除いて、あなたは自分の質問にかなりよく答えました。stringWithCString:encoding:

ただし、長さがある場合 (NSData がある場合のように)、 を使用するのはさらに簡単で、より適切initWithBytes:length:encoding:です。null で終わるデータを必要としないため、簡単です。すでに持っている長さを使用するだけです。(解放または自動解放することを忘れないでください。)

于 2009-02-17T00:07:11.983 に答える
7

手っ取り早く汚い方法は、NSStringstringWithFormatイニシャライザを使用して解決することです。文字列フォーマットのあまり使用されない機能の 1 つは、文字列を出力するときに最大文字列長を指定する機能です。この便利な機能を使用するとNSData、非常に簡単に文字列に変換できます。

NSData *myData = [self getDataFromSomewhere];
NSString *string = [NSString stringWithFormat:@"%.*s", [myData length], [myData bytes]];

ログに出力したい場合は、さらに簡単です。

NSLog(@"my Data: %.*s", [myData length], [myData bytes]);
于 2009-08-26T00:49:14.503 に答える
6

ああ、NSStringメソッドstringWithCStringは正しく動作します:

プロジェクトにbencoding.h/.mファイルを追加すると、完全な.mファイルは次のようになります。

#import <Foundation/Foundation.h>
#import "BEncoding.h"

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // Read raw file, and de-bencode
    NSData *rawdata = [NSData dataWithContentsOfFile:@"/path/to/a.torrent"];
    NSData *torrent = [BEncoding objectFromEncodedData:rawdata];

    // Get the file name
    NSData *infoData = [torrent valueForKey:@"info"];
    NSData *nameData = [infoData valueForKey:@"name"];
    NSString *filename = [NSString stringWithCString:[nameData bytes] encoding:NSUTF8StringEncoding];
    NSLog(@"%@", filename);

    [pool drain];
    return 0;
}

..そして出力:

ubuntu-8.10-desktop-i386.iso
于 2009-02-15T06:22:13.153 に答える
2

ネットワークからの読み取りなど、文字列に変換されるデータを制御できない場合は、NSString -initWithBytes:length:encoding:定義された結果を得るために NULL で終了する文字列に依存しないように使用することを好みます。Apple のドキュメントには、cString が NULL で終了する文字列でない場合、結果は未定義であると記載されていることに注意してください。

于 2009-02-16T01:18:58.200 に答える
2

NSData でカテゴリを使用します。

NSData+NSString.h

@interface NSData (NSString)

- (NSString *)toString;

@end

NSData+NSString.m

#import "NSData+NSString.h"

@implementation NSData (NSString)

- (NSString *)toString
{
    Byte *dataPointer = (Byte *)[self bytes];
    NSMutableString *result = [NSMutableString stringWithCapacity:0];
    NSUInteger index;
    for (index = 0; index < [self length]; index++)
    {
        [result appendFormat:@"0x%02x,", dataPointer[index]];
    }
    return result;
}

@end

それからちょうどNSLog(@"Data is %@", [nsData toString])"

于 2012-03-02T00:06:33.390 に答える
0

NSDataからBase64でエンコードされた文字列を作成する必要がある場合があります。たとえば、電子メールMIMEを作成する場合です。この場合、以下を使用します。

#import "NSData+Base64.h"
NSString *string = [data base64EncodedString];
于 2012-10-05T15:21:14.230 に答える
0

これは機能します。

NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
于 2013-06-05T06:16:21.180 に答える