【问题标题】:Converting NSData to base64将 NSData 转换为 base64
【发布时间】:2011-01-12 22:22:34
【问题描述】:

如何将NSData 转换为base64。我有NSData 并想转换成base64 我该怎么做?

【问题讨论】:

标签: iphone base64 nsdata


【解决方案1】:

iOS 始终包含对 base64 编码和解码的内置支持。如果您查看resolv.h,您应该会看到b64_ntopb64_pton 这两个函数。 Square SocketRocket 库提供了一个合理的示例,说明如何使用 Objective-c 中的这些函数。

这些功能经过了很好的测试并且非常可靠 - 与您在互联网上随机发布的许多实现不同。 不要忘记链接到libresolv.dylib

如果您链接 iOS 7 SDK,您可以使用更新的方法initWithBase64Encoding:base64EncodedDataWithOptions:。这些存在于以前的版本中,但是是私有的。因此,如果您链​​接到 6 SDK,您可能会遇到未定义的行为。这将是一个仅在链接到 7 SDK 时如何使用它的示例:

#ifndef __IPHONE_7_0
    // oh no! you are using something unsupported!
    // Call and implementation that uses b64_pton here
#else
    data = [[NSData alloc] initWithBase64Encoding:string];
#endif

【讨论】:

    【解决方案2】:

    编辑

    从 OS X 10.9 / iOS 7 开始,这是内置在框架中的。

    -[NSData base64EncodedDataWithOptions:]


    iOS7/OS X 10.9 之前:

    Matt Gallagher 就这个话题写了an article。在底部,他提供了一个指向他的 iPhone 可嵌入代码的链接。

    在 mac 上你可以使用 OpenSSL 库,在 iPhone 上他编写了自己的 impl。

    【讨论】:

    • Matts 代码中似乎有一个小问题:在 void *NewBase64Decode 第 128 行中,j += accumulateIndex - 1; 必须用 if (accumulatedIndex > 0) {...} 包围。否则,如果编码流的末尾包含无效(例如\r\n)字符,则解码文本的最后一个字符可能会丢失。这在我的代码中导致了奇怪的问题,对 IMAP 响应进行基于行的解码......
    • @Joker 这发生在我身上。谢谢你的简单修复,你这个天才!
    • 原来从 iOS4 开始就有一个函数可以做到这一点,但直到 iOS 7 才公开发布。如果 imageData 是 NSData 的一个实例,那么只需... [imageData base64Encoding]; developer.apple.com/library/ios/documentation/cocoa/reference/…
    【解决方案3】:

    作为更新,iOS7 SDK 在NSData (NSDataBase64Encoding) 上有一个带有方法的类别

    -[NSData base64EncodedStringWithOptions:]
    -[NSData initWithBase64EncodedString:options:]
    -[NSData initWithBase64EncodedData:options:]
    -[NSData base64EncodedDataWithOptions:]
    

    应该避免滚动你自己的类别方法

    【讨论】:

    • 哇,很高兴听到!每次谈到 base64,我都想知道为什么它没有出现在这么多语言的标准库中......
    • 这些都可以返回到 iOS 4,iOS 7 SDK 刚刚公开了它们
    • 抱歉,iOS 4 也有功能等效的方法(initWithBase64Encoding 和 base64Encoding)
    • 你能在你的回答中举例说明如何使用它吗?
    • 一个例子是将二进制数据发送到 REST Web 服务接口。例如。假设我在 Person 对象上有一个 photo photo 属性,要通过 JSON 发送它,我可以通过 -[[Person photo] base64EncodedStringWithOptions:0]-[Person photo] NSData 属性转换为 NSString ,因此可以通过 NSJSONSerialization 进行序列化
    【解决方案4】:
    //from: http://cocoadev.com/BaseSixtyFour
    + (NSString*)base64forData:(NSData*)theData {
    
        const uint8_t* input = (const uint8_t*)[theData bytes];
        NSInteger length = [theData length];
    
      static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
      NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
      uint8_t* output = (uint8_t*)data.mutableBytes;
    
        NSInteger i;
      for (i=0; i < length; i += 3) {
        NSInteger value = 0;
            NSInteger j;
        for (j = i; j < (i + 3); j++) {
          value <<= 8;
    
          if (j < length) {
            value |= (0xFF & input[j]);
          }
        }
    
        NSInteger theIndex = (i / 3) * 4;
        output[theIndex + 0] =                    table[(value >> 18) & 0x3F];
        output[theIndex + 1] =                    table[(value >> 12) & 0x3F];
        output[theIndex + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
        output[theIndex + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
      }
    
      return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease];
    }
    

    【讨论】:

    • 如果你有任何 swift 版本??
    【解决方案5】:

    我修改了上面的代码以满足我的需要,构建了一个 HTTP POST。我能够跳过 NSString 步骤,并在 BASE64 代码中包含换行符,至少有一个 Web 服务器发现它更可口:

    #define LINE_SIZE   76
    
    //originally from: http://www.cocoadev.com/index.pl?BaseSixtyFour
    // via joshrl on stockoverflow
    
    - (void) appendBase64Of: (NSData *)inData to:(NSMutableData *)outData {
        const uint8_t* input = (const uint8_t*)[inData bytes];
        NSInteger length = [inData length];
    
        static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
        uint8_t buf[LINE_SIZE + 4 + 2];
        size_t n = 0;
    
        NSInteger i;
        for (i=0; i < length; i += 3) {
            NSInteger value = 0;
            NSInteger j;
            for (j = i; j < (i + 3); j++) {
                value <<= 8;
    
                if (j < length) {
                    value |= (0xFF & input[j]);
                }
            }
    
            buf[n + 0] =                    table[(value >> 18) & 0x3F];
            buf[n + 1] =                    table[(value >> 12) & 0x3F];
            buf[n + 2] = (i + 1) < length ? table[(value >> 6)  & 0x3F] : '=';
            buf[n + 3] = (i + 2) < length ? table[(value >> 0)  & 0x3F] : '=';
            n += 4;
            if (n + 2 >= LINE_SIZE) {
                buf[n++] = '\r';
                buf[n++] = '\n';
                [outData appendBytes:buf length:n];
                n = 0;
            }
        }
        if (n > 0) {
            buf[n++] = '\r';
            buf[n++] = '\n';
            [outData appendBytes:buf length:n];
        }
        return;
    }
    

    【讨论】:

      【解决方案6】:

      超级简单的谷歌库代码here.

      只需使用+rfc4648Base64StringEncoding 获取实例,然后使用encode/decode 函数。

      这是一件美好的事情。 (不过,不要忘记从根目录中获取头文件和 GTMDefines.h 头文件。)

      【讨论】:

        【解决方案7】:

        这并不容易。因为在 c 或 obj-c 中没有对此的内置支持。这就是我正在做的事情(基本上是让 CL 为我做这件事):

        - (NSString *)_base64Encoding:(NSString *) str
        {
            NSTask *task = [[[NSTask alloc] init] autorelease];
            NSPipe *inPipe = [NSPipe pipe], *outPipe = [NSPipe pipe];
            NSFileHandle *inHandle = [inPipe fileHandleForWriting], *outHandle = [outPipe fileHandleForReading];
            NSData *outData = nil;
        
            [task setLaunchPath:@"/usr/bin/openssl"];
            [task setArguments:[NSArray arrayWithObjects:@"base64", @"-e", nil]];
            [task setStandardInput:inPipe];
            [task setStandardOutput:outPipe];
            [task setStandardError:outPipe];
        
            [task launch];
        
            [inHandle writeData:[str dataUsingEncoding: NSASCIIStringEncoding]];
            [inHandle closeFile];
        
            [task waitUntilExit];
        
            outData = [outHandle readDataToEndOfFile];
            if (outData)
            {
                NSString *base64 = [[[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding] autorelease];
                if (base64)
                    return base64;
            }
        
            return nil;
        }
        

        你可以这样使用它:

        NSString *b64str = [strToConvert _base64Encoding:strToConvert];
        

        这不是我的代码 - 我在这里找到了它:http://www.cocoadev.com/index.pl?BaseSixtyFour,它工作得很好。你总是可以把它变成一个 +() 方法。

        哦,为了这个方法让你的 NSData 变成一个 NSString:

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

        【讨论】:

        • 在 mac 上不需要生成进程 - 您可以直接使用 libcrypto。在 iPhone 上,是否存在 /usr/bin/openssl?
        猜你喜欢
        • 2017-06-04
        • 2012-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-17
        • 2011-09-01
        相关资源
        最近更新 更多