How to convert UInt8 byte array to string in Swift

ArraysSwift

Arrays Problem Overview


I am facing problems while converting UInt8 Byte array to string in swift. I have searched and find a simple solution

String.stringWithBytes(buff, encoding: NSUTF8StringEncoding)

but it is showing error String.type does not have a member stringWithBytes. Can anyone suggest me a solution ?

this is my code where i am getting an NSData and converted into bytes array and then i have to convert that byte array into string.

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)

Arrays Solutions


Solution 1 - Arrays

Update for Swift 3/Xcode 8:

String from bytes: [UInt8]:

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

String from data: Data:

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

Update for Swift 2/Xcode 7:

String from bytes: [UInt8]:

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

String from data: NSData:

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

Previous answer:

String does not have a stringWithBytes() method. NSString has a

 NSString(bytes: , length: , encoding: )

method which you could use, but you can create the string directly from NSData, without the need for an UInt8 array:

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

Solution 2 - Arrays

Swifty solution

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

Hex representation:

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

Solution 3 - Arrays

Update for Swift 5.2.2:

String(decoding: yourByteArray, as: UTF8.self)

Solution 4 - Arrays

This worked for me:

String(bytes: bytes, encoding: NSUTF8StringEncoding)

Solution 5 - Arrays

This solution works.

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

Solution 6 - Arrays

Swift 3

the following was giving me an error because of "NSUTF8StringEncoding":

String(data: nsdata, encoding: NSUTF8StringEncoding)! 

this worked for me in swift 3:

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

Solution 7 - Arrays

For anyone who cannot transform array of bytes to a String, try this

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

This is my example string extension. I use it for 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)"
        }
    }
}

Solution 8 - Arrays

Martin R in https://stackoverflow.com/a/29644387/2214832 answered Sunil Kumar on his problem but not on the topic question. The problem still appears if you already have UInt8 byte array and need to present it as string.

Here is my solution:

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

Using this extension you can now init String with UInt8 byte array like that:

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

This is not ideal solution because practically you would need to decode something like UTF-8 encoded text. But for ASCII data this works as expected.

Solution 9 - Arrays

Here is some more generalized code for extracting strings from a byte array where the strings have been encoded in 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)!
   }
}

This is an extract from a larger class (see also https://stackoverflow.com/a/41547936/253938 ) which I use to process serialized data.

Solution 10 - Arrays

Not very elegant or 'Swifty', but this is simple and it works:

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

I wasted hours searching for an easy way to do this, before I suddenly thought of 'printf' from my Unix scripting days!

Solution 11 - Arrays

Complete example for 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'

Solution 12 - Arrays

"MSString(bytes: , length: , encoding: )" does not appear to be working as of July 26th, 2015

Converting byte values to ASCII seems problematic, if you have hit a wall you can do it the hard way as follows (and maybe I am missing something with swift but I couldn't find any solutions within my timeframe.) This will be done with two functions. The first function accepts a UInt8 and converts that to a "\u{}" representation, which is then returned by the function. Second, another function is set up which takes in a UInt8 array as a parameter, then outputs a string.

Step #1. Function convert each byte to "\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}"

//.. Add for as many characters as you anticipate...don't forget base 16..

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

default: characterToReturn = "\u{0}"

/*.. and all the way up to 0xff */

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



  }

return characterToReturn

}

Step #2 ...Next a function which takes in a UInt8 array as a parameter then returns a string...

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

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

returnString += convertToCharacter(UInt8Bits: eachUInt8Byte)

}

return returnString }

This should work in a Swift Playground Make an array

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

//Then apply the functions above

println(UInt8ArrayToString(UInt8Array: myArray))

Solution 13 - Arrays

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

Solution 14 - Arrays

You need convert Int8 array to Data firstly, then convert to String.

This is my solution:

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSunil KumarView Question on Stackoverflow
Solution 1 - ArraysMartin RView Answer on Stackoverflow
Solution 2 - ArraysMarek HView Answer on Stackoverflow
Solution 3 - Arrays0xFView Answer on Stackoverflow
Solution 4 - Arraysdavid72View Answer on Stackoverflow
Solution 5 - Arraysniklas30View Answer on Stackoverflow
Solution 6 - ArraysLeftyTView Answer on Stackoverflow
Solution 7 - ArraysKhemmachart ChutapetchView Answer on Stackoverflow
Solution 8 - ArraysACHTUNGView Answer on Stackoverflow
Solution 9 - ArraysRenniePetView Answer on Stackoverflow
Solution 10 - ArraysSimon YouensView Answer on Stackoverflow
Solution 11 - ArraysLightbeardView Answer on Stackoverflow
Solution 12 - ArraysRobertHanaView Answer on Stackoverflow
Solution 13 - ArraysPJ_FinneganView Answer on Stackoverflow
Solution 14 - ArraysQi WangView Answer on Stackoverflow