আমি কীভাবে iOS এ বেস 64 এনকোডিং করব?


230

আমি base64এনকোডিং এবং ডিকোডিং করতে চাই , তবে আমি আইফোন থেকে কোনও সমর্থন পাই না SDK। আমি base64লাইব্রেরির সাথে বা ছাড়া কীভাবে এনকোডিং এবং ডিকোডিং করব?


1
এই পোস্টের নীচে একটি দুর্দান্ত কোড নমুনা আছে। খুব স্ব- নিহিত
গ্রেগ বার্নহার্ট

@ গ্রেগবার্নহার্ড লিঙ্কটি মারা গেছে।
সিউর

উত্তর:


116

এটি অবজেক্টিভ সি বিভাগগুলির জন্য একটি ভাল ব্যবহারের কেস ।

বেস 64 এনকোডিংয়ের জন্য:

#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

বেস 64 ডিকোডিংয়ের জন্য:

#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
ওবজ-সি যদি সি-এর মতো কিছু হয় তবে আপনার এটি করতে সক্ষম হওয়া উচিত: স্ট্যাটিক চর বেস 6464 এনকোডিং টেবিল []৪] = "এবিসিডিই [ইত্যাদি] 9৮৯ + /";
আর্টেলিয়াস

3
আমি খুঁজে পেলাম কেন আমি কেবল 4 টি অক্ষর পাচ্ছি ... যখন () লুপের জন্য ফিরে আসার আগে একটি} হওয়া দরকার। আমি এটি সম্পাদনা করব তবে আমি দেখতে পাচ্ছি না।
ল্যারি হিপ

3
এটি কোনও বিশ্লেষক বাগ নয়। কোডটিও ইনবুফ [3] অ্যাক্সেস করার চেষ্টা করে দেখুন যা সেই অ্যারের সীমা ছাড়িয়ে গেছে। এই কোড দুর্গন্ধযুক্ত।
মাইক ওয়েলার

1
দৈর্ঘ্য মান কী প্রতিনিধিত্ব করে?
মেগাএএমএএনএক্স

3
আইওএস 7 এর হিসাবে অ্যাপল তাদের স্থানীয় বেস 64 এনকোডিং পদ্ধতিটি উন্মোচিত করেছে। পিছনের সামঞ্জস্য বজায় রেখে কীভাবে এটি ব্যবহার করতে হয় তার জন্য নীচের রবের উত্তর দেখুন।
কোড কমান্ডার

100

একটি সত্যই, সত্যই দ্রুত বাস্তবায়ন যা পিএইচপি কোর লাইব্রেরি থেকে দেশীয় উদ্দেশ্য-সি কোডে পোর্ট করা হয়েছিল (এবং পরিবর্তিত / উন্নত) QSUtilities লাইব্রেরি থেকে QSStrings ক্লাসে উপলব্ধ । আমি একটি দ্রুত মাপদণ্ডটি করেছি: একটি 5.3MB চিত্র (জেপিজি) ফাইল এনকোড করতে <50 মিমি এবং প্রায় 140 মিমি ডিকোড করতে লেগেছিল।

পুরো লাইব্রেরির জন্য কোড (বেস 64 পদ্ধতিগুলি সহ) গিটহাবটিতে উপলব্ধ

অথবা বিকল্পভাবে, আপনি যদি কেবল বেস 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 বাড়াতে হবে না?
এরিকপ্রাইস

1
আপেল এটি সরবরাহ করে না এই সত্যটি God
শ্বর

2
আমি এটি কিছুক্ষণ ব্যবহার করে আসছি এবং মনে হচ্ছে যে আমি স্মৃতি দুর্নীতির সাথে সম্পর্কিত কিছু ত্রুটি পেতে এবং গার্ড ম্যালোক ব্যবহার শুরু না করা অবধি দুর্দান্ত কাজ করেছে আমি এটিকে এই লাইনে সংকুচিত করেছি: * Pজেক্টপয়েন্টার = '\ 0'; সুতরাং আপনি যদি নিজের অ্যাপগুলিতে এটি ব্যবহার করেন তবে সাবধান হন।
ম্যাটিয়া

72

Orতিহাসিকভাবে আমরা বাইনারি ডেটা থেকে বেস স্ট্রিং (এবং পিছনে) রূপান্তর করার জন্য আপনাকে অনেকগুলি তৃতীয় পক্ষের বেস 64 লাইব্রেরিতে (অন্য উত্তরগুলিতে আলোচিত) একটিতে নির্দেশনা দিতাম, তবে আইওএস 7 এর এখন নেটিভ বেস 64 এনকোডিং রয়েছে (এবং পূর্বে প্রাইভেট আইওএস 4 পদ্ধতি উন্মুক্ত করে, যদি আপনাকে আইওএসের পূর্ববর্তী সংস্করণগুলি সমর্থন করার প্রয়োজন হয়)।

সুতরাং বেস 64 উপস্থাপন আপনি রূপে ব্যবহার করতে পারেন রূপান্তর NSDataকরতে । আপনার যদি 7.0 এর আগে আইওএস সংস্করণগুলি সমর্থন করতে হয় তবে আপনি এটি করতে পারেন:NSStringbase64EncodedStringWithOptions

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 এর আগে আইওএস সংস্করণগুলি সমর্থন করার প্রয়োজন হয় তবে আপনি এটি করতে পারেন:

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 এর আগে আইওএস সংস্করণগুলির সাথে পশ্চাদপটে সামঞ্জস্যের প্রয়োজন না হয় তবে এটি আরও সহজ , যথাক্রমে ব্যবহার করুন base64EncodedStringWithOptionsবা initWithBase64EncodedString, যথাক্রমে ব্যবহার করুন এবং পূর্ববর্তী আইওএস সংস্করণগুলির জন্য রান-টাইম চেক নিয়ে বিরক্ত করবেন না। প্রকৃতপক্ষে, আপনি যখন আপনার সর্বনিম্ন লক্ষ্য আইওএস 7 বা তার বেশি হয় তখন আপনি উপরোক্ত কোডটি ব্যবহার করেন, আপনি অবহেলা পদ্ধতি সম্পর্কে আসলে একটি সংকলক সতর্কতা পাবেন। সুতরাং, আইওএস 7 এবং এর চেয়েও বড় ক্ষেত্রে, আপনি কেবল এগুলি দিয়ে বেস 64 স্ট্রিংয়ে রূপান্তর করতে পারবেন:

NSString *string = [data base64EncodedStringWithOptions:kNilOptions];

এবং সাথে আবার ফিরে:

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

ধন্যবাদ এই রব সম্পর্কে। আপনি কি লিখেছিলেন, " ... এবং পূর্ববর্তী ব্যক্তিগত আইওএস 4 পদ্ধতিগুলি প্রকাশ করে " দয়া করে সংক্ষিপ্ত বিবরণ দিতে পারেন ?
phi

8
এই উত্তরটি সেই সমস্ত কাস্টম বাস্তবায়নের নীচে সমাহিত করা খুব লজ্জার বিষয়। এটি এসও-র একটি দুর্বলতা, যেখানে মূল প্রশ্ন জিজ্ঞাসার অনেক পরে আরও উপযুক্ত সমাধান আসতে পারে, সেই সমাধানটি এখন যা গ্রহণ করা হয়েছিল তার সাথে প্রতিযোগিতা করতে হবে।
জাকেভ

এজন্য এটি সাম্প্রতিক সঠিক উত্তরগুলির উর্ধ্বে নেওয়া সর্বদা দরকারী :)
স্টিভ উইলফোর্ড

এর মতো নরকের উত্তরগুলি কেন শীর্ষে নেই :(, আমি উপরের সমস্ত উত্তর প্রক্রিয়া করতে অনেক সময় ব্যয় করেছি T__T
আলশ সংকলক

33

আইওএসের মধ্যে বেস 64 এনকোডিং এবং ডিকোডিংয়ের সমর্থনে অন্তর্নির্মিত অন্তর্ভুক্ত রয়েছে। যদি আপনি তাকান resolv.hআপনার দুটি ফাংশন দেখতে হবে b64_ntopএবং b64_pton। স্কয়ার সকেটরকেট লাইব্রেরি কীভাবে উদ্দেশ্য-সি থেকে এই ফাংশনগুলি ব্যবহার করতে হয় তার একটি যুক্তিসঙ্গত উদাহরণ সরবরাহ করে।

এই ক্রিয়াকলাপগুলি বেশ ভালভাবে পরীক্ষিত এবং নির্ভরযোগ্য - র্যান্ডম ইন্টারনেট পোস্টিংগুলিতে আপনি দেখতে পেতে পারেন এমন অনেকগুলি প্রয়োগের বিপরীতে। বিরুদ্ধে লিঙ্ক করতে ভুলবেন না libresolv.dylib


3
অসাধারণ; এলোমেলো ইন্টারনেট সাইটের চেয়ে অনেক ভাল! যদি কেউ এই স্ক্রয়লিটি-ডকুমেন্টেড ফাংশনগুলি ব্যবহার করতে উদ্বিগ্ন হয় তবে আপনি অ্যাপলের সাইটে এর উত্সটি দেখতে পাবেন ।
জেসি রুশাক

1
এই লোকটি এতে আরও কিছু পটভূমি দেয়: blog.montgomerie.net/ios-hided-base64-routines
মাইক

21

যেহেতু বেস6464 এনকোডিং এবং আইফোনটিতে এটি গুগল এক নম্বর হিট বলে মনে হচ্ছে, তাই উপরের কোড স্নিপেটের সাথে আমার অভিজ্ঞতা ভাগ করে নেওয়ার মতো অনুভব করেছি।

এটি কাজ করে তবে এটি অত্যন্ত ধীর। এলোমেলো চিত্রের একটি বেঞ্চমার্ক (0.4 এমবি) নেটিভ আইফোনে 37 সেকেন্ড সময় নিয়েছিল। মূল কারণটি হ'ল সমস্ত ওওপি যাদু - একক চর এনএসএসআরটিংস ইত্যাদি, যা কেবল এনকোডিংয়ের পরে স্বতঃপ্রযুক্ত হয়।

এখানে পোস্ট করা আরেকটি পরামর্শে (আব) ওপেনসেল লাইব্রেরি ব্যবহার করেছে, যা ওভারকিলের মতোও বোধ করে।

নীচের কোডটি 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 এনকোডিং পর্যবেক্ষণ করি। আপনি কি আরএফসি 4648 এর উদাহরণ দিয়ে পরীক্ষা করেছেন? সরঞ্জামস.ইএইটিএফ.আর.এইচটিএম
অ্যালেক্স রেনল্ডস

3
বেস 6464 এনকোডিং টেবিল 1, বেস 6464 এনকোডিং টেবিল 2, বেস 6464 এনকোডিং টেবিল 3 এবং বেস 6464 এনকোডিং টেবিল 4 কী উল্লেখ করছে তা দেখার জন্য লড়াই করা হচ্ছে?
জেমি চ্যাপম্যান

খুব সহায়ক, তবে এটি ইনপুট বাফারের শেষের বাইরে পড়তে পারে। যখন (বাম == ২), কাঁচা [inp + 2] টিএমপিফুফের শেষের বাইরে এক বাইট হবে। আমি মনে করি লাইনটি হওয়া উচিত: যদি (বাম == 2) আউটবুফ [আউটপুট ++] = বেস64 এনকোডিং টেবিল [((কাঁচা [ইনপ + 1] এবং 0x0F) << 2)];
জন লেমবার্গে

নীচের লাইনটি <কোড> চর tmpbuf [2] = {0,0}; </code> <code> স্বাক্ষরবিহীন চর tmpbuf [3] = {0,0,0}; </code>
সত্য

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

আরও ভাল সমাধান:

এনএসডাটাতে একটি বিল্ট ইন ফাংশন রয়েছে

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

আমরা iOS সংস্করণটির উপর ভিত্তি করে এটি করতে পারি যার উপরে অ্যাপ্লিকেশনটি "[[ইউআইডিভাইস বর্তমান ডিভাইস] সিস্টেম ভার্সন] .ফ্লোটভ্যালু" ব্যবহার করে চলছে।
নাগরাজ

2
1. এটি আপনাকে বলবে না যে আপনি এসডিকে আপনি কীসের সাথে যুক্ত করেছেন, এটি রানটাইম চেক। ২. এটি সরাসরি অ্যাপলের নির্দেশনার বিরোধী। আপনার সিস্টেমের সংস্করণ নয়, কোনও বৈশিষ্ট্যের প্রাপ্যতার জন্য যাচাই করা উচিত।
ক্লিলেশ

6

খুশি লোকেরা এটি পছন্দ করেছে। শেষ খেলাটি কিছুটা ত্রুটিযুক্ত ছিল আমাকে অবশ্যই স্বীকার করতে হবে। যথাযথভাবে ইনপ = 0 সেট করার পাশাপাশি আপনারও tmpbuf এর আকার 3 টির মতো বাড়ানো উচিত

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

বা কাঁচা [inp + 2] এর oring ছেড়ে দিন; আমাদের যদি কাঁচা [ইনপ + 2] থাকত! = 0 এই খণ্ডটির জন্য আমরা অবশ্যই অবশ্যই লুপে থাকতাম ...

যে কোনও উপায়ে কাজ করে, আপনি স্বচ্ছতার জন্য চূড়ান্ত টেবিল লুক্কুল ব্লকটিকে লুপের মতো করে রাখার বিষয়ে বিবেচনা করতে পারেন। চূড়ান্ত সংস্করণে আমি ব্যবহার করেছি

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

যোগ করতে ==

দুঃখিত, আমি আরএফসি এবং স্টাফ চেক করিনি, আরও ভাল কাজ করা উচিত ছিল!


3
আপনার পূর্ববর্তী উত্তরটি অন্যরকম অ্যাকাউন্ট হিসাবে আপনার ইতিমধ্যে এখানে একটি অ্যাকাউন্ট রয়েছে। এছাড়াও, এটি হয় এটির একটি সম্পাদনা বা কোনও মন্তব্য হওয়া উচিত।
অ্যালাস্টার পিটস

@ অ্যালস্টায়ার, আপনি কুকিজ সাফ করার পরে নিবন্ধভুক্ত না করে প্রতিবার উত্তর পোস্ট করার সময় আপনি একটি "অ্যাকাউন্ট" পেয়েছেন বলে মনে হয়। আমি আমার প্রথম "অ্যাকাউন্ট" (এমনকি একই ইমেল এবং আইপি অ্যাড্রেস সহ) সংযোগ করতে সক্ষম হইনি, তাই আমি কেবল এটি একটি নতুন উত্তর হিসাবে রেখেছি, এর জন্য দুঃখিত sorry - সবে নিবন্ধিত!
এমভিডিস

3
এই উত্তরটি আপনার আগেরটিতে সম্পাদনা করতে পারে এমন কোনও সুযোগের একটি যথার্থ সঠিক সংস্করণ আছে কি? ধন্যবাদ!
জোসেফ এইচ

6

IOS8 এর অধীনে এবং পরে - (NSString *)base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)optionsএনএসডিটা ব্যবহার


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

এনএসডিটাতে বিভাগ হিসাবে এখানে একটি কমপ্যাক্ট উদ্দেশ্য-সি সংস্করণ রয়েছে। এটি সম্পর্কে কিছু চিন্তা লাগে ...

@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-বাইট) "=" অক্ষরের সাথে 'গন্তব্য' যুক্ত করে প্যাডিং যুক্ত করা যেতে পারে।

এরপরে কোনও বিভাগ এনএসএসস্ট্রিং এ যুক্ত করা যায়, এভাবে:

@implementation NSString (StringUtils)

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

 return [theData newStringInBase64FromData];
}

@end

2

আইওএস আইওএস ৪ এর পর থেকে বেস 64 ইনকোডিং এবং ডিকোডিংয়ের পদ্ধতিগুলি (লাইব্রেসোলভ ব্যবহার না করে) বিল্ট-ইন রয়েছে However তবে এটি কেবল আইওএস 7 এসডিকেই ঘোষণা করা হয়েছিল। অ্যাপল ডকুমেন্টেশনে উল্লেখ করা হয়েছে যে আইওএস 4 বা তদুর্ধের লক্ষ্যবস্তু করার সময় আপনি এটি ব্যবহার করতে পারেন।

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

2

এখানে এনএসডাটা অবজেক্টটি বেস 64৪ তে রূপান্তর করার উদাহরণ রয়েছে It এটি অন্যভাবে কীভাবে যেতে হয় তাও দেখায় (একটি বেস 64৪ এনকোডড এনএসডাটা অবজেক্টটি ডিকোড করুন):

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

আইওএস 7 এ

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

নাগরাজ ইতিমধ্যে এটি উল্লেখ করেছেন। তার পোস্ট এবং মন্তব্যগুলির সাথে এটি দেখুন যা এটি আইওএস 4 সাল থেকে সেখানে রয়েছে বলে
জানিয়েছে

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
        }
    
    
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.