Swift 3:将字符串编码为UTF-16LE
Swift 3: Encode String to UTF-16LE
我需要将字符串编码为 UTF-16LE(稍后再转换为 sha1),但我遇到了一些问题。这是我试过的:
let utf16array = Array("password".utf16)
print(utf16array)
// [112, 97, 115, 115, 119, 111, 114, 100]
但这正是我所期待的:
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0]
同样使用 utf8array:
let utf8array = "password".utf8.map({ [=13=] as UInt8 })
// [112, 97, 115, 115, 119, 111, 114, 100]
所以,这就是我对 "fix" 所做的:
var bytesArray:[UInt16] = []
for byte in utf16array {
bytesArray.append(byte)
bytesArray.append(0)
}
print(bytesArray)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0]
但我敢肯定这不是正确的方法。有什么建议吗?
使用 是适合这里目的的解决方案。
但为了好玩,另一种方法是使用 String
:s UTF-16 编码方法(String
的 utf16
属性) OP。使用 UInt8
的 init(truncatingBitPattern: UInt16)
初始值设定项,结合 zip
后跟 flatMap
,后者将压缩元组展平为数组:
let pw = "password€"
let bytes = zip(pw.utf16.map{ UInt8(truncatingBitPattern: [=10=]) },
pw.utf16.map{ UInt8(truncatingBitPattern: [=10=] >> 8) })
.flatMap{ [[=10=], ] }
print(bytes)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
您可以使用
获得 UTF-16LE 数据的表示形式
let password = "password€"
let data = password.data(using: .utf16LittleEndian)!
print(data as NSData)
// <70006100 73007300 77006f00 72006400 ac20>
这已经足以计算 SHA1 摘要(代码
来自 How to crypt string to sha1 with Swift?):
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1([=11=], CC_LONG(data.count), &digest)
}
let hexEncodedDigest = digest.map { String(format: "%02hhx", [=11=]) }.joined()
print(hexEncodedDigest)
// 177f0d080dfe533e102dd67d6321204813cf1b0c
但是如果你需要它作为一个字节数组那么
let bytesArray = data.map { [=12=] }
print(bytesArray)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
会起作用。
(为了演示,我附加了一个非ASCII字符,
€ = U+20AC
变成 172, 32
.)
如果您想知道如何将 [UInt16]
数组转换为
[UInt8]
数组,这就是你可以通过一些指针杂耍来做到这一点的方法
(只有一个副本):
let utf16array = Array("password€".utf16)
print(utf16array)
// [112, 97, 115, 115, 119, 111, 114, 100, 8364]
let bytes = Array(utf16array.withUnsafeBufferPointer {
[=13=].baseAddress!.withMemoryRebound(to: UInt8.self, capacity: 2 * utf16array.count) {
UnsafeBufferPointer(start: [=13=], count: 2 * utf16array.count)
}
})
print(bytes)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
使用 cString
访问器怎么样?
var bytes = str.cStringUsingEncoding(NSUTF16LittleEndianStringEncoding)
我需要将字符串编码为 UTF-16LE(稍后再转换为 sha1),但我遇到了一些问题。这是我试过的:
let utf16array = Array("password".utf16)
print(utf16array)
// [112, 97, 115, 115, 119, 111, 114, 100]
但这正是我所期待的:
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0]
同样使用 utf8array:
let utf8array = "password".utf8.map({ [=13=] as UInt8 })
// [112, 97, 115, 115, 119, 111, 114, 100]
所以,这就是我对 "fix" 所做的:
var bytesArray:[UInt16] = []
for byte in utf16array {
bytesArray.append(byte)
bytesArray.append(0)
}
print(bytesArray)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0]
但我敢肯定这不是正确的方法。有什么建议吗?
使用
但为了好玩,另一种方法是使用 String
:s UTF-16 编码方法(String
的 utf16
属性) OP。使用 UInt8
的 init(truncatingBitPattern: UInt16)
初始值设定项,结合 zip
后跟 flatMap
,后者将压缩元组展平为数组:
let pw = "password€"
let bytes = zip(pw.utf16.map{ UInt8(truncatingBitPattern: [=10=]) },
pw.utf16.map{ UInt8(truncatingBitPattern: [=10=] >> 8) })
.flatMap{ [[=10=], ] }
print(bytes)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
您可以使用
获得 UTF-16LE 数据的表示形式let password = "password€"
let data = password.data(using: .utf16LittleEndian)!
print(data as NSData)
// <70006100 73007300 77006f00 72006400 ac20>
这已经足以计算 SHA1 摘要(代码 来自 How to crypt string to sha1 with Swift?):
var digest = [UInt8](repeating: 0, count:Int(CC_SHA1_DIGEST_LENGTH))
data.withUnsafeBytes {
_ = CC_SHA1([=11=], CC_LONG(data.count), &digest)
}
let hexEncodedDigest = digest.map { String(format: "%02hhx", [=11=]) }.joined()
print(hexEncodedDigest)
// 177f0d080dfe533e102dd67d6321204813cf1b0c
但是如果你需要它作为一个字节数组那么
let bytesArray = data.map { [=12=] }
print(bytesArray)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
会起作用。
(为了演示,我附加了一个非ASCII字符,
€ = U+20AC
变成 172, 32
.)
如果您想知道如何将 [UInt16]
数组转换为
[UInt8]
数组,这就是你可以通过一些指针杂耍来做到这一点的方法
(只有一个副本):
let utf16array = Array("password€".utf16)
print(utf16array)
// [112, 97, 115, 115, 119, 111, 114, 100, 8364]
let bytes = Array(utf16array.withUnsafeBufferPointer {
[=13=].baseAddress!.withMemoryRebound(to: UInt8.self, capacity: 2 * utf16array.count) {
UnsafeBufferPointer(start: [=13=], count: 2 * utf16array.count)
}
})
print(bytes)
// [112, 0, 97, 0, 115, 0, 115, 0, 119, 0, 111, 0, 114, 0, 100, 0, 172, 32]
使用 cString
访问器怎么样?
var bytes = str.cStringUsingEncoding(NSUTF16LittleEndianStringEncoding)