Pan*_*man 1 arrays base64 ios swift
为了保持简单,我将只编码/解码单个字节。
\n\n如果我对字节 127 进行编码,我会得到 base64 字符串“fw==”,它可以成功解码回字节 127。但是,如果我对字节 \xe2\x89\xa5 128 进行编码,那么即使我可以生成没有错误的 Base64 字符串(例如,字节 128 给出字符串“gA==”),当我尝试对其进行解码时出现错误。
\n\n这是我的代码,可以将其复制粘贴到任何 Xcode Playground 中以重现该问题:
\n\nfunc stringToByteArray(string: String) -> [UInt8] {\n var bytes: [UInt8] = [];\n for code in string.utf8 {\n bytes.append(UInt8(code));\n }\n return bytes;\n}\n\nfunc byteArrayToBase64(bytes: [UInt8]) -> String {\n let nsdata: NSData = NSData(bytes: bytes as [Byte], length: bytes.count)\n let base64Encoded: NSString = nsdata.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));\n return String(base64Encoded);\n}\n\nfunc base64ToByteArray(base64String: String) -> [UInt8] {\n let nsdata: NSData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))!\n let base64Decoded: NSString = NSString(data: nsdata, encoding: NSUTF8StringEncoding)!\n return stringToByteArray(String(base64Decoded));\n}\n\n/* Replacing 127 with 128 below or greater produces an error */\nvar testString = byteArrayToBase64([127]);\nbase64ToByteArray(testString)\nRun Code Online (Sandbox Code Playgroud)\n
问题就在这里:
let base64Decoded: NSString = NSString(data: nsdata, encoding: NSUTF8StringEncoding)!
Run Code Online (Sandbox Code Playgroud)
您将解码后的数据转换为字符串。此操作失败,
[128]因为它不代表有效的 UTF-8 序列。
这是避免中间字符串的版本:
func base64ToByteArray(base64String: String) -> [UInt8] {
let nsdata: NSData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))!
// Create array of the required size ...
var bytes = [UInt8](count: nsdata.length, repeatedValue: 0)
// ... and fill it with the data
nsdata.getBytes(&bytes)
return bytes
}
Run Code Online (Sandbox Code Playgroud)
评论:
options: NSDataBase64DecodingOptions(rawValue: 0)可以简化为options: nil.baseString如果不是有效的 Base64 字符串,您的函数将崩溃。您可以更改它以返回可选值。然后它看起来像这样:
func byteArrayToBase64(bytes: [UInt8]) -> String {
let nsdata = NSData(bytes: bytes, length: bytes.count)
let base64Encoded = nsdata.base64EncodedStringWithOptions(nil);
return base64Encoded;
}
func base64ToByteArray(base64String: String) -> [UInt8]? {
if let nsdata = NSData(base64EncodedString: base64String, options: nil) {
var bytes = [UInt8](count: nsdata.length, repeatedValue: 0)
nsdata.getBytes(&bytes)
return bytes
}
return nil // Invalid input
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
let testString = byteArrayToBase64([127, 128, 0, 130]);
println(testString) // Output: f4AAgg==
if let result = base64ToByteArray(testString) {
println(result) // Output: [127, 128, 0, 130]
} else {
println("failed")
}
Run Code Online (Sandbox Code Playgroud)
Swift 2 / Xcode 7更新:
func byteArrayToBase64(bytes: [UInt8]) -> String {
let nsdata = NSData(bytes: bytes, length: bytes.count)
let base64Encoded = nsdata.base64EncodedStringWithOptions([]);
return base64Encoded;
}
func base64ToByteArray(base64String: String) -> [UInt8]? {
if let nsdata = NSData(base64EncodedString: base64String, options: []) {
var bytes = [UInt8](count: nsdata.length, repeatedValue: 0)
nsdata.getBytes(&bytes, length: bytes.count)
return bytes
}
return nil // Invalid input
}
let testString = byteArrayToBase64([127, 128, 0, 130]);
print(testString) // Output: f4AAgg==
if let result = base64ToByteArray(testString) {
print(result) // Output: [127, 128, 0, 130]
} else {
print("failed")
}
Run Code Online (Sandbox Code Playgroud)
Swift 3及更高版本的更新:
func byteArrayToBase64(bytes: [UInt8]) -> String {
let data = Data(bytes)
let base64Encoded = data.base64EncodedString()
return base64Encoded;
}
func base64ToByteArray(base64String: String) -> [UInt8]? {
guard let data = Data(base64Encoded: base64String) else {
return nil
}
return Array(data)
}
let testString = byteArrayToBase64(bytes: [127, 128, 0, 130]);
print(testString) // Output: f4AAgg==
if let result = base64ToByteArray(base64String: testString) {
print(result) // Output: [127, 128, 0, 130]
} else {
print("failed")
}
Run Code Online (Sandbox Code Playgroud)