Когда я использую метод NSOutputStream
write
func write(_ buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int
Я не знаю, как преобразовать String
в UnsafePointer<UInt8>
и length
Как это сделать быстро?
Когда я использую метод NSOutputStream
write
func write(_ buffer: UnsafePointer<UInt8>, maxLength length: Int) -> Int
Я не знаю, как преобразовать String
в UnsafePointer<UInt8>
и length
Как это сделать быстро?
Сначала вы должны преобразовать строку в данные 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) }
Вот как это сделать в 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
Ответ для людей, работающих в 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)
Вы также можете позволить 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
Вот расширение строки для 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)
Swift 4,
Преобразуйте строку в NSString, затем используйте методы NSString.
let text = "Hello"
let pointer: UnsafePointer<Int8>? = NSString(string: text).utf8String
let length = NSString(string: text).length
Я вижу, что есть и другие ответы, и принятый ответ, так что, кажется, вы получили то, что вам нужно. Я пришел сюда, потому что заметил предупреждения об 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)
(! используется, чтобы заставить замолчать ошибку компилятора, но вы должны избегать принудительного развертывания, где это возможно).
file.cString(используя: String.Encoding.utf8)