当我使用NSOutputStream
' write
方法
func write(_ buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int
我不知道如何将String
转换为UnsafePointer<UInt8>
和长度
我怎样才能在swift中做到这一点?
答案 0 :(得分:20)
您必须先将字符串转换为UTF-8数据
let string = "foo bar"
let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
然后将其写入输出流
let outputStream: NSOutputStream = ... // the stream that you want to write to
let bytesWritten = outputStream.write(UnsafePointer(data.bytes), maxLength: data.length)
UnsafePointer()
强制转型是必要的,因为data.bytes
具有UnsafePointer<Void>
类型,而不是UnsafePointer<UInt8>
所期望的write()
方法
Swift 3的更新:
let string = "foo bar"
// Conversion to UTF-8 data (cannot fail):
let data = string.data(using: String.Encoding.utf8)!
// Write to output stream:
let outputStream: NSOutputStream = ... // the stream that you want to write to
let bytesWritten = data.withUnsafeBytes { outputStream.write($0, maxLength: data.count) }
答案 1 :(得分:14)
以下是如何在Swift 3中执行此操作。在Swift 4中运行正常
Figure2
要从extension String {
func toPointer() -> UnsafePointer<UInt8>? {
guard let data = self.data(using: String.Encoding.utf8) else { return nil }
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
let stream = OutputStream(toBuffer: buffer, capacity: data.count)
stream.open()
data.withUnsafeBytes({ (p: UnsafePointer<UInt8>) -> Void in
stream.write(p, maxLength: data.count)
})
stream.close()
return UnsafePointer<UInt8>(buffer)
}
}
转换为String
UnsafeMutablePointer<Int8>
要从let cString = strdup("Hello") // UnsafeMutablePointer<Int8>
转换为UnsafeMutablePointer<Int8>
String
答案 2 :(得分:3)
你也可以让Swift为你做这件事!
import Foundation
// Example function:
func printUTF8Vals(_ ptr: UnsafePointer<UInt8>, _ len: Int) {
for i in 0..<len {
print(ptr[i])
}
}
// Call it:
let str = "Hello"
printUTF8Vals(str, str.lengthOfBytes(using: String.Encoding.utf8))
// Prints:
// 72
// 101
// 108
// 108
// 111
答案 3 :(得分:3)
现在为在Swift 4工作的人们提供答案。您不能再从Data对象获取字节,您必须将它们复制到UnsafeMutablePointer
let helloWorld = "Hello World!"
let data = helloWorld.data(using: String.Encoding.utf8, allowLossyConversion: false)!
var dataMutablePointer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
//Copies the bytes to the Mutable Pointer
data.copyBytes(to: dataMutablePointer, count: data.count)
//Cast to regular UnsafePointer
let dataPointer = UnsafePointer<UInt8>(dataMutablePointer)
//Your stream
oStream.write(dataPointer, maxLength: data.count)
答案 4 :(得分:1)
这是 Swift 5 的字符串扩展名,您可以将字符串转换为UnsafePointer<UInt8>
和UnsafeMutablePointer<Int8>
extension String {
func toUnsafePointer() -> UnsafePointer<UInt8>? {
guard let data = self.data(using: .utf8) else {
return nil
}
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: data.count)
let stream = OutputStream(toBuffer: buffer, capacity: data.count)
stream.open()
let value = data.withUnsafeBytes {
$0.baseAddress?.assumingMemoryBound(to: UInt8.self)
}
guard let val = value else {
return nil
}
stream.write(val, maxLength: data.count)
stream.close()
return UnsafePointer<UInt8>(buffer)
}
func toUnsafeMutablePointer() -> UnsafeMutablePointer<Int8>? {
return strdup(self)
}
}
要将UnsafeMutablePointer<Int8>
转换为String
guard let mutablePointer = "test".toUnsafeMutablePointer() else {
return
}
let str = String(cString: mutablePointer)
答案 5 :(得分:1)
快捷键4 ,
将String转换为NSString,然后使用NSString的方法。
let text = "Hello"
let pointer: UnsafePointer<Int8>? = NSString(string: text).utf8String
let length = NSString(string: text).length
答案 6 :(得分:0)
我看到还有其他答案,也是一个可以接受的答案,因此看来您已经找到了需要的东西。我来这里是因为我注意到withUnsafeMutableBytes
等人的Swift 5弃用警告,并开始测试@abdullahselek的答案,但是我在Swift 5中(尚未验证它是否可以在以前的版本中使用)注意到{{1} }可直接转换为String
,因此可以在需要UnsafePointer<UInt8>
的地方使用它。如果有助于查看另一个示例,这是我们的旧功能和更新功能,发布在这里:
OLD
UnsafePointer<UInt8>
新
let derivationStatus = localDerivedKeyData.withUnsafeMutableBytes { derivedKeyBytes in
salt.withUnsafeBytes { saltBytes in
CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordData.count,
saltBytes,
salt.count,
algorithm,
UInt32(rounds),
derivedKeyBytes,
derivedKeyData.count
)
}
}
话虽如此,您可以使用类似的方法来获取流,如下所示:
let derivationStatus = localDerivedKeyData.withUnsafeMutableBytes { (outputBytes: UnsafeMutableRawBufferPointer) -> Int32 in
let status = CCKeyDerivationPBKDF(
CCPBKDFAlgorithm(kCCPBKDF2),
password, // a String
passwordData.count, // just the password String converted to Data
String(data: salt, encoding: .utf8), // converts salt (Data) to String
salt.count,
algorithm,
UInt32(rounds),
outputBytes.baseAddress?.assumingMemoryBound(to: UInt8.self),
derivedKeyData.count
)
return status
}
(!用于使编译器错误静音,但应尽可能避免强行展开)。
答案 7 :(得分:0)
到目前为止(在Swift 5中)是最简单的方法:
let s = "hello, world"
let pointer = UnsafePointer(Array(s.utf8CString))
不确定这是向后兼容的方式。
答案 8 :(得分:0)
我创建了一个 Swift 扩展,其中包含该功能以及用于从字符串生成指针的许多其他功能。
它包括一个完整的测试套件并且它支持:
myString.stackPointer() -> UnsafePointer<Int8>?
myString.mutableStackPointer() -> UnsafeMutablePointer<Int8>?
myString.withUnsignedStackPointer { (ptr: UnsafePointer<UInt8>?) in
myString.withUnsignedMutableStackPointer { (ptr: UnsafeMutablePointer<UInt8>?) in
myString.heapPointer() -> UnsafePointer<Int8>?
myString.mutableHeapPointer() -> UnsafeMutablePointer<Int8>?
myString.unsignedHeapPointer() -> UnsafePointer<UInt8>?
myString.unsignedMutableHeapPointer() -> UnsafeMutablePointer<UInt8>?
https://gist.github.com/nathan-fiscaletti/892e074dc14e6707603414cd2d80c287
如果您想对其进行测试,您应该可以直接将其粘贴到 Swift Playground 中。
答案 9 :(得分:-1)
file.cString(using:String.Encoding.utf8)