将NSData字节转换为NSString?

dbr*_*dbr 49 cocoa bittorrent objective-c

我正在尝试使用BEncoding ObjC类来解码.torrent文件.

NSData *rawdata = [NSData dataWithContentsOfFile:@"/path/to/the.torrent"];
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];
Run Code Online (Sandbox Code Playgroud)

当我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;
....
Run Code Online (Sandbox Code Playgroud)

如何将其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);
Run Code Online (Sandbox Code Playgroud)

..which检索数据,但似乎有其他unicode垃圾:

File name: ubuntu-8.10-desktop-i386.iso)
Run Code Online (Sandbox Code Playgroud)

我也试过(从这里)..

NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];
Run Code Online (Sandbox Code Playgroud)

..但这似乎返回了一堆随机字符:

??????????????
Run Code Online (Sandbox Code Playgroud)

事实上第一种方式(如Apple文档中所述)正确地返回大部分数据,一些额外的字节使我认为它可能是BEncoding库中的一个错误..但我对ObjC缺乏了解更有可能是有过错..

Ala*_*lan 99

这是一个重要的观点,我认为应该再次强调.事实证明,

NSString *content = [NSString stringWithUTF8String:[responseData bytes]];
Run Code Online (Sandbox Code Playgroud)

是不一样的,

NSString *content = [[NSString alloc]  initWithBytes:[responseData bytes]
              length:[responseData length] encoding: NSUTF8StringEncoding];
Run Code Online (Sandbox Code Playgroud)

第一个期望NULL终止字节串,第二个不期望.在上述两种情况下content,如果字节串未正确终止,则第一个示例中将为NULL.

  • +1我因为一个我根本想不通的错误而被杀.感谢您的深刻见解.你让我免于沮丧. (2认同)

use*_*008 20

怎么样

NSString *content = [[[NSString alloc] initWithData:myData
                                           encoding:NSUTF8StringEncoding] autorelease];
Run Code Online (Sandbox Code Playgroud)


Pet*_*sey 19

NSData *torrent = [BEncoding objectFromEncodedData:rawdata];
Run Code Online (Sandbox Code Playgroud)

当我NSLog洪流时,我得到以下内容:

{
    ?
}
Run Code Online (Sandbox Code Playgroud)

那将是一个NSDictionary,然后,不是NSData.

unsigned char aBuffer[[name length]];
[name getBytes:aBuffer length:[name length]];
NSLog(@"File name: %s", aBuffer);
Run Code Online (Sandbox Code Playgroud)

..which检索数据,但似乎有其他unicode垃圾:

File name: ubuntu-8.10-desktop-i386.iso)
Run Code Online (Sandbox Code Playgroud)

不,它检索文件名就好了; 你只是错误地打印它.%s接受一个以C结尾的C字符串; 数据对象的字节不是以空值终止的(它们只是字节,不一定是任何编码中的字符,而0-作为字符为空 - 是一个完全有效的字节).您将不得不再分配一个字符,并将数组中的最后一个字符设置为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);
Run Code Online (Sandbox Code Playgroud)

但是null终止NSData对象中的数据是错误的(除非你确实需要一个C字符串).我马上就能找到正确的方法.

我也试过[...] ..

NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];
Run Code Online (Sandbox Code Playgroud)

..但这似乎返回随机的汉字:

??????????????
Run Code Online (Sandbox Code Playgroud)

那是因为你的字节是UTF-8,它在(通常)一个字节中编码一个字符.

unichar是,并stringWithCharacters:length:接受,UTF-16.在该编码中,一个字符(通常)是两个字节.(因此除以sizeof(unichar):它将字节数除以2得到字符数.)

所以你说"这里有一些UTF-16数据",它从每两个字节开始制作字符; 每对字节应该是两个字符,而不是一个,所以你有垃圾(原来是CJK表意文字).


很好地回答了自己的问题,除了stringWithUTF8String:stringWithCString:encoding:UTF-8编码的字符串更简单.

但是,当你有长度时(就像你拥有NSData时那样),使用起来更容易,也更合适initWithBytes:length:encoding:.它更容易,因为它不需要以空值终止的数据; 它只是使用你已经拥有的长度.(不要忘记释放或自动释放它.)


Eth*_*han 7

一个很好的快速和肮脏的方法是使用NSStringstringWithFormat初始化程序来帮助你.字符串格式化中不常使用的一个特性是在输出字符串时指定最大字符串长度的能力.使用这个方便的功能,您可以NSData很容易地转换为字符串:

NSData *myData = [self getDataFromSomewhere];
NSString *string = [NSString stringWithFormat:@"%.*s", [myData length], [myData bytes]];
Run Code Online (Sandbox Code Playgroud)

如果要将其输出到日志,可以更容易:

NSLog(@"my Data: %.*s", [myData length], [myData bytes]);
Run Code Online (Sandbox Code Playgroud)


dbr*_*dbr 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;
}
Run Code Online (Sandbox Code Playgroud)

..和输出:

ubuntu-8.10-desktop-i386.iso
Run Code Online (Sandbox Code Playgroud)