2017-09-25 60 views

回答

0

我已經找到了解決辦法。這個對我有用。歡迎重構我的例子。

extension String { 
    func removingPercentEncoding(using encoding: String.Encoding) -> String { 
     let firstChar = self.first 
     let percentCharacter = Character("%") 

     var encodedPrefix: String.SubSequence? = nil 
     var encodedSuffix = self 
     if firstChar != percentCharacter { 
      if let indexOfFirstPercentChar = index(of: percentCharacter) { 
       encodedPrefix = self[..<indexOfFirstPercentChar] 
       encodedSuffix = String(self[indexOfFirstPercentChar...]) 
      } else { 
       //no % char at all. Nothing encoded 
       return self 
      } 
     } 

     let substrings = encodedSuffix.components(separatedBy: "%") 
     let arr = substrings.map{ substring -> (String) in 
      switch substring.count { 
      case let count where count < 2: 
       return substring 
      case let count where count == 2: 
       let decodedArr = substring.hexa2Bytes 
       let data = Data(decodedArr) 
       if let decodedStr = String(data: data, encoding: encoding) { 
        return decodedStr 
       } 

       return substring 
      default: //>2 
       let thirdSymbolIndex = index(startIndex, offsetBy: 2) 
       let firstTwo = substring[..<thirdSymbolIndex] 
       let furhter = substring[thirdSymbolIndex...] 
       let decodedArr = String(firstTwo).hexa2Bytes 
       let data = Data(decodedArr) 
       if let decodedStr = String(data: data, encoding: encoding) { 
        return decodedStr + furhter 
       } 

       return substring 
      } 
     } 

     let result = arr.joined() 

     return String(encodedPrefix ?? "") + result 
    } 

    var hexa2Bytes: [UInt8] { 
     let hexa = Array(characters) 
     return stride(from: 0, to: characters.count, by: 2).flatMap { UInt8(String(hexa[$0..<$0.advanced(by: 2)]), radix: 16) } 
    } 

} 
0

一個小例子,預計可以使用多字節字符串編碼。

extension UInt8 { 
    //returns 0...15 when '0'...'9', 'A'...'F', 'a'...'f', otherwise returns nil 
    var hexValue: UInt8? { 
     if UInt8(ascii: "0") <= self && self <= UInt8(ascii: "9") { 
      return self - UInt8(ascii: "0") 
     } else if UInt8(ascii: "A") <= self && self <= UInt8(ascii: "F") { 
      return self - UInt8(ascii: "A") + 10 
     } else if UInt8(ascii: "a") <= self && self <= UInt8(ascii: "f") { 
      return self - UInt8(ascii: "a") + 10 
     } else { 
      return nil 
     } 
    } 
} 

extension String { 
    func removingPercentEncoding(using encoding: String.Encoding) -> String? { 
     guard let percentEncodedData = self.data(using: encoding) else {return nil} 
     var byteIterator = percentEncodedData.makeIterator() 
     var percentDecodedData = Data() 
     while let b0 = byteIterator.next() { 
      guard b0 == UInt8(ascii: "%"), let b1 = byteIterator.next() else { 
       //Non percent character 
       percentDecodedData.append(b0) 
       continue 
      } 
      guard let h1 = b1.hexValue, let b2 = byteIterator.next() else { 
       //Keep it as is, when invalid hex-sequece appeared 
       percentDecodedData.append(b0) 
       percentDecodedData.append(b1) 
       continue 
      } 
      guard let h2 = b2.hexValue else { 
       //Keep it as is, when invalid hex-sequece appeared 
       percentDecodedData.append(b0) 
       percentDecodedData.append(b1) 
       percentDecodedData.append(b2) 
       continue 
      } 
      percentDecodedData.append((h1<<4) + h2) 
     } 
     return String(data: percentDecodedData, encoding: encoding) 
    } 
} 

在我看來,你應該考慮非UTF8編碼百分之現在過時,並修補其產生與CP1251百分比編碼字符串的一部分。