将 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;
....
How do I conversion the name
into a 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)];
..但这似乎返回了一堆随机字符:
扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳
事实上,第一种方法(如Apple文档中提到的)正确返回了大部分数据,还有一些额外的字节让我觉得这可能是 BEncoding 库中的错误..但我对 ObjC 缺乏了解更有可能是错误..
I'm trying to use the BEncoding ObjC class to decode a .torrent
file.
NSData *rawdata = [NSData dataWithContentsOfFile:@"/path/to/the.torrent"];
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];
When I NSLog
torrent
I get the following:
{
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;
....
How do I convert the name
into a NSString? I have tried..
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);
..which retrives the data, but seems to have additional unicode rubbish after it:
File name: ubuntu-8.10-desktop-i386.iso)
I have also tried (from here)..
NSString *secondtry = [NSString stringWithCharacters:[name bytes] length:[name length] / sizeof(unichar)];
..but this seems to return a bunch of random characters:
扵湵畴㠭ㄮⴰ敤歳潴⵰㍩㘸椮潳
The fact the first way (as mentioned in the Apple documentation) returns most of the data correctly, with some additional bytes makes me think it might be an error in the BEncoding library.. but my lack of knowledge about ObjC is more likely to be at fault..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
我认为这是应该再次强调的重要一点。 事实证明,
不同
与第一个期望以 NULL 结尾的字节字符串 ,第二个则不需要。 在上述两种情况下,如果字节字符串未正确终止,则第一个示例中的
content
将为 NULL。That's an important point that should be re-emphasized I think. It turns out that,
is not the same as,
the first expects a NULL terminated byte string, the second doesn't. In the above two cases
content
will be NULL in the first example if the byte string isn't correctly terminated.怎么样
How about
那将是一个 NSDictionary,而不是一个 NSData。
不,它检索文件名很好; 您只是打印错误。
%s
接受一个以 null 结尾的 C 字符串; 数据对象的字节不是以 null 结尾的(它们只是字节,不一定是任何编码中的字符,并且 0(作为字符为 null)是完全有效的字节)。 您必须再分配一个字符,并将数组中的最后一个字符设置为 0:但是以 null 终止 NSData 对象中的数据是错误的(除非您确实需要 C 字符串) 。 我一会儿就会找到正确的方法。
那是因为你的字节是UTF-8,它在(通常)一个字节中编码一个字符。
unichar
是,并且stringWithCharacters:length:
接受 UTF-16。 在该编码中,一个字符(通常)是两个字节。 (因此除以sizeof(unichar)
:它将字节数除以 2 以获得字符数。)所以你说“这里有一些 UTF-16 数据”,然后它就生成了每两个字节的字符; 每对字节应该是两个字符,而不是一个,所以你得到了垃圾(结果大部分是 CJK 表意文字)。
您很好地回答了自己的问题,除了
stringWithUTF8String :
比 UTF-8 编码字符串的stringWithCString:encoding:
更简单。然而,当你有长度时(就像你有一个 NSData 时所做的那样),使用 initWithBytes:length:encoding: 会更容易、更合适。 它更容易,因为它不需要以 null 结尾的数据; 它只是使用您已有的长度。 (不要忘记释放或自动释放它。)
That would be an NSDictionary, then, not an NSData.
No, it retrieved the filename just fine; you simply printed it incorrectly.
%s
takes a C string, which is null-terminated; the bytes of a data object are not null-terminated (they are just bytes, not necessarily characters in any encoding, and 0—which is null as a character—is a perfectly valid byte). You would have to allocate one more character, and set the last one in the array to 0:But null-terminating the data in an NSData object is wrong (except when you really do need a C string). I'll get to the right way in a moment.
That's because your bytes are UTF-8, which encodes one character in (usually) one byte.
unichar
is, andstringWithCharacters:length:
accepts, UTF-16. In that encoding, one character is (usually) two bytes. (Hence the division bysizeof(unichar)
: it divides the number of bytes by 2 to get the number of characters.)So you said “here's some UTF-16 data”, and it went and made characters from every two bytes; each pair of bytes was supposed to be two characters, not one, so you got garbage (which turned out to be mostly CJK ideographs).
You answered your own question pretty well, except that
stringWithUTF8String:
is simpler thanstringWithCString:encoding:
for UTF-8-encoded strings.However, when you have the length (as you do when you have an NSData), it is even easier—and more proper—to use
initWithBytes:length:encoding:
. It's easier because it does not require null-terminated data; it simply uses the length you already have. (Don't forget to release or autorelease it.)一个快速而肮脏的方法是使用 NSString 的 stringWithFormat 初始化器来帮助您。 字符串格式化不太常用的功能之一是能够在输出字符串时指定最大字符串长度。 使用这个方便的功能可以让您非常轻松地将
NSData
转换为字符串:如果您想将其输出到日志,则可以更容易:
A nice quick and dirty approach is to use
NSString
'sstringWithFormat
initializer to help you out. One of the less-often used features of string formatting is the ability to specify a mximum string length when outputting a string. Using this handy feature allows you to convertNSData
into a string pretty easily:If you want to output it to the log, it can be even easier:
啊哈,
NSString
方法stringWithCString
工作正常:将
bencoding.h/.m
文件添加到您的项目后,完整的. m
文件:..和输出:
Aha, the
NSString
methodstringWithCString
works correctly:With the
bencoding.h/.m
files added to your project, the complete.m
file:..and the output:
如果我无法控制数据转换为字符串,例如从网络读取,我更喜欢使用 NSString -initWithBytes:length:encoding: ,这样我就不会依赖于 NULL 终止的字符串以获得定义的结果。 请注意,Apple 的文档指出,如果 cString 不是以 NULL 结尾的字符串,则结果是未定义的。
In cases where I don't have control over the data being transformed into a string, such as reading from the network, I prefer to use
NSString -initWithBytes:length:encoding:
so that I'm not dependent upon having a NULL terminated string in order to get defined results. Note that Apple's documentation says if cString is not a NULL terminated string, that the results are undefined.在 NSData 上使用类别:
NSData+NSString.h
NSData+NSString.m
然后只需
NSLog(@"Data is %@", [nsData toString])"
Use a category on NSData:
NSData+NSString.h
NSData+NSString.m
Then just
NSLog(@"Data is %@", [nsData toString])"
你可以试试这个。 我都可以。
You can try this. Fine with me.
有时您需要从 NSData 创建 Base64 编码的字符串。 例如,当您创建电子邮件 MIME 时。 在这种情况下,请使用以下命令:
Sometimes you need to create Base64 encoded string from NSData. For instance, when you create a e-mail MIME. In this case use the following:
这会起作用。
This will work.