Swift - 从UnsafePointer <UInt8>转换为String

mac*_*acu 9 type-conversion swift

我考虑了很多类似的问题,但仍然无法让编译器接受这个.

Socket Mobile API(在Objective-C中)将ISktScanDecodedData传递给Swift中的委托方法(数据可能是二进制的,我想这就是为什么它不作为字符串提供):

func onDecodedData(device: DeviceInfo?, DecodedData d: ISktScanDecodedData?) {
  let symbology: String = d!.Name()
  let rawData: UnsafePointer<UInt8> = d!.getData()
  let rawDataSize: UInt32 = decoded!.getDataSize()
  // want a String (UTF8 is OK) or Swifty byte array...
}
Run Code Online (Sandbox Code Playgroud)

在C#中,此代码将原始数据转换为字符串:

string s = Marshal.PtrToStringAuto(d.GetData(), d.GetDataSize());
Run Code Online (Sandbox Code Playgroud)

在斯威夫特,我可以得到UnsafeArray,但后来我卡住了:

let rawArray = UnsafeArray<UInt8>(start: rawData, length: Int(rawDataSize))
Run Code Online (Sandbox Code Playgroud)

另外我看String.fromCStringNSString.stringWithCharacters,但也不会在手上接受类型的参数.如果我可以从转换UnsafePointer<UInt8>UnsafePointer<()>,例如,那么这将是可用的(虽然我不知道如果它甚至会是安全的):

NSData(bytesNoCopy: UnsafePointer<()>, length: Int, freeWhenDone: Bool)
Run Code Online (Sandbox Code Playgroud)

是否有明显的方法来获取所有这些字符串?

hnh*_*hnh 15

怎么样,'纯'Swift 2.2而不是使用NSData:

public extension String {

  static func fromCString
    (cs: UnsafePointer<CChar>, length: Int!) -> String?
  {
    if length == .None { // no length given, use \0 standard variant
      return String.fromCString(cs)
    }

    let buflen = length + 1
    var buf    = UnsafeMutablePointer<CChar>.alloc(buflen)
    memcpy(buf, cs, length))
    buf[length] = 0 // zero terminate
    let s = String.fromCString(buf)
    buf.dealloc(buflen)
    return s
  }
}
Run Code Online (Sandbox Code Playgroud)

和斯威夫特3:

public extension String {

  static func fromCString
    (cs: UnsafePointer<CChar>, length: Int!) -> String?
  {
    if length == nil { // no length given, use \0 standard variant
      return String(cString: cs)
    }

    let buflen = length + 1
    let buf    = UnsafeMutablePointer<CChar>.allocate(capacity: buflen)
    memcpy(buf, cs, length)
    buf[length] = 0 // zero terminate
    let s = String(cString: buf)
    buf.deallocate(capacity: buflen)
    return s
  }
}
Run Code Online (Sandbox Code Playgroud)

不可否认,分配缓冲区并复制数据只是为了添加零终结符有点愚蠢.

显然,正如Zaph所提到的,你需要确保你对字符串编码的假设是正确的.


Mar*_*n R 10

这应该工作:

let data = NSData(bytes: rawData, length: Int(rawDataSize))
let str = String(data: data, encoding: NSUTF8StringEncoding)
Run Code Online (Sandbox Code Playgroud)

Swift 3更新:

let data = Data(bytes: rawData, count: Int(rawDataSize))
let str = String(data: data, encoding: String.Encoding.utf8)
Run Code Online (Sandbox Code Playgroud)

结果字符串是nil数据不表示有效的UTF-8序列.