如何在iPhone上进行Base64编码

39

如何在iPhone上进行Base64编码?

我找到了一些看起来很有希望的例子,但是在手机上却从未成功过。


也许这个小代码片段在iPhone上也能工作: https://dev59.com/PGXWa4cB1Zd3GeqPRN9J#14522792 - denis2342
9个回答

66

你可以在这里看到一个例子。

这适用于iOS7及以上版本。

我把代码复制在这里,以防万一:

// Create NSData object
NSData *nsdata = [@"iOS Developer Tips encoded in Base64"
  dataUsingEncoding:NSUTF8StringEncoding];

// Get NSString from NSData object in Base64
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];

// Print the Base64 encoded string
NSLog(@"Encoded: %@", base64Encoded);

// Let's go the other way...

// NSData from the Base64 encoded str
NSData *nsdataFromBase64String = [[NSData alloc]
  initWithBase64EncodedString:base64Encoded options:0];

// Decoded NSString from the NSData
NSString *base64Decoded = [[NSString alloc] 
  initWithData:nsdataFromBase64String encoding:NSUTF8StringEncoding];
NSLog(@"Decoded: %@", base64Decoded);

哇,直到iOS 7之前,NSData中才没有Base64编码。 - Bryan Bryce

11

我也曾经苦于找不到我能理解的iPhone工作代码。

最终,我写了这个。

-(NSString *)Base64Encode:(NSData *)data;

-(NSString *)Base64Encode:(NSData *)data{

    //Point to start of the data and set buffer sizes
    int inLength = [data length];
    int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
    const char *inputBuffer = [data bytes];
    char *outputBuffer = malloc(outLength+1);
    outputBuffer[outLength] = 0;

    //64 digit code
    static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    //Start the count
    int cycle = 0;
    int inpos = 0;
    int outpos = 0;
    char temp;

    //Pad the last to bytes, the outbuffer must always be a multiple of 4.
    outputBuffer[outLength-1] = '=';
    outputBuffer[outLength-2] = '=';

    /* http://en.wikipedia.org/wiki/Base64

        Text content     M         a         n
        ASCII            77        97        110
        8 Bit pattern    01001101  01100001  01101110

        6 Bit pattern    010011    010110    000101    101110
        Index            19        22        5         46
        Base64-encoded   T         W         F         u
    */

    while (inpos < inLength){
        switch (cycle) {

            case 0:
                outputBuffer[outpos++] = Encode[(inputBuffer[inpos] & 0xFC) >> 2];
                cycle = 1;
                break;

            case 1:
                temp = (inputBuffer[inpos++] & 0x03) << 4;
                outputBuffer[outpos] = Encode[temp];
                cycle = 2;
                break;

            case 2:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0) >> 4];
                temp = (inputBuffer[inpos++] & 0x0F) << 2;
                outputBuffer[outpos] = Encode[temp];
                cycle = 3;
                break;

            case 3:
                outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0) >> 6];
                cycle = 4;
                break;

            case 4:
                outputBuffer[outpos++] = Encode[inputBuffer[inpos++] & 0x3f];
                cycle = 0;
                break;

            default:
                cycle = 0;
                break;
        }
    }
    NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
    free(outputBuffer);
    return pictemp;
}

在使用ARC时,我遇到了很多问题。我的应用程序会随机崩溃。 - Peter
计算输出长度有什么问题吗? - Sulthan
嗨 @kdda,我知道这个问题已经有答案了一段时间。不知道你有没有解码的方法?谢谢! - gdubs
1
  1. 分配的缓冲区太小,导致内存损坏和崩溃。我已经进行了编辑修复。
  2. 您的长度计算过于复杂了。一个简单的(inLength+2)/3*4就足够了吧?
- CodesInChaos
这个答案被引用在 复制粘贴编程有害吗? 中。 - Peter Mortensen

11

使用此库进行Base64编码。

该库还支持ARC


现在它已经被弃用了。 - Gajendra K Chauhan

5

reference

NSString *plainString = @"foo";

编码

NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
NSLog(@"%@", base64String); // Zm9v

解码

NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
NSString *decodedString = [[NSString alloc] initWithData:decodedData encoding:NSUTF8StringEncoding];
NSLog(@"%@", decodedString); // foo 

5

试一下这个方法... 对我来说非常完美。创建一个类别 Base64.h 和 Base64.m,导入到你想要使用的任何类中,并使用单行代码调用它,以使Base64编码发生。

//
//  Base64.h
//  CryptTest
//  Created by SURAJ K THOMAS  on 02/05/2013.


#import <Foundation/Foundation.h>


@interface Base64 : NSObject {

}
+ (void) initialize;
+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length;
+ (NSString*) encode:(NSData*) rawBytes;
+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength;
+ (NSData*) decode:(NSString*) string;
@end





#import "Base64.h"


@implementation Base64
#define ArrayLength(x) (sizeof(x)/sizeof(*(x)))

static char encodingTable[] = 
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static char decodingTable[128];

+ (void) initialize {
if (self == [Base64 class]) {
    memset(decodingTable, 0, ArrayLength(decodingTable));
    for (NSInteger i = 0; i < ArrayLength(encodingTable); i++) {
        decodingTable[encodingTable[i]] = i;
    }
}
}


+ (NSString*) encode:(const uint8_t*) input length:(NSInteger) length {
NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
uint8_t* output = (uint8_t*)data.mutableBytes;

for (NSInteger i = 0; i < length; i += 3) {
    NSInteger value = 0;
    for (NSInteger j = i; j < (i + 3); j++) {
        value <<= 8;

        if (j < length) {
            value |= (0xFF & input[j]);
        }
    }

    NSInteger index = (i / 3) * 4;
    output[index + 0] =                    encodingTable[(value >> 18) & 0x3F];
    output[index + 1] =                    encodingTable[(value >> 12) & 0x3F];
    output[index + 2] = (i + 1) < length ? encodingTable[(value >> 6)  & 0x3F] : '=';
    output[index + 3] = (i + 2) < length ? encodingTable[(value >> 0)  & 0x3F] : '=';
}

return [[NSString alloc] initWithData:data
                              encoding:NSASCIIStringEncoding];
}


+ (NSString*) encode:(NSData*) rawBytes {
return [self encode:(const uint8_t*) rawBytes.bytes length:rawBytes.length];
}


+ (NSData*) decode:(const char*) string length:(NSInteger) inputLength {
if ((string == NULL) || (inputLength % 4 != 0)) {
    return nil;
}

while (inputLength > 0 && string[inputLength - 1] == '=') {
    inputLength--;
}

NSInteger outputLength = inputLength * 3 / 4;
NSMutableData* data = [NSMutableData dataWithLength:outputLength];
uint8_t* output = data.mutableBytes;

NSInteger inputPoint = 0;
NSInteger outputPoint = 0;
while (inputPoint < inputLength) {
    char i0 = string[inputPoint++];
    char i1 = string[inputPoint++];
    char i2 = inputPoint < inputLength ? string[inputPoint++] : 'A'; /* 'A' will   
decode to \0 */
    char i3 = inputPoint < inputLength ? string[inputPoint++] : 'A';

    output[outputPoint++] = (decodingTable[i0] << 2) | (decodingTable[i1] >> 4);
    if (outputPoint < outputLength) {
        output[outputPoint++] = ((decodingTable[i1] & 0xf) << 4) |   
(decodingTable[i2] >> 2);
    }
    if (outputPoint < outputLength) {
        output[outputPoint++] = ((decodingTable[i2] & 0x3) << 6) |   
decodingTable[i3];
    }
}

return data;
}


+ (NSData*) decode:(NSString*) string {
return [self decode:[string cStringUsingEncoding:NSASCIIStringEncoding]   
length:string.length];
}

@end

now import the above category to any class and convert the string like below


 NSString *authString = [[NSString stringWithFormat:@"OD0EK819OJFIFT6OJZZXT09Y1YUT1EJ2"]   
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];


NSData *inputData = [authString dataUsingEncoding:NSUTF8StringEncoding];

NSString *finalAuth =[Base64 encode:inputData];
NSLog(@"Encoded string =%@", finalAuth);

5

GitHub下载以下两个文件:

Base64.h
Base64.m

将这些文件添加到您的项目中。
在所需的文件中导入头文件。
#import "Base64.h"

并使用“as”进行编码
NSString *plainText = @"Your String";

NSString *base64String = [plainText base64EncodedStringWithWrapWidth:0];

此外,您还可以将其解码为:
NSString *plainText = [base64String base64DecodedString];

initWithBase64Encoding 已被弃用。这些类需要更新。 - dev4life

3
似乎从iOS 7开始,您不再需要使用任何库来对Base64进行编码。可以使用NSData上的以下方法进行Base64编码:
  • base64EncodedDataWithOptions: - base64EncodedStringWithOptions:

1

这个答案已经过时了,请使用https://dev59.com/zXNA5IYBdhLWcg3wpfiu#24468530,因为它适用于iOS 7及以上版本。

NSData类别中的一个方法

- (NSString*)encodeBase64 {    
    static char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
    unsigned int length = self.length;
    unsigned const char* rawData = self.bytes;
    
    //empty data = empty output
    if (length == 0) {
        return @"";
    }
        
    unsigned int outputLength = (((length + 2) / 3) * 4);
    
    //let's allocate buffer for the output
    char* rawOutput = malloc(outputLength + 1);
    
    //with each step we get 3 bytes from the input and write 4 bytes to the output
    for (unsigned int i = 0, outputIndex = 0; i < length; i += 3, outputIndex += 4) {
        BOOL triple = NO;
        BOOL quad = NO;
        
        //get 3 bytes (or only 1 or 2 when we have reached the end of input)
        unsigned int value = rawData[i];
        value <<= 8;
        
        if (i + 1 < length) {
            value |= rawData[i + 1];
            triple = YES;
        }
        
        value <<= 8;
        
        if (i + 2 < length) {
            value |= rawData[i + 2];
            quad = YES;
        }
        
        //3 * 8 bits written as 4 * 6 bits (indexing the 64 chars of the alphabet)
        //write = if end of input reached
        rawOutput[outputIndex + 3] = (quad) ? alphabet[value & 0x3F] : '=';
        value >>= 6;
        rawOutput[outputIndex + 2] = (triple) ? alphabet[value & 0x3F] : '=';
        value >>= 6;
        rawOutput[outputIndex + 1] = alphabet[value & 0x3F];
        value >>= 6;
        rawOutput[outputIndex] = alphabet[value & 0x3F];
    }
    
    rawOutput[outputLength] = 0;
    
    NSString* output = [NSString stringWithCString:rawOutput encoding:NSASCIIStringEncoding];
    
    free(rawOutput);
    
    return output;
}

1
我做了自己的实现,在循环内部删除了所有检查。因此,在大量数据上,它的工作速度更快。你可以将其作为自己解决方案的基础。
static char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

+ (NSString *)encodeString:(NSString *)data
{
    const char *input = [data cStringUsingEncoding:NSUTF8StringEncoding];
    unsigned long inputLength = [data length];
    unsigned long modulo = inputLength % 3;
    unsigned long outputLength = (inputLength / 3) * 4 + (modulo ? 4 : 0);
    unsigned long j = 0;

    // Do not forget about trailing zero
    unsigned char *output = malloc(outputLength + 1);
    output[outputLength] = 0;

    // Here are no checks inside the loop, so it works much faster than other implementations
    for (unsigned long i = 0; i < inputLength; i += 3) {
        output[j++] = alphabet[ (input[i] & 0xFC) >> 2 ];
        output[j++] = alphabet[ ((input[i] & 0x03) << 4) | ((input[i + 1] & 0xF0) >> 4) ];
        output[j++] = alphabet[ ((input[i + 1] & 0x0F)) << 2 | ((input[i + 2] & 0xC0) >> 6) ];
        output[j++] = alphabet[ (input[i + 2] & 0x3F) ];
    }
    // Padding in the end of encoded string directly depends of modulo
    if (modulo > 0) {
        output[outputLength - 1] = '=';
        if (modulo == 1)
            output[outputLength - 2] = '=';
    }
    NSString *s = [NSString stringWithUTF8String:(const char *)output];
    free(output);
    return s;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接