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

Как преобразовать массив байтов UInt8 в строку в Swift

Я сталкиваюсь с проблемами при преобразовании UInt8 массива UInt8 в строку в swift. Я искал и нашел простое решение

String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)

но он показывает ошибку String.type не имеет члена stringWithBytes. Кто-нибудь может предложить мне решение?

это мой код, где я получаю NSData и преобразую в байтовый массив, а затем мне нужно преобразовать этот байтовый массив в строку.

let count = data.length / sizeof(UInt8)
var array = [UInt8](count: count, repeatedValue: 0)
data.getBytes(&array, length:count * sizeof(UInt8))
String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)
4b9b3361

Ответ 1

Обновление для Swift 3/Xcode 8:

Строка из bytes: [UInt8]:

if let string = String(bytes: bytes, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

Строка из data: Data:

let data: Data = ...
if let string = String(data: data, encoding: .utf8) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

Обновление для Swift 2/Xcode 7:

Строка из bytes: [UInt8]:

if let string = String(bytes: bytes, encoding: NSUTF8StringEncoding) {
    print(string)
} else {
    print("not a valid UTF-8 sequence")
}

Строка из data: NSData:

let data: NSData = ...
if let str = String(data: data, encoding: NSUTF8StringEncoding) {
    print(str)
} else {
    print("not a valid UTF-8 sequence")
}

Предыдущий ответ:

String не имеет stringWithBytes(). NSString имеет

 NSString(bytes: , length: , encoding: )

метод, который вы можете использовать, но вы можете создать строку непосредственно из NSData, без необходимости в массиве UInt8:

if let str = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
    println(str)
} else {
    println("not a valid UTF-8 sequence")
}

Ответ 2

Это сработало для меня:

String(bytes: bytes, encoding: NSUTF8StringEncoding)

Ответ 3

Swifty solution

array.reduce("", combine: { $0 + String(format: "%c", $1)})

Hex-представление:

array.reduce("", combine: { $0 + String(format: "%02x", $1)})

Ответ 4

Это решение работает.

NSString(bytes: data!, length: data!.count, encoding: NSUTF8StringEncoding) 

Ответ 5

Мартин Р в fooobar.com/questions/264189/... ответил Сунил Кумар на его проблему, но не на вопрос темы. Проблема все еще появляется, если у вас уже есть массив байтов UInt8, и вам нужно представить его как строку.

Вот мое решение:

extension String {
    init(_ bytes: [UInt8]) {
        self.init()
        for b in bytes {
            self.append(UnicodeScalar(b))
        }
    }
}

Используя это расширение, вы можете теперь инициализировать String с массивом байтов UInt8 следующим образом:

func testStringUInt8Extension() {
    var cs : [UInt8] = []
    for char : UInt8 in 0..<255 {
        cs.append(char)
    }
    print("0..255 string looks like \(String(cs)))")
}

Это не идеальное решение, потому что практически вам нужно будет декодировать что-то вроде текста в кодировке UTF-8. Но для данных ASCII это работает так, как ожидалось.

Ответ 6

Swift 3

следующее дало мне ошибку из-за "NSUTF8StringEncoding":

String(data: nsdata, encoding: NSUTF8StringEncoding)! 

это сработало для меня в быстрой 3:

let xmlStr:String = String(bytes: data!, encoding: String.Encoding.utf8)!

Ответ 7

Не очень элегантный или "Swifty", но это просто и работает:

let i: UInt8 = 65
let s = String(format: "%c", i)  // A

Я потратил много времени на поиск простого способа сделать это, прежде чем я внезапно подумал о "printf" из моих дней сценариев Unix!

Ответ 8

Полный пример для Swift 2 и 3:

import Foundation

let bytes : [UInt8] = [72, 73]
let nsdata = NSData(bytes: bytes as [UInt8], length: 2)
let str = String(data: nsdata, encoding: NSUTF8StringEncoding)! // 'HI'

Ответ 9

Вот еще один обобщенный код для извлечения строк из массива байтов, где строки были закодированы в UTF-8.

/// Class which encapsulates a Swift byte array (an Array object with elements of type UInt8) and an
/// index into the array.
open class ByteArrayAndIndex {

   private var _byteArray : [UInt8]
   private var _arrayIndex = 0

   public init(_ byteArray : [UInt8]) {
      _byteArray = byteArray;
   }

   /// Method to get a UTF-8 encoded string preceded by a 1-byte length.
   public func getShortString() -> String {
      return getTextData(getUInt8AsInt())
   }

   /// Method to get a UTF-8 encoded string preceded by a 2-byte length.
   public func getMediumString() -> String {
      return getTextData(getUInt16AsInt())
   }

   /// Method to get a UTF-8 encoded string preceded by a 4-byte length. By convention a length of
   /// -1 is used to signal a String? value of nil.
   public func getLongString() -> String? {
      let encodedLength = getInt32()
      if encodedLength == -1 {
         return nil
      }
      return getTextData(Int(encodedLength))
   }

   /// Method to get a single byte from the byte array, returning it as an Int.
   public func getUInt8AsInt() -> Int {
      return Int(getUInt8())
   }

   /// Method to get a single byte from the byte array.
   public func getUInt8() -> UInt8 {
      let returnValue = _byteArray[_arrayIndex]
      _arrayIndex += 1
      return returnValue
   }

   /// Method to get a UInt16 from two bytes in the byte array (little-endian), returning it as Int.
   public func getUInt16AsInt() -> Int {
      return Int(getUInt16())
   }

   /// Method to get a UInt16 from two bytes in the byte array (little-endian).
   public func getUInt16() -> UInt16 {
      let returnValue = UInt16(_byteArray[_arrayIndex]) |
                        UInt16(_byteArray[_arrayIndex + 1]) << 8
      _arrayIndex += 2
      return returnValue
   }

   /// Method to get an Int32 from four bytes in the byte array (little-endian).
   public func getInt32() -> Int32 {
      return Int32(bitPattern: getUInt32())
   }

   /// Method to get a UInt32 from four bytes in the byte array (little-endian).
   public func getUInt32() -> UInt32 {
      let returnValue = UInt32(_byteArray[_arrayIndex]) |
                        UInt32(_byteArray[_arrayIndex + 1]) << 8 |
                        UInt32(_byteArray[_arrayIndex + 2]) << 16 |
                        UInt32(_byteArray[_arrayIndex + 3]) << 24
      _arrayIndex += 4
      return returnValue
   }

   // Method to decode UTF-8 encoded text data in the byte array.
   private func getTextData(_ numberBytes : Int) -> String {
      if numberBytes == 0 {
         return ""  // Tiny optimization?
      }
      let startIndex = _arrayIndex
      _arrayIndex += numberBytes
      return String(bytes: _byteArray[startIndex ..< _arrayIndex], encoding: String.Encoding.utf8)!
   }
}

Это выдержка из более крупного класса (см. также fooobar.com/questions/264190/...), который я использую для обработки сериализованных данных.

Ответ 10

Для тех, кто не может преобразовать массив байтов в строку, попробуйте это

String(data: Data(decrypted), encoding: .utf8)

Это мой пример расширения строки. Я использую это для AES

extension String {

    func decryptAES(key: String, iv: String) -> String {
        do {
            let encrypted = self
            let key = Array(key.utf8)
            let iv = Array(iv.utf8)
            let aes = try AES(key: key, blockMode: CTR(iv: iv), padding: .noPadding)
            let decrypted = try aes.decrypt(Array(hex: encrypted))
            return String(data: Data(decrypted), encoding: .utf8) ?? ""
        } catch {
            return "Error: \(error)"
        }
    }
}

Ответ 11

"MSString (bytes:, length:, encoding:)", похоже, не работает с 26 июля 2015 г.

Преобразование значений байтов в ASCII кажется проблематичным, если вы нажмете на стену, вы можете сделать это трудным путем следующим образом (и, возможно, мне не хватает чего-то с быстрым, но я не мог найти никаких решений в течение моих временных рамок.) Это будет выполняются с двумя функциями. Первая функция принимает UInt8 и преобразует ее в представление "\ u {}", которое затем возвращается функцией. Во-вторых, настраивается другая функция, которая принимает в качестве массива UInt8 параметр, а затем выводит строку.

Шаг # 1. Функция преобразует каждый байт в "\ u {someNumber}"

func convertToCharacters(#UInt8Bits : UInt8) -> String {

 var characterToReturn : String

 switch UInt8Bits{

case 0x00: characterToReturn = "\u{0}"
case 0x01: characterToReturn = "\u{1}"
case 0x02: characterToReturn = "\u{2}"
case 0x03: characterToReturn = "\u{3}"
case 0x04: characterToReturn = "\u{4}"

//.. Добавьте для количества символов, которые вы ожидаете... не забудьте базу 16..

case 0x09: characterToReturn = "\u{09}"
case 0x0A: characterToReturn = "\u{0A}"

default: characterToReturn = "\u{0}"

/*.. и вплоть до 0xff */

case 0xFE: characterToReturn = "\u{FE}"
case 0xFF: characterToReturn = "\u{FF}"



  }

return characterToReturn

}

Шаг # 2... Затем функция, которая принимает в массиве UInt8 в качестве параметра, затем возвращает строку...

func UInt8ArrayToString(#UInt8Array: [UInt8]) -> String {

var returnString : String = "" for eachUInt8Byte in UInt8Array {

returnString += convertToCharacter(UInt8Bits: eachUInt8Byte)

}

return returnString }

Это должно работать на Swift Playground Сделать массив

var myArray: [UInt8] = [0x30, 0x3A, 0x4B]

//Затем применим функции выше

println (UInt8ArrayToString (UInt8Array: myArray))

Ответ 12

Вам нужно сначала преобразовать массив Int8 в Data, а затем преобразовать в String.

Это мое решение:

    var buffer = [Int8](repeating: 0, count: 100)
    let data = Data(bytes: buffer as [Int8], count: buffer.count);
    return String( data: data, encoding: .utf8)

Ответ 13

Swift 4/Ubuntu 16.04

let serverAns = [UInt8](repeating: 0x50, count: 100)
let readBytes = 8
let truncatedServerAns = serverAns[0..<readBytes]
let tsaData = Data(bytes: truncatedServerAns)
let serverIdStr = String(data: tsaData, encoding: .utf8)
print("serverIdStr=\(String( describing: serverIdStr))")

// Prints:
// serverIdStr=Optional("PPPPPPPP")

Ответ 14

Не все байтовые последовательности [UInt8] представляют строки UTF-8, у вас могут быть разные кодировки или представления, которые, хотя и не являются допустимыми UTF, являются совершенно корректными строками.

В некоторых случаях последовательность байтов может представлять cString, например, в выходных данных из библиотек Crypto, таких как BlueCrypto, или других библиотек, которые обертывают библиотеку CommonCrypto

В этом случае для cStrings есть простое решение

let myString = String (cString: inputBuffer)

'Swifty' array.reduce("", {$ 0 + String (формат: "% c", $ 1)}) также будет работать, но требует большего набора текста.