问题
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