How to use Big5 encoding in Swift on iOS

烂漫一生 提交于 2019-12-24 09:50:12

问题


I'm scanning a QR-Code with chinese characters encoded in Big5. (主页概况)

Is there a chance to get this String decoded correctly in Swift 3?

I found this Objective-C example on GitHub and this SO question, but there are no kCFStringEncodingBig5_HKSCS_1999 and kCFStringEncodingBig constants in Swift.


Update:

I found the corresponding swift variables, so i now tried the following:

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

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

How can i get to the expected output Big5 encoded String: 主页概况


Update 2:

It seems that my QR-Code contained some corrupt data, so i created a new Code, this time the content is definitely a Big5 encoded String (Android App reads it correctly). The content is 傳統

When I scan this code with my iOS app, metadata.stringValue returns the japanese String カヌイホ

What the hell is going on here???


回答1:


CFStringEncodings are defined as enumeration values in 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*/
    // ...    
}

so you have to convert

CFStringEncodings -> CFStringEncoding -> NSStringEncoding -> String.Encoding

Example:

let cfEnc = CFStringEncodings.big5
let nsEnc = CFStringConvertEncodingToNSStringEncoding(CFStringEncoding(cfEnc.rawValue))
let big5encoding = String.Encoding(rawValue: nsEnc) // String.Encoding

Then big5encoding can be used for conversion between String and (NS)Data.

In your case you have a string where each unicode scalar corresponds to a byte of the Big5 encoding. Then the following should work:

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

Alternatively, using the fact that the ISO Latin 1 encoding maps the Unicode code points U+0000 .. U+00FF to the bytes 0x00 .. 0xFF:

if let data = code.data(using: .isoLatin1),
    let result = String(data: data, encoding: big5encoding) {
    print(result)
}


来源:https://stackoverflow.com/questions/44063591/how-to-use-big5-encoding-in-swift-on-ios

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!