Ich würde gerne base64
codieren und decodieren, aber ich konnte keine Unterstützung vom iPhone finden SDK
. Wie kann ich base64
mit oder ohne Bibliothek codieren und decodieren?
Ich würde gerne base64
codieren und decodieren, aber ich konnte keine Unterstützung vom iPhone finden SDK
. Wie kann ich base64
mit oder ohne Bibliothek codieren und decodieren?
Antworten:
Dies ist ein guter Anwendungsfall für Ziel-C- Kategorien .
Für die Base64-Codierung:
#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
Für die Base64-Decodierung:
#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
Eine wirklich sehr schnelle Implementierung, die aus der PHP Core-Bibliothek in nativen Objective-C-Code portiert (und geändert / verbessert) wurde, ist in der QSStrings-Klasse aus der QSUtilities-Bibliothek verfügbar . Ich habe einen schnellen Benchmark durchgeführt: Die Codierung einer 5,3-MB-Bilddatei (JPEG) dauerte <50 ms und die Dekodierung etwa 140 ms.
Der Code für die gesamte Bibliothek (einschließlich der Base64-Methoden) ist auf GitHub verfügbar .
Oder alternativ, wenn Sie möchten, dass der Code nur die Base64-Methoden selbst enthält, habe ich ihn hier veröffentlicht:
Zunächst benötigen Sie die Zuordnungstabellen:
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
};
So codieren Sie:
+ (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;
}
Zu dekodieren:
+ (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;
}
strResult
im Encoder zugewiesene Speicher scheint durchgesickert zu sein; es braucht nur ein free()
am Ende (vor der Rückkehr, aber danach NSString stringWithCString
)
encodeBase64WithData:
Methode nicht der erste Parameter im Aufruf calloc()
um 1 erhöht werden, um den Nullterminator ( '\0'
) zu berücksichtigen, den Sie am Ende hinzufügen?
In der Vergangenheit hätten wir Sie an eine der vielen Basis-64-Bibliotheken von Drittanbietern verwiesen (wie in den anderen Antworten erläutert), um von Binärdaten in Basis-64-Zeichenfolgen (und zurück) zu konvertieren, aber iOS 7 verfügt jetzt über eine native Basis-64-Codierung (und macht die zuvor privaten iOS 4-Methoden verfügbar (falls Sie frühere Versionen von iOS unterstützen müssen).
Sie können also eine Konvertierung NSData
in eine NSString
Basis-64-Darstellung verwenden base64EncodedStringWithOptions
. Wenn Sie auch iOS-Versionen vor 7.0 unterstützen müssen, können Sie Folgendes tun:
NSString *string;
if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
string = [data base64EncodedStringWithOptions:kNilOptions]; // iOS 7+
} else {
string = [data base64Encoding]; // pre iOS7
}
Und um die Basis 64 NSString
wieder zu konvertieren , können NSData
Sie verwenden initWithBase64EncodedString
. Wenn Sie iOS-Versionen vor 7.0 unterstützen müssen, können Sie Folgendes tun:
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
}
Wenn Sie vor 7.0 keine Abwärtskompatibilität mit iOS-Versionen benötigen, ist es natürlich noch einfacher, einfach base64EncodedStringWithOptions
bzw. zu initWithBase64EncodedString
verwenden und sich nicht um die Laufzeitprüfung für frühere iOS-Versionen zu kümmern. Wenn Sie den obigen Code verwenden, wenn Ihr Mindestziel iOS 7 oder höher ist, erhalten Sie tatsächlich eine Compiler-Warnung zu den veralteten Methoden. In iOS 7 und höher konvertieren Sie also einfach in eine Basis-64-Zeichenfolge mit:
NSString *string = [data base64EncodedStringWithOptions:kNilOptions];
und wieder zurück mit:
NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:kNilOptions];
iOS bietet integrierte Unterstützung für die Base64-Codierung und -Decodierung. Wenn Sie sich ansehen resolv.h
, sollten Sie die beiden Funktionen b64_ntop
und sehen b64_pton
. Die Square SocketRocket- Bibliothek bietet ein vernünftiges Beispiel für die Verwendung dieser Funktionen von Objective-C.
Diese Funktionen sind ziemlich gut getestet und zuverlässig - im Gegensatz zu vielen Implementierungen, die Sie in zufälligen Internet-Postings finden können. Vergiss nicht, gegen zu verlinken libresolv.dylib
.
Da dies der Google-Hit Nummer eins bei Base64-Codierung und iPhone zu sein scheint, wollte ich meine Erfahrungen mit dem obigen Code-Snippet teilen.
Es funktioniert, aber es ist extrem langsam. Ein Benchmark für ein zufälliges Bild (0,4 MB) dauerte auf dem nativen iPhone 37 Sekunden. Der Hauptgrund ist wahrscheinlich die gesamte OOP-Magie - Einzelzeichen-NSStrings usw., die erst nach Abschluss der Codierung automatisch freigegeben werden.
Ein anderer Vorschlag, der hier (ab) veröffentlicht wurde, verwendet die openssl-Bibliothek, die sich ebenfalls wie ein Overkill anfühlt.
Der folgende Code dauert 70 ms - das ist eine 500-fache Beschleunigung. Dies führt nur eine Base64-Codierung durch (die Decodierung erfolgt, sobald ich darauf stoße).
+ (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;
}
Ich habe das Linienschneiden weggelassen, da ich es nicht brauchte, aber es ist trivial hinzuzufügen.
Für diejenigen, die an einer Optimierung interessiert sind: Ziel ist es, das Geschehen in der Hauptschleife zu minimieren. Daher wird die gesamte Logik zur Behandlung der letzten 3 Bytes außerhalb der Schleife behandelt.
Versuchen Sie außerdem, Daten direkt zu bearbeiten, ohne sie zusätzlich in / aus den Puffern zu kopieren. Und reduzieren Sie jede Arithmetik auf das Nötigste.
Beachten Sie, dass sich die Bits, die zusammengesetzt werden, um einen Eintrag in der Tabelle nachzuschlagen, nicht überlappen würden, wenn sie ohne Verschiebung zusammengefügt würden. Eine wesentliche Verbesserung könnte daher darin bestehen, 4 separate 256-Byte-Nachschlagetabellen zu verwenden und die Verschiebungen wie folgt zu beseitigen:
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];
Natürlich könnte man noch viel weiter gehen, aber das geht hier über den Rahmen hinaus.
Bei der hervorragenden Verbesserung von mvds gibt es zwei Probleme. Ändern Sie den Code in diesen:
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++] = '=';
Bessere Lösung:
In NSData ist eine Funktion integriert
[data base64Encoding]; //iOS < 7.0
[data base64EncodedStringWithOptions:NSDataBase64Encoding76CharacterLineLength]; //iOS >= 7.0
Ich bin froh, dass es den Leuten gefallen hat. Das Endspiel war ein wenig fehlerhaft, muss ich zugeben. Neben der richtigen Einstellung von inp = 0 sollten Sie entweder auch die Größe von tmpbuf auf 3 erhöhen, z
unsigned char tmpbuf[3] = {0,0,0};
oder lassen Sie den rohen Orring weg [inp + 2]; Wenn wir für dieses Stück ein rohes [inp + 2]! = 0 hätten, wären wir natürlich immer noch auf dem Laufenden ...
In beiden Fällen können Sie aus Gründen der Übersichtlichkeit in Betracht ziehen, den Final Table-Suchblock mit dem in der Schleife identischen Block identisch zu halten. In der endgültigen Version, die ich verwendet habe, habe ich getan
while ( outp%4 ) outbuf[outp++] = '=';
Um das == hinzuzufügen
Tut mir leid, dass ich RFCs und andere Dinge nicht überprüft habe, hätte einen besseren Job machen sollen!
#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
Ein Update zur Verwendung der NSData (NSDataBase64Encoding)
Kategoriemethoden in iOS7 finden Sie in meiner Antwort hier: https://stackoverflow.com/a/18927627/1602729
Hier ist eine kompakte Objective-C-Version als Kategorie für NSData. Man muss nachdenken ...
@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
Bei Bedarf kann eine Auffüllung hinzugefügt werden, indem der Bereich von 'byt' erweitert und 'dest' vor der Rückkehr mit (2-byt) "=" Zeichen angehängt wird.
Eine Kategorie kann dann zu NSString hinzugefügt werden, also:
@implementation NSString (StringUtils)
- (NSString *)newStringInBase64FromString
{
NSData *theData = [NSData dataWithBytes:[self UTF8String] length:[self length]];
return [theData newStringInBase64FromData];
}
@end
iOS verfügt seit iOS 4 über integrierte Base64-Codierungs- und -Decodierungsmethoden (ohne Verwendung von Libresolv). Diese wurden jedoch nur im iOS 7 SDK deklariert. In der Apple-Dokumentation heißt es, dass Sie es für iOS 4 und höher verwenden können.
NSData *myData = ... some data
NSString *base64String = [myData base64Encoding];
NSData *decodedData = [[NSData alloc] initWithBase64Encoding:base64String];
Hier ist ein Beispiel zum Konvertieren eines NSData-Objekts in Base 64. Es zeigt auch, wie Sie in die andere Richtung gehen (ein Base 64-codiertes NSData-Objekt dekodieren):
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];
Ich habe es mit der folgenden Klasse gemacht ..
@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
Während des Anrufs
[Base64Converter base64StringFromData:dataval length:lengthval];
Das ist es...
Ich denke, das wird hilfreich sein
+ (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];
}}
Laden Sie Base64 herunter
Führen Sie den folgenden Code aus, um ein Bild in base64 zu konvertieren
NSString *base64String=[UIImagePNGRepresentation(image) base64Encoding];
Gemäß Ihrer Anforderung habe ich mit Swift 4 eine Beispieldemo erstellt, in der Sie Zeichenfolge und Bild gemäß Ihrer Anforderung codieren / decodieren können.
Ich habe auch Beispielmethoden für relevante Operationen hinzugefügt.
//
// 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
}
}