Подтвердить что ты не робот

Как преобразовать String в UnsafePointer <UInt8> и длину

Когда я использую метод NSOutputStream write

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

Я не знаю, как преобразовать String в UnsafePointer<UInt8> и length

Как это сделать быстро?

4b9b3361

Ответ 1

Сначала вы должны преобразовать строку в данные 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) }

Ответ 2

Вот как это сделать в Swift 3. Хорошо работает и в Swift 4

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

let string = String(cString: cString!) // String

Ответ 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

Вы также можете позволить 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

Ответ 5

Вот расширение строки для 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)

Ответ 6

Swift 4,

Преобразуйте строку в NSString, затем используйте методы NSString.

let text = "Hello"
let pointer: UnsafePointer<Int8>? = NSString(string: text).utf8String
let length = NSString(string: text).length

Ответ 7

Я вижу, что есть и другие ответы, и принятый ответ, так что, кажется, вы получили то, что вам нужно. Я пришел сюда, потому что заметил предупреждения об withUnsafeMutableBytes Swift 5 для withUnsafeMutableBytes и др. И начал тестировать ответ @abdullahselek, но заметил в Swift 5 (еще не проверял, работал ли он в предыдущих версиях), что String можно преобразовать в UnsafePointer<UInt8> в строке, так что вы можете использовать его там, где UnsafePointer<UInt8>. В случае, если это помогает увидеть другой пример, здесь наша старая и обновленная функция, размещенная здесь:

OLD

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

NEW

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
}

С учетом сказанного, вы можете использовать аналогичный подход, чтобы получить ваш поток следующим образом:

let stream = OutputStream(toBuffer: UnsafeMutablePointer(mutating: someString), capacity: someString.data(using: .utf8)!.count)

(! используется, чтобы заставить замолчать ошибку компилятора, но вы должны избегать принудительного развертывания, где это возможно).

Ответ 8

file.cString(используя: String.Encoding.utf8)