objective-c 将 NSData 字节转换为 NSString?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/550405/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:08:08  来源:igfitidea点击:

Convert NSData bytes to NSString?

objective-ccocoabittorrent

提问by dbr

I'm trying to use the BEncoding ObjC classto decode a .torrentfile.

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

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

When I NSLogtorrentI get the following:

当我NSLogtorrent得到以下信息时:

{
    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 nameinto a NSString? I have tried..

如何将 转换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);

..which retrives the data, but seems to have additional unicode rubbish after it:

..它检索数据,但后面似乎有额外的unicode垃圾:

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..

第一种方式(如 Apple 文档中提到的)正确返回大部分数据的事实,以及一些额外的字节让我认为这可能是 BEncoding 库中的错误..但我对 ObjC 缺乏了解更有可能是有过错..

采纳答案by Peter Hosey

NSData *torrent = [BEncoding objectFromEncodedData:rawdata];

When I NSLog torrent I get the following:

{
    ?
}
NSData *torrent = [BEncoding objectFromEncodedData:rawdata];

当我 NSLog torrent 时,我得到以下信息:

{
    ?
}

That would be an NSDictionary, then, not an NSData.

那将是一个 NSDictionary,而不是一个 NSData。

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)
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)

No, it retrieved the filename just fine; you simply printed it incorrectly. %stakes 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:

不,它检索文件名就好了;你只是打印错误。%s接受一个以空字符结尾的 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);

But null-terminating the data in an NSData object is wrong (except when you really doneed a C string). I'll get to the right way in a moment.

但是空终止 NSData 对象中的数据是错误的(除非您确实需要 C 字符串)。我马上就会找到正确的方法。

I have also tried […]..

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

..but this seems to return random Chinese characters:

扵湵畴???敤歳潴???椮潳

我也试过 […]..

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

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

扵湵畴???敤歳潴???椮潳

That's because your bytes are UTF-8, which encodes one character in (usually) one byte.

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

unicharis, and stringWithCharacters:length:accepts, UTF-16. In that encoding, one character is (usually) two bytes. (Hence the division by sizeof(unichar): it divides the number of bytes by 2 to get the number of characters.)

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

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).

所以你说“这是一些 UTF-16 数据”,然后它从每两个字节中生成一个字符;每对字节应该是两个字符,而不是一个,所以你得到了垃圾(结果大部分是 CJK 表意文字)。



You answered your own questionpretty well, except that stringWithUTF8String:is simpler than stringWithCString:encoding:for UTF-8-encoded strings.

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

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.)

但是,当您拥有长度时(就像拥有 NSData 时所做的那样),使用initWithBytes:length:encoding:. 它更容易,因为它不需要以空字符结尾的数据;它只是使用您已有的长度。(不要忘记释放或自动释放它。)

回答by Alasdair Allan

That's an important point that should be re-emphasized I think. It turns out that,

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

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

is not the same as,

不一样,

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

the first expects a NULL terminated byte string, the second doesn't. In the above two cases contentwill be NULL in the first example if the byte string isn't correctly terminated.

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

回答by user102008

How about

怎么样

NSString *content = [[[NSString alloc] initWithData:myData
                                           encoding:NSUTF8StringEncoding] autorelease];

回答by Ethan

A nice quick and dirty approach is to use NSString's stringWithFormatinitializer 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 convert NSDatainto a string pretty easily:

一个不错的快速而肮脏的方法是使用NSStringstringWithFormat初始化程序来帮助您。字符串格式化的不常用功能之一是在输出字符串时指定最大字符串长度的能力。使用这个方便的功能可以让你NSData很容易地转换成一个字符串:

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

If you want to output it to the log, it can be even easier:

如果你想把它输出到日志,它可以更容易:

NSLog(@"my Data: %.*s", [myData length], [myData bytes]);

回答by dbr

Aha, the NSStringmethod stringWithCStringworks correctly:

啊哈,该NSString方法stringWithCString工作正常:

With the bencoding.h/.mfiles added to your project, the complete .mfile:

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;
}

..and the output:

..和输出:

ubuntu-8.10-desktop-i386.iso

回答by Jay O'Conor

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.

在我无法控制被转换为字符串的数据的情况下,例如从网络读取,我更喜欢使用,NSString -initWithBytes:length:encoding:这样我就不会依赖于以 NULL 结尾的字符串来获得定义的结果。请注意,Apple 的文档说如果 cString 不是以 NULL 结尾的字符串,则结果未定义。

回答by DefenestrationDay

Use a category on NSData:

在 NSData 上使用一个类别:

NSData+NSString.h

NSData+NSString.h

@interface NSData (NSString)

- (NSString *)toString;

@end

NSData+NSString.m

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

Then just NSLog(@"Data is %@", [nsData toString])"

那么就 NSLog(@"Data is %@", [nsData toString])"

回答by user2652623

You can try this. Fine with me.

你可以试试这个。我都可以。

DLog(@"responeData: %@", [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSASCIIStringEncoding] autorelease]);

回答by Denis Kutlubaev

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:

有时您需要从 NSData 创建 Base64 编码的字符串。例如,当您创建电子邮件 MIME 时。在这种情况下,请使用以下内容:

#import "NSData+Base64.h"
NSString *string = [data base64EncodedString];

回答by MobilePundits

This will work.

这将起作用。

NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];