How to Encode a String to Base64 in Swift

How can I encode a string to Base64 in Swift?

I don’t have 6.2 installed but I don’t think 6.3 is any different in this regard:

dataUsingEncoding returns an optional, so you need to unwrap that.

NSDataBase64EncodingOptions.fromRaw has been replaced with NSDataBase64EncodingOptions(rawValue:). Slightly surprisingly, this is not a failable initializer so you don’t need to unwrap it.

But since NSData(base64EncodedString:) is a failable initializer, you need to unwrap that.

Btw, all these changes were suggested by Xcode migrator (click the error message in the gutter and it has a “fix-it” suggestion).

Final code, rewritten to avoid force-unwraps, looks like this:

import Foundation

let str = "iOS Developer Tips encoded in Base64"
println("Original: \(str)")

let utf8str = str.dataUsingEncoding(NSUTF8StringEncoding)

if let base64Encoded = utf8str?.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0))
{

println("Encoded: \(base64Encoded)")

if let base64Decoded = NSData(base64EncodedString: base64Encoded, options: NSDataBase64DecodingOptions(rawValue: 0))
.map({ NSString(data: $0, encoding: NSUTF8StringEncoding) })
{
// Convert back to a string
println("Decoded: \(base64Decoded)")
}
}

(if using Swift 1.2 you could use multiple if-lets instead of the map)

Swift 5 Update:

import Foundation

let str = "iOS Developer Tips encoded in Base64"
print("Original: \(str)")

let utf8str = str.data(using: .utf8)

if let base64Encoded = utf8str?.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0)) {
print("Encoded: \(base64Encoded)")

if let base64Decoded = Data(base64Encoded: base64Encoded, options: Data.Base64DecodingOptions(rawValue: 0))
.map({ String(data: $0, encoding: .utf8) }) {
// Convert back to a string
print("Decoded: \(base64Decoded ?? "")")
}
}

Convert string to base64 in Swift 3

Use this instead:

let longstring = "test123"
if let data = (longstring).data(using: String.Encoding.utf8) {
let base64 = data.base64EncodedString(options: Data.Base64EncodingOptions(rawValue: 0))
print(base64)// dGVzdDEyMw==\n
}

Decoding Base64 String Returns nil

Your string contains underscore character ('_' U+005F LOW LINE), which is invalid as Base-64.

There are some variations of Base-64, so you need to find which one your Gmail something is using. (Wikipedia Base-64.)

Assuming it uses base64url URL- and filename-safe, you may need to write something like this:

extension String {
func urlSafeBase64Decoded() -> String? {
var st = self
.replacingOccurrences(of: "_", with: "/")
.replacingOccurrences(of: "-", with: "+")
let remainder = self.count % 4
if remainder > 0 {
st = self.padding(toLength: self.count + 4 - remainder,
withPad: "=",
startingAt: 0)
}
guard let d = Data(base64Encoded: st, options: .ignoreUnknownCharacters) else{
return nil
}
return String(data: d, encoding: .utf8)
}
}

Example:

let base64 = "WW91ciBhY2NvdW50IHNhbG1hbm1hamlkMTRAZ21haWwuY29tIGlzIGxpc3RlZCBhcyB0aGUgcmVjb3ZlcnkgZW1haWwgZm9yDQpzaWRyYWlicmFoaW0wMzQ5QGdtYWlsLmNvbS4gRG9uJ3QgcmVjb2duaXplIHRoaXMgYWNjb3VudD8gQ2xpY2sgaGVyZQ0KPGh0dHBzOi8vYWNjb3VudHMuZ29vZ2xlLmNvbS9BY2NvdW50RGlzYXZvdz9hZHQ9QU9YOGtpcHBKRG5OX19KVGloejdoUHRnMlFwRHRRb3VETWVUalRMN2J4YjA3b2dJRC1xYm54QnZPRElTUjB3Q1h6RHlYQSZyZm49MTI3JmFuZXhwPWdpdmFiLWZhLS1tZHYyLWZhPg0KR29vZ2xlIEFQSXMgRXhwbG9yZXIgd2FzIGdyYW50ZWQgYWNjZXNzIHRvIHlvdXIgbGlua2VkIEdvb2dsZSBBY2NvdW50DQoNCg0Kc2lkcmFpYnJhaGltMDM0OUBnbWFpbC5jb20NCg0KSWYgeW91IGRpZCBub3QgZ3JhbnQgYWNjZXNzLCB5b3Ugc2hvdWxkIGNoZWNrIHRoaXMgYWN0aXZpdHkgYW5kIHNlY3VyZSB5b3VyDQphY2NvdW50Lg0KQ2hlY2sgYWN0aXZpdHkNCjxodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20vQWNjb3VudENob29zZXI_RW1haWw9c2lkcmFpYnJhaGltMDM0OUBnbWFpbC5jb20mY29udGludWU9aHR0cHM6Ly9teWFjY291bnQuZ29vZ2xlLmNvbS9hbGVydC9udC8xNTY3ODQ3ODEyMDAwP3JmbiUzRDEyNyUyNnJmbmMlM0QxJTI2ZWlkJTNELTE1NzQzMDEyNjk4Mjg2MTM3OTQlMjZldCUzRDElMjZhbmV4cCUzRGdpdmFiLWZhLS1tZHYyLWZhPg0KWW91IHJlY2VpdmVkIHRoaXMgZW1haWwgdG8gbGV0IHlvdSBrbm93IGFib3V0IGltcG9ydGFudCBjaGFuZ2VzIHRvIHlvdXINCkdvb2dsZSBBY2NvdW50IGFuZCBzZXJ2aWNlcy4NCsKpIDIwMTkgR29vZ2xlIExMQywgMTYwMCBBbXBoaXRoZWF0cmUgUGFya3dheSwgTW91bnRhaW4gVmlldywgQ0EgOTQwNDMsIFVTQQ0K"

print(base64.urlSafeBase64Decoded() ?? "* decoding failed*")

Output:

You received this email to let you know about important changes to your
Google Account and services.
© 2019 Google LLC, 1600 Amphitheatre Parkway, Mountain View, CA 94043, USA

iOS Swift convert HEX string to Base64 with NO_WRAP option

It's in the doc:

  • base64 encoding options
  • base64 decoding options

So just specify no option at all when encoding to avoid adding any line ending character, and specify ignoreUnknownCharacters when decoding to ignore line ending characters.

Step 1: Hex String to Data is a separate StackOverflow question (but you should avoid Hex String to begin with, it's a big waste of bytes!)

Step 2: Data to base64 Data or base64 String (choose one)

// By default, no line endings are inserted: https://developer.apple.com/reference/foundation/nsdata/1412739-base64encodeddata
let encodedAsData = data.base64EncodedData()

// By default, no line endings are inserted: https://developer.apple.com/reference/foundation/nsdata/1413546-base64encodedstring
let encodedAsString = data.base64EncodedString()

Swift base64 decode non alphabetic and non utf-8 strings

You're looking a fairly old examples. The syntax changed to this:

let decodedData = Data(base64Encoded: base64String)

I've tested with your examples, and they work fine. Keep in mind that the output is raw Data, this isn't a String in any encoding (Windows-1252 or ISO-8859-1, etc). It's just a sequence of random bytes, and that's what it is expected to be. The online tool you're using is just trying to decode it as ISO-8859-1, but that's gibberish, and is in fact corrupted in the output you've shown. It's not displaying the first byte (which is 0x16, and unprintable).

Swift 4 base64 String to Data not working due to String containing incomplete emoji

(Some of this is out of comments, but trying to bring it together and describe solutions.)

First, your strings are not UTF-8. They're UTF-16 or malformed UTF-16. Sometimes UTF-16 happens to be interpretable as UTF-8, but when it is, there will be NULL characters scattered through the string. In your "working" example, it's not really working.

let toApostrophe = "ACAAKgBVAFMAQQAqACAn"                 // *USA* '//
if let textData = Data(base64Encoded: toApostrophe) {
if let decodedString = String(data: textData, encoding: .utf8) {
print(decodedString)
print(decodedString.count)
print(decodedString.map { $0.unicodeScalars.map { $0.value } } )
} else {
print("DID NOT DECODE UTF8")
}
} else {
print("DID NOT DECODE BASE64")
}

Prints:

 *USA* '
15
[[0], [32], [0], [42], [0], [85], [0], [83], [0], [65], [0], [42], [0], [32], [39]]

Note that the length of string is 15 characters, not 8 like you were probably expecting. That's because it includes an extra invisible NULL (0) between most characters.

toEndBracket doesn't happen to be legal UTF-8, however. Here are its bytes:

["00", "20", "00", "2a", "00", "55", "00", "53", "00", "41", "00", "2a", "00", "20", "27", "96", "00", "20", "d8", "3c", "00", "22", "00", "7d", "00", "5d", "00"]

This is ok until it gets to 0xd8. That starts with the bits 110, which indicates that it's the start of a two byte sequence. But the next byte is 0x3c, which is not a valid second byte of a multi-byte sequence (it should start with 10, but it starts with 00). So we can't decode this as UTF-8. Even using decodeCString(_:as:repairingInvalidCodeUnits) can't decode this string because it's filled with embedded NULLs. You've got to decode it using at least the right encoding.

But let's do that. Decode as UTF-16. At least that's close, even though it's slightly invalid UTF-16.

let toEndBracket16 = String(data: toEndBracketData, encoding: .utf16)
// " *USA* ➖ �"}]"

Now we can at least work with this. It's invalid JSON, though. So we can strip that by filtering it:

let legalJSON = String(toEndBracket16.filter { $0 != "\u{FFFD}" })
// " *USA* ➖ "}]"

I don't really recommend this approach. It's incredibly fragile and based on broken input. Fix the input. But in a world where you're trying to parse broken input, these are the tools.



Related Topics



Leave a reply



Submit