如何将String转换为UnsafePointer <uint8>和length </uint8>

时间:2014-08-28 17:47:57

标签: string swift

当我使用NSOutputStream&#39; write方法

func write(_ buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int

我不知道如何将String转换为UnsafePointer<UInt8>和长度

我怎样才能在swift中做到这一点?

10 个答案:

答案 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)