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
How to Round a Double to the Nearest Int in Swift
How to Apply the Type to a Nsfetchrequest Instance
Swift Dictionary Get Key For Value
Unexpected Non-Void Return Value in Void Function (Swift 2.0)
Changing the Status Bar Color For Specific Viewcontrollers Using Swift in Ios8
Uialertcontroller - Add Custom Views to Actionsheet
Whither Dispatch_Once in Swift 3
Getting the Decimal Part of a Double in Swift
Swift 2 ( Executefetchrequest ): Error Handling
Realitykit VS Scenekit VS Metal - High-Quality Rendering
Xcode Swift Am/Pm Time to 24 Hour Format
How to Make a Random Color With Swift
When Should I Access Properties With Self in Swift