Reputation: 831
After sending a HTTP request from Swift, I get a field in the response called textEncodingName
.
I want to convert the data
object I also received into a string containing its contents, and to do this, I'm using String(data: data!, encoding: .utf8)
. This works most of the time, because most websites are UTF-8 encoded. But with, for example, https://www.google.co.uk
, the response.textEncodingName == "iso-8859-1"
.
I guess other websites would use even more obscure encodings, so my question is this: how can I find the right encoding to convert my data
object to the correct string.
Upvotes: 3
Views: 5410
Reputation: 987
In Swift You can use:
guard let string = String(data: data, encoding: .isoLatin1) else {return}
guard let perfectData = string.data(using: .utf8, allowLossyConversion: true) else {return}
Upvotes: 1
Reputation: 318774
You can simply try String.Encoding.windowsCP1250
for iso-8859-1
. Please refer https://en.wikipedia.org/wiki/Windows-1250
String(data: data, encoding: .windowsCP1250)
OR..
I found a few steps that will take you from the textEncodingName
to the corresponding String.Encoding
value:
let estr = "iso-8859-1"
let cfe = CFStringConvertIANACharSetNameToEncoding(estr as CFString)
let se = CFStringConvertEncodingToNSStringEncoding(cfe)
let encoding = String.Encoding(rawValue: se)
This is largely based on the documentation for URLResponse.textEncodingName
:
You can convert this string to a CFStringEncoding value by calling CFStringConvertIANACharSetNameToEncoding(:). You can subsequently convert that value to an NSStringEncoding value by calling CFStringConvertEncodingToNSStringEncoding(:).
Here's an update that checks to see if the original text encoding string is valid or not:
let estr = "XXX"
let cfe = CFStringConvertIANACharSetNameToEncoding(estr as CFString)
if cfe != kCFStringEncodingInvalidId {
let se = CFStringConvertEncodingToNSStringEncoding(cfe)
let sse = String.Encoding(rawValue: se)
print("sse = \(sse)")
} else {
print("Invalid")
}
Upvotes: 8
Reputation: 1141
In swift you can use:
func getTextFrom(_ url: URL) -> String? {
guard let data = try? Data(contentsOf: url) else {
return nil
}
return String(data: data, encoding: .utf8) ??
String(data: data, encoding: .isoLatin1)
}
Upvotes: 0
Reputation: 64002
I would write an enum with a String
raw value and a computed property to return the appropriate String.Encoding
value. Then you can use its init(rawValue:)
to create an instance.
import Foundation
enum APITextEncoding : String
{
case iso8859_1 = "iso-8859-1"
// etc.
var encoding: String.Encoding
{
switch self
{
case .iso8859_1:
return .isoLatin1
// etc.
}
}
}
let receivedEncoding = APITextEncoding(rawValue: encodingDescription)
let receivedText = String(data: receivedData, encoding: receivedEncoding.encoding)
Upvotes: 1