मैं iOS पर बेस 64 एनकोडिंग कैसे करूं?


230

मैं base64एन्कोडिंग और डिकोडिंग करना चाहूंगा , लेकिन मुझे iPhone से कोई समर्थन नहीं मिला SDK। मैं base64लाइब्रेरी के साथ या उसके बिना एन्कोडिंग और डिकोडिंग कैसे कर सकता हूं ?


1
इस पोस्ट के निचले भाग में एक अच्छा कोड नमूना है। बहुत आत्म-निहित ... बेससिक्सफॉर
ग्रेग बर्नहार्ट

@GregBernhardt लिंक मृत है।
कूर

जवाबों:


116

यह उद्देश्य सी श्रेणियों के लिए एक अच्छा उपयोग मामला है ।

Base64 एन्कोडिंग के लिए:

#import <Foundation/NSString.h>

@interface NSString (NSStringAdditions)

+ (NSString *) base64StringFromData:(NSData *)data length:(int)length;

@end

-------------------------------------------

#import "NSStringAdditions.h"

static char base64EncodingTable[64] = {
  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
  'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
};

@implementation NSString (NSStringAdditions)

+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
  unsigned long ixtext, lentext;
  long ctremaining;
  unsigned char input[3], output[4];
  short i, charsonline = 0, ctcopy;
  const unsigned char *raw;
  NSMutableString *result;

  lentext = [data length]; 
  if (lentext < 1)
    return @"";
  result = [NSMutableString stringWithCapacity: lentext];
  raw = [data bytes];
  ixtext = 0; 

  while (true) {
    ctremaining = lentext - ixtext;
    if (ctremaining <= 0) 
       break;        
    for (i = 0; i < 3; i++) { 
       unsigned long ix = ixtext + i;
       if (ix < lentext)
          input[i] = raw[ix];
       else
  input[i] = 0;
  }
  output[0] = (input[0] & 0xFC) >> 2;
  output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
  output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
  output[3] = input[2] & 0x3F;
  ctcopy = 4;
  switch (ctremaining) {
    case 1: 
      ctcopy = 2; 
      break;
    case 2: 
      ctcopy = 3; 
      break;
  }

  for (i = 0; i < ctcopy; i++)
     [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];

  for (i = ctcopy; i < 4; i++)
     [result appendString: @"="];

  ixtext += 3;
  charsonline += 4;

  if ((length > 0) && (charsonline >= length))
    charsonline = 0;
  }     
  return result;
}

@end

Base64 डिकोडिंग के लिए:

#import <Foundation/Foundation.h>

@class NSString;

@interface NSData (NSDataAdditions)

+ (NSData *) base64DataFromString:(NSString *)string;

@end

-------------------------------------------

#import "NSDataAdditions.h"

@implementation NSData (NSDataAdditions)

+ (NSData *)base64DataFromString: (NSString *)string
{
    unsigned long ixtext, lentext;
    unsigned char ch, inbuf[4], outbuf[3];
    short i, ixinbuf;
    Boolean flignore, flendtext = false;
    const unsigned char *tempcstring;
    NSMutableData *theData;

    if (string == nil)
    {
        return [NSData data];
    }

    ixtext = 0;

    tempcstring = (const unsigned char *)[string UTF8String];

    lentext = [string length];

    theData = [NSMutableData dataWithCapacity: lentext];

    ixinbuf = 0;

    while (true)
    {
        if (ixtext >= lentext)
        {
            break;
        }

        ch = tempcstring [ixtext++];

        flignore = false;

        if ((ch >= 'A') && (ch <= 'Z'))
        {
            ch = ch - 'A';
        }
        else if ((ch >= 'a') && (ch <= 'z'))
        {
            ch = ch - 'a' + 26;
        }
        else if ((ch >= '0') && (ch <= '9'))
        {
            ch = ch - '0' + 52;
        }
        else if (ch == '+')
        {
            ch = 62;
        }
        else if (ch == '=')
        {
            flendtext = true;
        }
        else if (ch == '/')
        {
            ch = 63;
        }
        else
        {
            flignore = true; 
        }

        if (!flignore)
        {
            short ctcharsinbuf = 3;
            Boolean flbreak = false;

            if (flendtext)
            {
                if (ixinbuf == 0)
                {
                    break;
                }

                if ((ixinbuf == 1) || (ixinbuf == 2))
                {
                    ctcharsinbuf = 1;
                }
                else
                {
                    ctcharsinbuf = 2;
                }

                ixinbuf = 3;

                flbreak = true;
            }

            inbuf [ixinbuf++] = ch;

            if (ixinbuf == 4)
            {
                ixinbuf = 0;

                outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
                outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
                outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);

                for (i = 0; i < ctcharsinbuf; i++)
                {
                    [theData appendBytes: &outbuf[i] length: 1];
                }
            }

            if (flbreak)
            {
                break;
            }
        }
    }

    return theData;
}

    @end

5
यदि ओबज-सी कुछ भी सी जैसा है, तो आपको ऐसा करने में सक्षम होना चाहिए: स्थिर चार बेस 64 इकोकोडिंगटेबल [64] = "एबीसीडीई [आदि] 789 + /";
आर्टेलियस

3
मैंने पाया कि मुझे केवल 4 अक्षर ही क्यों मिल रहे थे ... थोड़ी देर () लूप की वापसी से पहले एक} होना चाहिए। मैं इसे संपादित करूंगा लेकिन मैं ऐसा नहीं दिख सकता।
लैरी हिप्प

3
यह एक विश्लेषक बग नहीं है। सूचना कोड भी inbuf [3] तक पहुंचने का प्रयास करता है, जो उस सरणी की सीमा से परे है। यह कोड बदबू आ रही है।
माइक वेलर

1
ऋणात्मक मूल्य क्या दर्शाता है?
मेगामैनएक्स

3
IOS7 के रूप में Apple ने अपने मूल आधार 64 एन्कोडिंग विधि को उजागर किया है। बैकवर्ड संगतता बनाए रखते हुए इसका उपयोग करने के लिए नीचे रोब का जवाब देखें।
कोड कमांडर

100

PHP के मूल पुस्तकालय से मूल उद्देश्य-सी कोड में पोर्ट किए गए (और संशोधित / सुधार किए गए) एक वास्तव में, तेजी से कार्यान्वयन , QSUtilities लाइब्रेरी से QSStrings कक्षा में उपलब्ध है । मैंने एक त्वरित बेंचमार्क किया: एक 5.3MB छवि (JPEG) फ़ाइल को एन्कोड करने के लिए <50ms और लगभग 140ms को डिकोड करने के लिए लिया।

GitHub पर पूरी लाइब्रेरी (Base64 मेथड सहित) के लिए कोड उपलब्ध हैं ।

या वैकल्पिक रूप से, यदि आप कोड को सिर्फ बेस 64 विधियों के लिए चाहते हैं, तो मैंने इसे यहाँ पोस्ट किया है:

सबसे पहले, आपको मैपिंग टेबल की आवश्यकता है:

static const char _base64EncodingTable[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static const short _base64DecodingTable[256] = {
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -1, -2, -1, -1, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -1, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, -2, -2, 63,
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -2, -2, -2, -2, -2, -2,
    -2,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -2, -2, -2, -2, -2,
    -2, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2,
    -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
};

एनकोड करने के लिए:

+ (NSString *)encodeBase64WithString:(NSString *)strData {
    return [QSStrings encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}

+ (NSString *)encodeBase64WithData:(NSData *)objData {
    const unsigned char * objRawData = [objData bytes];
    char * objPointer;
    char * strResult;

    // Get the Raw Data length and ensure we actually have data
    int intLength = [objData length];
    if (intLength == 0) return nil;

    // Setup the String-based Result placeholder and pointer within that placeholder
    strResult = (char *)calloc((((intLength + 2) / 3) * 4) + 1, sizeof(char));
    objPointer = strResult;

    // Iterate through everything
    while (intLength > 2) { // keep going until we have less than 24 bits
        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
        *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
        *objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];
        *objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];

        // we just handled 3 octets (24 bits) of data
        objRawData += 3;
        intLength -= 3; 
    }

    // now deal with the tail end of things
    if (intLength != 0) {
        *objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
        if (intLength > 1) {
            *objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
            *objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];
            *objPointer++ = '=';
        } else {
            *objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];
            *objPointer++ = '=';
            *objPointer++ = '=';
        }
    }

    // Terminate the string-based result
    *objPointer = '\0';

    // Create result NSString object
    NSString *base64String = [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];

    // Free memory
    free(strResult);

    return base64String;
}

डिकोड करने के लिए:

+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
    const char *objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];
    size_t intLength = strlen(objPointer);
    int intCurrent;
    int i = 0, j = 0, k;

    unsigned char *objResult = calloc(intLength, sizeof(unsigned char));

    // Run through the whole string, converting as we go
    while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {
        if (intCurrent == '=') {
            if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {
                // the padding character is invalid at this point -- so this entire string is invalid
                free(objResult);
                return nil;
            }
            continue;
        }

        intCurrent = _base64DecodingTable[intCurrent];
        if (intCurrent == -1) {
            // we're at a whitespace -- simply skip over
            continue;
        } else if (intCurrent == -2) {
            // we're at an invalid character
            free(objResult);
            return nil;
        }

        switch (i % 4) {
            case 0:
                objResult[j] = intCurrent << 2;
                break;

            case 1:
                objResult[j++] |= intCurrent >> 4;
                objResult[j] = (intCurrent & 0x0f) << 4;
                break;

            case 2:
                objResult[j++] |= intCurrent >>2;
                objResult[j] = (intCurrent & 0x03) << 6;
                break;

            case 3:
                objResult[j++] |= intCurrent;
                break;
        }
        i++;
    }

    // mop things up if we ended on a boundary
    k = j;
    if (intCurrent == '=') {
        switch (i % 4) {
            case 1:
                // Invalid state
                free(objResult);
                return nil;

            case 2:
                k++;
                // flow through
            case 3:
                objResult[k] = 0;
        }
    }

    // Cleanup and setup the return NSData
    NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];
    free(objResult);
    return objData;
}

2
अंत में एक सही और कुशल कार्यान्वयन। धन्यवाद। इधर-उधर के कुछ दूसरे कोड मुझे डराते हैं।
माइक वेलर

4
strResultएनकोडर के रूप में आवंटित स्मृति लीक होने लगती है; इसे बस free()अंत में (लौटने से पहले लेकिन बाद में NSString stringWithCString) की आवश्यकता है
जोसेफ

2
आपकी encodeBase64WithData:पद्धति में, अंत में जोड़ने वाले calloc()शून्य टर्मिनेटर ( '\0') के लिए कॉल में पहला पैरामीटर 1 से बढ़ाना आवश्यक नहीं है ?
23

1
तथ्य यह है कि सेब यह प्रदान नहीं करता है कि भगवान बिल्ली के बच्चे की हत्या करना चाहते हैं ... उनमें से एक बहुत ...
dsingleton 50-50

2
मैं इसे थोड़ी देर के लिए उपयोग कर रहा हूं और यह तब तक बहुत अच्छा लग रहा था जब तक कि मुझे कुछ स्मृति संबंधी भ्रष्टाचार संबंधी त्रुटियां होने लगीं और गार्ड मॉलॉक का उपयोग करते हुए मैंने इसे इस पंक्ति तक सीमित कर दिया: * objPointer = '\ 0'; यदि आप अपने स्वयं के ऐप्स में इसका उपयोग करते हैं तो सावधान रहें।
मटिया

72

ऐतिहासिक रूप से हमने आपको बाइनरी डेटा से बेस 64 स्ट्रिंग (और बैक) में परिवर्तित करने के लिए कई तृतीय-पक्ष बेस 64 पुस्तकालयों (जैसा कि अन्य उत्तरों में चर्चा की गई है) में से एक में निर्देशित किया होगा, लेकिन iOS 7 में अब मूल आधार 64 एन्कोडिंग है (और पहले के निजी iOS 4 तरीकों को उजागर करता है, यदि आपको iOS के पुराने संस्करणों का समर्थन करने की आवश्यकता होती है)।

इस प्रकार आधार 64 प्रतिनिधित्व में परिवर्तित करने के NSDataलिए NSStringआप उपयोग कर सकते हैं base64EncodedStringWithOptions। यदि आपको 7.0 से पहले iOS संस्करणों का समर्थन करना है, तो आप कर सकते हैं:

NSString *string;

if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
    string = [data base64EncodedStringWithOptions:kNilOptions];  // iOS 7+
} else {
    string = [data base64Encoding];                              // pre iOS7
}

और बेस 64 को NSStringवापस कन्वर्ट करने के लिए NSDataआप उपयोग कर सकते हैं initWithBase64EncodedString। इसी तरह, अगर आपको 7.0 से पहले iOS संस्करणों का समर्थन करने की आवश्यकता है, तो आप कर सकते हैं:

NSData *data;

if ([NSData instancesRespondToSelector:@selector(initWithBase64EncodedString:options:)]) {
    data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions];  // iOS 7+
} else {
    data = [[NSData alloc] initWithBase64Encoding:string];                           // pre iOS7
}

जाहिर है, अगर आपको 7.0 से पहले iOS संस्करणों के साथ पिछड़े संगतता की आवश्यकता नहीं है, तो यह और भी आसान है , क्रमशः, base64EncodedStringWithOptionsया initWithBase64EncodedStringक्रमशः उपयोग करें , और पहले के iOS संस्करणों के लिए रन-टाइम चेक से परेशान न करें। वास्तव में, यदि आप उपरोक्त कोड का उपयोग करते हैं जब आपका न्यूनतम लक्ष्य iOS 7 या अधिक है, तो आपको वास्तव में पदावनत तरीकों के बारे में एक संकलक चेतावनी मिलेगी। तो, iOS 7 और अधिक से अधिक में, आप बस 64 स्ट्रिंग को आधार में बदलेंगे:

NSString *string = [data base64EncodedStringWithOptions:kNilOptions];

और फिर से साथ:

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions]; 

उस रोब के बारे में धन्यवाद। क्या आप कृपया संक्षेप में बता सकते हैं कि आपने क्या लिखा है, " ... और पहले के निजी iOS 4 तरीकों को उजागर करता है "?
फि

8
यह शर्म की बात है कि यह जवाब उन सभी कस्टम कार्यान्वयन के नीचे दफन है। यह एसओ की कमजोरी है, जहां मूल सवाल पूछे जाने के बाद लंबे समय के बारे में अधिक उपयुक्त समाधान आ सकता है, उस समाधान को अब जो पहले स्वीकार किया गया था उससे मुकाबला करना होगा।
जाकव

यही कारण है कि यह हमेशा उपयोगी होता है अधिक हाल ही में सही उत्तरों को उभारने के लिए :)
स्टीव विल्फोर्ड

इस तरह से नरक के उत्तर शीर्ष पर क्यों नहीं हैं :(, मैंने T__T के ऊपर सभी उत्तरों को संसाधित करने में बहुत समय बिताया है
Alsh संकलक

33

iOS में बेस 64 एन्कोडिंग और डिकोडिंग के लिए समर्थन शामिल है। यदि आप resolv.hदेखते हैं तो आपको दो कार्यों को देखना चाहिए b64_ntopऔर b64_pton। स्क्वायर सॉकेटरॉकेट लाइब्रेरी उद्देश्य-सी से इन कार्यों का उपयोग करने का एक उचित उदाहरण प्रदान करता है।

ये फ़ंक्शन बहुत अच्छी तरह से परीक्षण किए गए और विश्वसनीय हैं - कई कार्यान्वयन के विपरीत जो आपको यादृच्छिक इंटरनेट पोस्टिंग में मिल सकते हैं। के खिलाफ लिंक करने के लिए मत भूलना libresolv.dylib


3
बहुत बढ़िया; यादृच्छिक इंटरनेट साइट की तुलना में बहुत बेहतर! यदि कोई भी इन स्केच-डॉक्यूमेंटेड फ़ंक्शंस का उपयोग करने के बारे में चिंतित है, तो आप एप्पल की साइट पर इन के लिए स्रोत देख सकते हैं ।
जेसी रुसाक

1
यह आदमी इस पर कुछ और पृष्ठभूमि देता है: blog.montgomerie.net/ios-hidden-base64-routines
माइक

21

चूंकि यह बेस 64 एन्कोडिंग और आईफोन पर नंबर एक गूगल हिट लगता है, इसलिए मुझे ऊपर कोड स्निपेट के साथ अपना अनुभव साझा करना पसंद आया।

यह काम करता है, लेकिन यह बेहद धीमा है। एक यादृच्छिक छवि (0.4 mb) पर एक बेंचमार्क ने देशी iPhone पर 37 सेकंड का समय लिया। मुख्य कारण शायद सभी ओओपी जादू है - एकल चार एनएसएसट्रेस आदि, जो एन्कोडिंग किए जाने के बाद केवल ऑटोरिल्ड हैं।

यहाँ पोस्ट किया गया एक अन्य सुझाव (ab) ओपनस् लाइब्ररी का उपयोग करता है, जो कि ओवरकिल जैसा भी महसूस करता है।

नीचे दिए गए कोड में 70 एमएस होता है - यह 500 गुना स्पीडअप है। यह केवल बेस 64 एनकोडिंग करता है (जैसे ही मैं इसका सामना करता हूं डिकोडिंग का पालन होगा)

+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {
int lentext = [data length]; 
if (lentext < 1) return @"";

char *outbuf = malloc(lentext*4/3+4); // add 4 to be sure

if ( !outbuf ) return nil;

const unsigned char *raw = [data bytes];

int inp = 0;
int outp = 0;
int do_now = lentext - (lentext%3);

for ( outp = 0, inp = 0; inp < do_now; inp += 3 )
{
    outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
    outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
    outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
    outbuf[outp++] = base64EncodingTable[raw[inp+2] & 0x3F];
}

if ( do_now < lentext )
{
    char tmpbuf[2] = {0,0};
    int left = lentext%3;
    for ( int i=0; i < left; i++ )
    {
        tmpbuf[i] = raw[do_now+i];
    }
    raw = tmpbuf;
    outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
    outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
    if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
}

NSString *ret = [[[NSString alloc] initWithBytes:outbuf length:outp encoding:NSASCIIStringEncoding] autorelease];
free(outbuf);

return ret;
}

मैंने लाइन-कटिंग को छोड़ दिया क्योंकि मुझे इसकी आवश्यकता नहीं थी, लेकिन इसे जोड़ने के लिए तुच्छ है।

जो लोग अनुकूलन में रुचि रखते हैं उनके लिए: लक्ष्य यह है कि मुख्य लूप में क्या होता है। इसलिए पिछले 3 बाइट्स से निपटने के लिए सभी लॉजिक को लूप के बाहर माना जाता है।

इसके अलावा, बफ़र्स से / के लिए अतिरिक्त प्रतिलिपि के बिना, इन-प्लेस डेटा पर काम करने की कोशिश करें। और नंगे न्यूनतम के लिए किसी भी अंकगणित को कम करें।

निरीक्षण करें कि तालिका में एक प्रविष्टि को देखने के लिए जो बिट्स एक साथ रखे गए हैं, वे ओवरलैप नहीं होंगे जब उन्हें स्थानांतरण के बिना एक साथ रखा जाना था। इसलिए एक बड़ा सुधार 4 अलग-अलग 256 बाइट लुकअप टेबल का उपयोग करने और पारियों को खत्म करने के लिए हो सकता है, जैसे:

outbuf[outp++] = base64EncodingTable1[(raw[inp] & 0xFC)];
outbuf[outp++] = base64EncodingTable2[(raw[inp] & 0x03) | (raw[inp+1] & 0xF0)];
outbuf[outp++] = base64EncodingTable3[(raw[inp+1] & 0x0F) | (raw[inp+2] & 0xC0)];
outbuf[outp++] = base64EncodingTable4[raw[inp+2] & 0x3F];

बेशक आप इसे पूरी तरह से आगे ले जा सकते हैं, लेकिन यह यहाँ के दायरे से परे है।


हम्म। मुझे यह काम नहीं मिला। मैं अपने अपेक्षित मूल्य से अलग बेस 64 एनकोडिंग का निरीक्षण करता हूं। क्या आपने RFC 4648 के उदाहरणों के साथ इसका परीक्षण किया है? tools.ietf.org/html/rfc4648
एलेक्स रेनॉल्ड्स

3
यह देखने के लिए कि क्या बेस 64EncodingTable1, base64EncodingTable2, base64EncodingTable3 और base64EncodingTable4 संदर्भित हैं?
जेमी चैपमैन

बहुत उपयोगी है, लेकिन यह इनपुट बफर के अंत से परे पढ़ सकता है। जब (बाएं == 2), कच्चा [inp + 2] tmpbuf के अंत से परे एक बाइट होगा। मुझे लगता है कि रेखा होनी चाहिए: अगर (बाएं == 2) प्रकोप [outp ++] = base64EncodingTable [(कच्चा ([inp + 1] & 0x0F) << 2)];
जॉन लम्बरजर

निम्नलिखित लाइन को बदलें <code> char tmpbuf [2] = {0,0}; </ code> से <code> अहस्ताक्षरित char tmpbuf [3] = {0,0,0}; </ code>
Satya

9

एमवीडी के उत्कृष्ट सुधार में, दो समस्याएं हैं। इसमें कोड बदलें:

raw = tmpbuf;
inp = 0;
outbuf[outp++] = base64EncodingTable[(raw[inp] & 0xFC) >> 2];
outbuf[outp++] = base64EncodingTable[((raw[inp] & 0x03) << 4) | ((raw[inp+1] & 0xF0) >> 4)];
if ( left == 2 ) outbuf[outp++] = base64EncodingTable[((raw[inp+1] & 0x0F) << 2) | ((raw[inp+2] & 0xC0) >> 6)];
else outbuf[outp++] = '=';
outbuf[outp++] = '=';

9

बेहतर समाधान:

NSData में एक अंतर्निहित फ़ंक्शन है

[data base64Encoding]; //iOS < 7.0
[data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //iOS >= 7.0

हम उस iOS वर्जन के आधार पर कर सकते हैं जिस पर "[[UIDevice currentDevice ]VVVVVIVVVVVIV]" का उपयोग करके ऐप चल रहा है।
नागराज

2
1. यह आपको यह नहीं बताएगा कि आपने एसडीके के खिलाफ क्या लिंक किया है, यह एक रनटाइम चेक है। 2. यह सीधे एप्पल के मार्गदर्शन के लिए काउंटर है। आपको एक सुविधा की उपलब्धता के लिए जाँच करनी चाहिए, न कि सिस्टम संस्करण की।
quellish

6

ख़ुशी लोगों को पसंद आई। अंत-खेल थोड़ा त्रुटिपूर्ण था जिसे मुझे स्वीकार करना चाहिए। सही तरीके से inp = 0 सेट करने के अलावा, आपको या तो tmpbuf का आकार 3 तक बढ़ाना चाहिए, जैसे

unsigned char tmpbuf[3] = {0,0,0};

या कच्चे [inp + 2] के आभूषण को छोड़ दें; अगर हमारे पास एक कच्चा [inp + 2]! = इस चंक के लिए हम अभी भी पाठ्यक्रम के पाश में होंगे ...

किसी भी तरह से काम करता है, आप अंतिम तालिका लुकअप ब्लॉक को स्पष्टता के लिए लूप में एक के समान रखने पर विचार कर सकते हैं। अंतिम संस्करण में मैंने जो प्रयोग किया वह मैंने किया

while ( outp%4 ) outbuf[outp++] = '=';

== जोड़ने के लिए

क्षमा करें, मैंने RFC और सामान की जाँच नहीं की, एक बेहतर काम करना चाहिए था!


3
आपके पास पहले से ही एक खाता है, क्योंकि आपका पिछला उत्तर वास्तव में एक अलग खाता है। इसके अलावा, यह या तो एक संपादित करने के लिए या एक टिप्पणी होना चाहिए।
एलेस्टेयर पिट्स

@alastair, आपको कुकीज़ की सफाई के बाद, हर बार जब आप पंजीकरण के बिना उत्तर पोस्ट करते हैं, तो आपको "खाता" लगता है। मैं अपने पहले "खाते" (यहां तक ​​कि एक ही ईमेल और आईपी पते के साथ) से कनेक्ट करने में सक्षम नहीं था, इसलिए मैंने इसे वहां एक नए उत्तर के रूप में रखा, इसके लिए खेद है। - बस पंजीकृत!
mvds

3
कोई भी मौका आप इस उत्तर को अपने पिछले एक में संपादित कर सकते हैं इसलिए एक निश्चित सही संस्करण है? धन्यवाद!
जोसफ

6

IOS8 के तहत और बाद - (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)optionsमें NSData का उपयोग


3
#import "NSDataAdditions.h"
@implementation NSData (NSDataAdditions)

+ (NSData *) base64DataFromString: (NSString *)string {
  unsigned long ixtext, lentext;
  unsigned char ch, input[4], output[3];
  short i, ixinput;
  Boolean flignore, flendtext = false;
  const char *temporary;
  NSMutableData *result;

  if (!string)
    return [NSData data];

  ixtext = 0;
  temporary = [string UTF8String];
  lentext = [string length];
  result = [NSMutableData dataWithCapacity: lentext];
  ixinput = 0;

  while (true) {
    if (ixtext >= lentext)
      break;
    ch = temporary[ixtext++];
    flignore = false;

    if ((ch >= 'A') && (ch <= 'Z'))
      ch = ch - 'A';
    else if ((ch >= 'a') && (ch <= 'z'))
      ch = ch - 'a' + 26;
    else if ((ch >= '0') && (ch <= '9'))
      ch = ch - '0' + 52;
    else if (ch == '+')
      ch = 62;
    else if (ch == '=')
      flendtext = true;
    else if (ch == '/')
      ch = 63;
    else
      flignore = true;

    if (!flignore) {
      short ctcharsinput = 3;
      Boolean flbreak = false;

      if (flendtext) {
         if (ixinput == 0)
           break;              
         if ((ixinput == 1) || (ixinput == 2))
           ctcharsinput = 1;
         else
           ctcharsinput = 2;
         ixinput = 3;
         flbreak = true;
      }

      input[ixinput++] = ch;

      if (ixinput == 4){
        ixinput = 0;
        output[0] = (input[0] << 2) | ((input[1] & 0x30) >> 4);
        output[1] = ((input[1] & 0x0F) << 4) | ((input[2] & 0x3C) >> 2);
        output[2] = ((input[2] & 0x03) << 6) | (input[3] & 0x3F);
        for (i = 0; i < ctcharsinput; i++)
        [result appendBytes: &output[i] length: 1];
      }
    if (flbreak)
      break;
    }
  }
  return result;
}
@end


2

यहाँ NSData पर एक श्रेणी के रूप में एक कॉम्पैक्ट ऑब्जेक्टिव-सी संस्करण है। यह कुछ सोच लेता है ...

@implementation NSData (DataUtils)

static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

- (NSString *)newStringInBase64FromData
{
 NSMutableString *dest = [[NSMutableString alloc] initWithString:@""];
 unsigned char * working = (unsigned char *)[self bytes];
 int srcLen = [self length];

 // tackle the source in 3's as conveniently 4 Base64 nibbles fit into 3 bytes
 for (int i=0; i<srcLen; i += 3)
 {
  // for each output nibble
  for (int nib=0; nib<4; nib++)
  {
   // nibble:nib from char:byt
   int byt = (nib == 0)?0:nib-1;
   int ix = (nib+1)*2;

   if (i+byt >= srcLen) break;

   // extract the top bits of the nibble, if valid
   unsigned char curr = ((working[i+byt] << (8-ix)) & 0x3F);

   // extract the bottom bits of the nibble, if valid
   if (i+nib < srcLen) curr |= ((working[i+nib] >> ix) & 0x3F);

   [dest appendFormat:@"%c", base64[curr]];
  }
 }

 return dest;
}

@end

लौटने से पहले 'बाइट' के दायरे को व्यापक (और 2-बाइट) "=" अक्षर के साथ 'डिस्ट' के साथ जोड़कर यदि आवश्यक हो तो पैडिंग को जोड़ा जा सकता है।

एक श्रेणी तो NSString में जोड़ा जा सकता है, इस प्रकार:

@implementation NSString (StringUtils)

- (NSString *)newStringInBase64FromString
{
 NSData *theData = [NSData dataWithBytes:[self UTF8String] length:[self length]]; 

 return [theData newStringInBase64FromData];
}

@end

2

iOS 4 के बाद से iOS में अंतर्निहित Base64 एन्कोडिंग और डिकोडिंग तरीके (लाइब्रेसोल्व का उपयोग किए बिना) है। हालाँकि, इसे केवल iOS 7 SDK में घोषित किया गया था। Apple प्रलेखन में कहा गया है कि iOS 4 और इसके बाद के संस्करण को लक्षित करते समय आप इसका उपयोग कर सकते हैं।

NSData *myData = ... some data
NSString *base64String = [myData base64Encoding];
NSData *decodedData = [[NSData alloc] initWithBase64Encoding:base64String];

2

यहां एक NSData ऑब्जेक्ट को बेस 64 में बदलने के लिए एक उदाहरण है। यह यह भी दर्शाता है कि दूसरे तरीके से कैसे जाना है (एक बेस 64 एनकोडेड NSData ऑब्जेक्ट को डीकोड करें):

NSData *dataTake2 = 
  [@"iOS Developer Tips" dataUsingEncoding:NSUTF8StringEncoding];

// Convert to Base64 data
NSData *base64Data = [dataTake2 base64EncodedDataWithOptions:0];

// Do something with the data...

// Now convert back from Base64
NSData *nsdataDecoded = [base64Data initWithBase64EncodedData:base64Data options:0];

1

iOS 7 में

        NSData *data=[[NSData alloc]init];
        [data base64Encoding];

नागराज ने इसका उल्लेख पहले ही कर दिया था। उनके पोस्ट और टिप्पणियों को देखें जो इसे उस स्थिति के साथ जोड़ते हैं जो आईओएस 4 के बाद से है।
jww

1

मैंने इसे निम्न वर्ग का उपयोग करके किया है।

@implementation Base64Converter
static char base64EncodingTable[64] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',  'M', 'N', 'O', 'P',
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',    '8', '9', '+', '/'
};
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length {

unsigned long ixtext, lentext;

long ctremaining;

unsigned char input[3], output[4];

short i, charsonline = 0, ctcopy;

const unsigned char *raw;

NSMutableString *result;

lentext = [data length];

if (lentext < 1)
    return @"";

result = [NSMutableString stringWithCapacity: lentext];

raw = [data bytes];

ixtext = 0;

while (true) {

    ctremaining = lentext - ixtext;

    if (ctremaining <= 0)
        break;

    for (i = 0; i < 3; i++) {
        unsigned long ix = ixtext + i;
        if (ix < lentext)
            input[i] = raw[ix];
        else
            input[i] = 0;
    }

    output[0] = (input[0] & 0xFC) >> 2;

    output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);

    output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);

    output[3] = input[2] & 0x3F;

    ctcopy = 4;

    switch (ctremaining) {
        case 1:
            ctcopy = 2;
            break;

        case 2:
            ctcopy = 3;
            break;
    }

    for (i = 0; i < ctcopy; i++)
        [result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];

    for (i = ctcopy; i < 4; i++)
        [result appendString: @"="];

    ixtext += 3;

    charsonline += 4;

    if ((length > 0) && (charsonline >= length))
        charsonline = 0;
}
return result;
}
@end

कॉल करते समय

 [Base64Converter base64StringFromData:dataval length:lengthval];

बस...


1

मुझे लगता है कि यह मददगार होगा

 + (NSString *)toBase64String:(NSString *)string {
    NSData *data = [string dataUsingEncoding: NSUnicodeStringEncoding];

    NSString *ret = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

    return ret;
    }

    + (NSString *)fromBase64String:(NSString *)string {
NSData *aData = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *aDataDecoded = [[NSData alloc]initWithBase64EncodedString:string options:0];
NSString *decryptedStr = [[NSString alloc]initWithData:aDataDecoded encoding:NSUTF8StringEncoding];

return [decryptedStr autorelease];

}


NSStringUtil? कृपया पूर्ण उत्तर दें?
मोहसिन खुब्बीब अहमद

1
यह दो तरीके हैं जो आपको किसी भी कक्षा में लिखने की आवश्यकता है और आप इसे कॉल कर सकते हैं और स्ट्रिंग इंस्टेंस को पैरामीटर के रूप में पास कर सकते हैं।
मृग


0

आपकी आवश्यकता के अनुसार मैंने स्विफ्ट 4 का उपयोग करके एक नमूना डेमो बनाया है जिसमें आप अपनी आवश्यकता के अनुसार स्ट्रिंग और छवि को एन्कोड / डिकोड कर सकते हैं।

  • मैंने प्रासंगिक संचालन के नमूना तरीकों को भी जोड़ा है।

    //
    //  Base64VC.swift
    //  SOF_SortArrayOfCustomObject
    //
    //  Created by Test User on 09/01/18.
    //  Copyright © 2018 Test User. All rights reserved.
    //
    
    import UIKit
    import Foundation
    
    class Base64VC: NSObject {
    
        //----------------------------------------------------------------
        // MARK:-
        // MARK:- String to Base64 Encode Methods
        //----------------------------------------------------------------
    
        func sampleStringEncodingAndDecoding() {
            if let base64String = self.base64Encode(string: "TestString") {
                print("Base64 Encoded String: \n\(base64String)")
                if let originalString = self.base64Decode(base64String: base64String) {
                    print("Base64 Decoded String: \n\(originalString)")
                }
            }
        }
    
    
        //----------------------------------------------------------------
    
        func base64Encode(string: String) -> String? {
            if let stringData = string.data(using: .utf8) {
                return stringData.base64EncodedString()
            }
            return nil
        }
    
        //----------------------------------------------------------------
    
        func base64Decode(base64String: String) -> String? {
            if let base64Data = Data(base64Encoded: base64String) {
                return String(data: base64Data, encoding: .utf8)
            }
            return nil
        }
    
    
        //----------------------------------------------------------------
        // MARK:-
        // MARK:- Image to Base64 Encode  Methods
        //----------------------------------------------------------------
    
        func sampleImageEncodingAndDecoding() {
            if let base64ImageString = self.base64Encode(image: UIImage.init(named: "yourImageName")!) {
                print("Base64 Encoded Image: \n\(base64ImageString)")
                if let originaImage = self.base64Decode(base64ImageString: base64ImageString) {
                    print("originalImageData \n\(originaImage)")
                }
            }
        }
    
        //----------------------------------------------------------------
    
        func base64Encode(image: UIImage) -> String? {
            if let imageData = UIImagePNGRepresentation(image) {
                return imageData.base64EncodedString()
            }
            return nil
        }
    
        //----------------------------------------------------------------
    
        func base64Decode(base64ImageString: String) -> UIImage? {
            if let base64Data = Data(base64Encoded: base64ImageString) {
                return UIImage(data: base64Data)!
            }
            return nil
        }
    
    
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.