2015-04-15 20 views
20

Mam do czynienia z problemami podczas konwertowania tablicy UInt8 Byte na ciąg w swift. Szukałem i znajdowałem proste rozwiązanie:Jak przekonwertować tablicę bajtów UInt8 na ciąg w Swift

String.stringWithBytes(buff, encoding: NSUTF8StringEncoding) 

ale pokazuje błąd String.type nie ma członka stringWithBytes. Czy ktoś może zaproponować mi rozwiązanie?

to jest mój kod, gdzie otrzymuję NSData i przekonwertowane na tablicy bajtów, a następnie muszę przekonwertować tablicę bajtów na ciąg znaków.

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) 
+0

http://stackoverflow.com/a/24465772/986169 to może Ci pomóc – giorashc

+0

Lub spróbuj http : //stackoverflow.com/questions/25554986/how-to-convert-string-to-unsafepointeruint8-and-length – emrys57

Odpowiedz

34

Aktualizacja Swift 3/Xcode 8:

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

aktualizacji dla Swift 2/Xcode 7:

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

Poprzednia odpowiedź:

String nie ma metody stringWithBytes(). NSString ma

NSString(bytes: , length: , encoding:) 

metody, które można użyć, ale można utworzyć ciąg bezpośrednio od NSData, bez konieczności stosowania UInt8 tablicy:

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

„MSString (bajtów:, długość: , kodowanie:) "wydaje się nie działać od 26 lipca 2015 roku

Konwertowanie wartości bajtów na ASCII wydaje się problematyczne, jeśli uderzysz w ścianę, możesz to zrobić w sposób następujący (i może Być może brakuje mi czegoś szybkiego, ale nie mogłem znaleźć żadnych rozwiązań w moim czasie.) Będzie to miało dwie funkcje. Pierwsza funkcja akceptuje UInt8 i zamienia ją na reprezentację "\ u {}", która jest następnie zwracana przez funkcję. Po drugie, ustawia się inną funkcję, która przyjmuje jako parametr parametr UInt8, a następnie wypisuje ciąg znaków.

Krok nr 1. Funkcja konwersji każdy bajt do "\ 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}" 

// .. Dodaj do tak wielu bohaterów, jak przewidywać ... nie zapomnij podstawy 16 ..

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

default: characterToReturn = "\u{0}" 

/* .. i wszystko aż do 0xff */

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



    } 

return characterToReturn

}

Krok nr 2 ...Następna funkcja, która trwa w tablicy Uint8 jako parametr następnie zwraca łańcuch ...

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

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

returnString += convertToCharacter(UInt8Bits: eachUInt8Byte)

}

return returnString }

To powinno działać w Swift Playground Dodać tablicę

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

// następnie zastosować funkcje powyżej

println (UInt8ArrayToString (UInt8Array: myArray))

+0

Czy możesz wyjaśnić swoje oświadczenie * "" NSString (bytes:, length:, encoding:) "nie pojawia się działać ... "*? - Sprawdziłem to dwukrotnie za pomocą Xcode 7 beta 5 i nie znalazłem żadnych problemów. –

+0

Mam również problem z tym. Robimy xor z dwóch UInt8s i wydaje się, że wynik Xor zwraca poprawny UInt8, ale NSString (bajty, ...) nie potrafi przekonwertować napisu. Jeśli używam Playground i dopasowuję łańcuchy, które zwracają wynik przed uruchomieniem base16, działa NSString (bajty, ...). – Josh

4

To rozwiązanie działa.

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

Nie bardzo elegancki lub „Swifty”, ale to jest prosty i działa:

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

zmarnowałem godzin szukając łatwy sposób to zrobić, zanim nagle myśl o „printf” z moich dni pisania skryptów Uniksa!

6

Ten pracował dla mnie:

String(bytes: bytes, encoding: NSUTF8StringEncoding) 
3

Martin R w https://stackoverflow.com/a/29644387/2214832 odpowiedział Sunil Kumar na jego problem, ale nie na temat kwestii. Problem nadal występuje, jeśli masz już tablicę bajtów UInt8 i musisz ją przedstawić jako ciąg.

Oto moje rozwiązanie:

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

Używanie tego rozszerzenia można teraz startowych String z Uint8 bajtów tablicy tak:

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

Nie jest to idealne rozwiązanie, ponieważ praktycznie trzeba by dekodować coś w rodzaju zakodowanego tekstu UTF-8. Ale dla danych ASCII działa to zgodnie z oczekiwaniami.Roztwór

7

Swifty

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

Hex przedstawienie:

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

Swift 3: '' 'array.reduce (" ", {0 0 + ciąg (format:"% c ", 1 $)})' '' –

+0

Nieprawidłowe użycie przy 'pomniejszeniu' IMO. Poszedłbym z 'array.map {String (format:"% c ", $ 0)} .joined()' –

0

pełny przykład do szybkiego 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' 
3

Swift 3

dodaje dawał mi błąd z powodu „NSUTF8StringEncoding”:

String(data: nsdata, encoding: NSUTF8StringEncoding)! 

ten pracował dla mnie w szybkim 3:

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

Oto kod bardziej uogólnione do wydobywania ciągi z tablicy bajtów gdzie ciągi zostały zakodowane w 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)! 
    } 
} 

Jest to fragment większej klasy (patrz także https://stackoverflow.com/a/41547936/253938), które użyć do przetwarzania danych odcinkach.

0

Konieczne jest najpierw przekonwertowanie tablicy Int8 na Dane, a następnie przekonwertowanie na ciąg.

To jest moje rozwiązanie:

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

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") 
Powiązane problemy