如何在 iOS 上的 Swift 中使用 Big5 编码

ndr*_*isg 1 xcode encoding big5 swift swift3

我正在扫描一个二维码,其中包含以 Big5 编码的汉字。(????)

是否有机会在 Swift 3 中正确解码此字符串?

我在 GitHub 和这个SO question上找到了这个Objective-C 示例,但在 Swift中没有和常量。kCFStringEncodingBig5_HKSCS_1999kCFStringEncodingBig


更新:

我找到了相应的 swift 变量,所以我现在尝试了以下操作:

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
    guard metadataObjects?.count ?? 0 > 0 else {
        return
    }
    guard let metadata = metadataObjects.first as? AVMetadataMachineReadableCodeObject, let code = metadata.stringValue else {
        return
    }
    let big5encoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(CFStringEncodings.big5.rawValue)))
    print("Big5 encoded String: " + (String(data: code.data(using: .nonLossyASCII)!, encoding: big5encoding) ?? "?"))
}
Run Code Online (Sandbox Code Playgroud)

输出: Big5 encoded String: \326\367\322\263\270\305\277\366

我怎样才能达到预期的输出 Big5 encoded String: ????


更新 2:

看来我的二维码包含了一些损坏的数据,所以我创建了一个新的代码,这次内容肯定是一个 Big5 编码的字符串(Android 应用程序正确读取它)。内容是??

当我使用 iOS 应用程序扫描此代码时, metadata.stringValue 返回日语字符串 ????

这到底是怎么回事???

Mar*_*n R 5

CFStringEncodings 在 Swift 3 中定义为枚举值:

public enum CFStringEncodings : CFIndex {

    // ...    
    case big5 /* Big-5 (has variants) */
    // ...    
    case big5_HKSCS_1999 /* Big-5 with Hong Kong special char set supplement*/
    // ...    
}
Run Code Online (Sandbox Code Playgroud)

所以你必须转换

CFStringEncodings -> CFStringEncoding -> NSStringEncoding -> String.Encoding
Run Code Online (Sandbox Code Playgroud)

例子:

let cfEnc = CFStringEncodings.big5
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let big5encoding = String.Encoding(rawValue: nsEnc) // String.Encoding
Run Code Online (Sandbox Code Playgroud)

然后big5encoding可用于之间的转换String(NS)Data

在您的情况下,您有一个字符串,其中每个 unicode 标量对应于 Big5 编码的一个字节。那么以下应该工作:

// let code = "\u{00D6}\u{00F7}\u{00D2}\u{00B3}\u{00B8}\u{00C5}\u{00BF}\u{00F6}"
let bytes = code.unicodeScalars.map { UInt8(truncatingBitPattern: $0.value) }
if let result = String(bytes: bytes, encoding: big5encoding) {
    print(result)
}
Run Code Online (Sandbox Code Playgroud)

或者,使用 ISO Latin 1 编码将 Unicode 代码点 U+0000 .. U+00FF 映射到字节 0x00 .. 0xFF 的事实:

if let data = code.data(using: .isoLatin1),
    let result = String(data: data, encoding: big5encoding) {
    print(result)
}
Run Code Online (Sandbox Code Playgroud)