解码某些Base64字符串时出错,但不解码其他字符串

时间:2014-11-09 09:38:53

标签: ios swift base64 bytearray

为了保持这一点,我只会对单个字节进行编码/解码。

如果我对字节127进行编码,我得到base64字符串“fw ==”,它可以成功解码回字节127.但是,如果我编码一个≥128的字节,那么即使我可以产生一个base64字符串没有错误(例如,字节128给出字符串“gA ==”),当我尝试解码时出错。

这是我的代码,可以将其复制粘贴到任何Xcode游乐场以重现问题:

func stringToByteArray(string: String) -> [UInt8] {
    var bytes: [UInt8] = [];
    for code in string.utf8 {
        bytes.append(UInt8(code));
    }
    return bytes;
}

func byteArrayToBase64(bytes: [UInt8]) -> String {
    let nsdata: NSData = NSData(bytes: bytes as [Byte], length: bytes.count)
    let base64Encoded: NSString = nsdata.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0));
    return String(base64Encoded);
}

func base64ToByteArray(base64String: String) -> [UInt8] {
    let nsdata: NSData = NSData(base64EncodedString: base64String, options: NSDataBase64DecodingOptions(rawValue: 0))!
    let base64Decoded: NSString = NSString(data: nsdata, encoding: NSUTF8StringEncoding)!
    return stringToByteArray(String(base64Decoded));
}

/* Replacing 127 with 128 below or greater produces an error */
var testString = byteArrayToBase64([127]);
base64ToByteArray(testString)

1 个答案:

答案 0 :(得分:4)

问题在于:

let base64Decoded: NSString = NSString(data: nsdata, encoding: NSUTF8StringEncoding)!

您将解码数据转换为字符串。这失败了 [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
}

说明:

  • 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
}

使用示例:

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")
}

更新 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")
}