将NSData字节转换为NSString?
我正在尝试使用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);
..回顾数据,但似乎有额外的unicode垃圾:
File name: ubuntu-8.10-desktop-i386.iso)
我也试过( 从这里 )..
NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];
..但是这似乎返回一堆随机字符:
扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳
事实上,第一种方式(正如苹果文档中所提到的)正确地返回了大部分数据,还有一些额外的字节让我觉得这可能是BEncoding库中的一个错误。但是我对于ObjC的知识缺乏的可能性更大有过错..
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];
当我NSLog洪stream我得到以下内容:
{ ⋮ }
那将是一个NSDictionary,那么,不是一个NSData。
unsigned char aBuffer[[name length]]; [name getBytes:aBuffer length:[name length]]; NSLog(@"File name: %s", aBuffer);
..回顾数据,但似乎有额外的unicode垃圾:
File name: ubuntu-8.10-desktop-i386.iso)
不,它检索文件名就好了; 你只是打印错误。 %s
取一个Cstring,它以null结尾; 数据对象的字节不是空终止的(它们只是字节,不一定是任何编码中的字符,而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);
但是在NSData对象中的空数据终止是错误的(除非你确实需要一个Cstring)。 我马上就会走对了。
我也试过[…] ..
NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];
..但是这似乎是随机的中文字符:
扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳
这是因为你的字节是UTF-8,它在(通常)一个字节中编码一个字符。
unichar
是,而stringWithCharacters:length:
接受,UTF-16。 在该编码中,一个字符(通常)是两个字节。 (因此,按sizeof(unichar)
划分:将字节数除以2以得到字符数。)
所以你说“这是一些UTF-16的数据”,它从每两个字节去做字符; 每一对字节应该是两个字符,而不是一个,所以你有垃圾(原来主要是CJK的表意文字)。
你很好地回答了你自己的问题 ,除了stringWithUTF8String:
比stringWithCString:encoding:
简单stringWithCString:encoding:
用于UTF-8编码的string。
但是,当你有长度的时候(就像你有一个NSData的时候那样),使用initWithBytes:length:encoding:
就更容易,也更合适。 这很容易,因为它不需要以null结尾的数据; 它只是使用你已经有的长度。 (不要忘记释放或autorelease它。)
这是我认为应该重新强调的重要一点。 事实certificate,
NSString *content = [NSString stringWithUTF8String:[responseData bytes]];
是不一样的,
NSString *content = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding: NSUTF8StringEncoding];
第一个期望一个NULL终止字节的string,第二个没有。 在上述两种情况下,如果字节string未正确终止, content
将在第一个示例中为NULL。
怎么样
NSString *content = [[[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding] autorelease];
一个好的快速和肮脏的方法是使用NSString
的stringWithFormat
初始值stringWithFormat
程序来帮助你。 string格式化不常用的function之一是能够在输出string时指定最大string长度。 使用这个方便的function,您可以很容易地将NSData
转换为string:
NSData *myData = [self getDataFromSomewhere]; NSString *string = [NSString stringWithFormat:@"%.*s", [myData length], [myData bytes]];
如果你想把它输出到日志,它可以更容易:
NSLog(@"my Data: %.*s", [myData length], [myData bytes]);
啊哈, 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
在我无法控制数据被转换成string(比如从networking中读取)的情况下,我宁愿使用NSString -initWithBytes:length:encoding:
这样我就不依赖于以NULL结尾的string以获得定义的结果。 请注意,苹果的文档说,如果cString不是一个NULL结束的string,结果是不确定的。
你可以试试这个 这对我很好
DLog(@"responeData: %@", [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSASCIIStringEncoding] autorelease]);
在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])"
有时你需要从NSData创buildBase64编码的string。 例如,当你创build一个电子邮件MIME。 在这种情况下使用以下内容:
#import "NSData+Base64.h" NSString *string = [data base64EncodedString];
我想你应该尝试这个代码,因为我已经使用它,它会工作。
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];