【问题标题】:Error when decoding certain Base64 strings, but not others解码某些 Base64 字符串时出错,但不是其他字符串
【发布时间】:2014-11-09 09:38:53
【问题描述】:

为了简单起见,我将只编码/解码一个字节。

如果我对字节 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)

【问题讨论】:

    标签: ios swift base64 bytearray


    【解决方案1】:

    问题出在这里:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-25
      • 2019-06-15
      • 1970-01-01
      • 2018-04-29
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      相关资源
      最近更新 更多