2017-03-08 132 views
0

我有一個二進制值的字符串,例如「010010000110010101111001」。有沒有一種簡單的方法將此字符串轉換爲其ascii表示以獲取(在這種情況下)「嘿」?Swift - 將二進制字符串轉換爲ASCII值

只找到整數其他方式或事物:

let binary = "11001" 
    if let number = Int(binary, radix: 2) { 
     print(number) // Output: 25 
    } 

難道有人知道這個情況良好而有效的解決方案?

+0

我認爲您的解決方案也很簡單。 – javimuu

+0

那不是我的解決方案,我需要一個Ø獲得ascii值不是整數 – Appygix

回答

3

您可能需要將輸入的二進制數字拆分爲8位塊,然後將每個塊轉換爲ASCII字符。我想不出一個超級簡單的方法:

var binaryBits = "010010000110010101111001" 

var index = binaryBits.startIndex 
var result: String = "" 
for _ in 0..<binaryBits.characters.count/8 { 
    let nextIndex = binaryBits.index(index, offsetBy: 8) 
    let charBits = binaryBits[index..<nextIndex] 
    result += String(UnicodeScalar(UInt8(charBits, radix: 2)!)) 
    index = nextIndex 
} 
print(result) //->Hey 
+0

你能幫助扭轉這種情況嗎? – rv7284

+0

@ rv7284,更好地開始你自己的新線程。它可能比編寫評論的代碼稍大一些。 – OOPer

+0

我創建了一個新線程 – rv7284

1

是否基本相同OOPer的解決方案,但他/她是速度更快,具有:-)

func getASCIIString(from binaryString: String) -> String? { 

    guard binaryString.characters.count % 8 == 0 else { 
     return nil 
    } 

    var asciiCharacters = [String]() 
    var asciiString = "" 

    let startIndex = binaryString.startIndex 
    var currentLowerIndex = startIndex 

    while currentLowerIndex < binaryString.endIndex { 

     let currentUpperIndex = binaryString.index(currentLowerIndex, offsetBy: 8) 
     let character = binaryString.substring(with: Range(uncheckedBounds: (lower: currentLowerIndex, upper: currentUpperIndex))) 
     asciiCharacters.append(character) 
     currentLowerIndex = currentUpperIndex 
    } 

    for asciiChar in asciiCharacters { 
     if let number = UInt8(asciiChar, radix: 2) { 
      let character = String(describing: UnicodeScalar(number)) 
      asciiString.append(character) 
     } else { 
      return nil 
     } 
    } 

    return asciiString 
} 

let binaryString = "010010000110010101111001" 

if let asciiString = getASCIIString(from: binaryString) { 
    print(asciiString) // Hey 
} 
6

一個變種更短,更優雅的方法@OOPer's solution將使用有條件綁定while循環和index(_:offsetBy:limitedBy:)爲了迭代8個字符的子字符串,利用當您嘗試提前超過限制時index(_:offsetBy:limitedBy:)返回nil這一事實。

let binaryBits = "010010000110010101111001" 

var result = "" 
var index = binaryBits.startIndex 

while let next = binaryBits.index(index, offsetBy: 8, limitedBy: binaryBits.endIndex) { 
    let asciiCode = UInt8(binaryBits[index..<next], radix: 2)! 
    result.append(Character(UnicodeScalar(asciiCode))) 
    index = next 
} 

print(result) // Hey 

請注意,我們通過Character而不是在中間步驟String去 - 這簡直就是拿那Characteris specially optimised的情況下UTF-8表示適合63個字節,這是事實的優點:這裏的情況。這節省了堆 - 爲每個字符分配一箇中間緩衝區。


純粹是爲了好玩,另一種方法可以是使用sequence(state:next:),以創建每個字符串的開始和結束的指標序列,然後reduce,以所得的人物串連在一起成字符串:

let binaryBits = "010010000110010101111001" 

// returns a lazily evaluated sequence of the start and end indices for each substring 
// of 8 characters. 
let indices = sequence(state: binaryBits.startIndex, next: { 
    index -> (index: String.Index, nextIndex: String.Index)? in 

    let previousIndex = index 

    // Advance the current index – if it didn't go past the limit, then return the 
    // current index along with the advanced index as a new element of the sequence. 
    return binaryBits.characters.formIndex(&index, offsetBy: 8, limitedBy: binaryBits.endIndex) ? (previousIndex, index) : nil 
}) 

// iterate over the indices, concatenating the resultant characters together. 
let result = indices.reduce("") { 
    $0 + String(UnicodeScalar(UInt8(binaryBits[$1.index..<$1.nextIndex], radix: 2)!)) 
} 

print(result) // Hey 

在它的面前,這似乎是要比第一個解決方案效率較低(由於這樣的事實,reduce應該複製在每次迭代的字符串) - 但它出現的編譯器能夠執行一些優化,使其不會比第一個解決方案慢得多。

+0

我是'序列(狀態:下一個)'的真正粉絲,儘管它通常傾向於遭受w.r.t.性能與更「經典」的方法相比。順便說一下,我的投票(或前一個尚未更新)對這個好的答案應該推動你超過999個Swift標記。因此,在金徽章上提前多預備好了! :D – dfri

+0

@dfri是的,如果性能不是問題,我肯定會更頻繁地使用它,它的語法稍微不令人生畏,我通常總是喜歡更「經典」的方法:)並感謝+1: D不幸的是,你錯過了一兩分鐘的第1000分!你得到了第1001個upvote;)期待揮舞着強大的mjölnir:) – Hamish

+1

是的,我也是:) darn,第1000個將是整潔!呃,是的,我刪除的評論有一些混淆w.r.t.事實上,只有銀徽章在你的個人資料中顯示,但我猜這個黃金徽章很快就會出現在那裏:)第一次錘擊將有望使人滿意! – dfri

1

一種不同的方法

let bytes_string: String = "010010000110010101111001" 
var range_count: Int = 0 

let characters_array: [String] = Array(bytes_string.characters).map({ String($0)}) 

var conversion: String = "" 

repeat 
{ 
    let sub_range = characters_array[range_count ..< (range_count + 8)] 
    let sub_string: String = sub_range.reduce("") { $0 + $1 } 

    let character: String = String(UnicodeScalar(UInt8(sub_string, radix: 2)!)) 

    conversion += character 

    range_count += 8 

} while range_count < characters_array.count 

print(conversion) 
相關問題