I need to change
This (string):
"0xab,0xcd,0x00,0x01,0xff,0xff,0xab,0xcd,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"
to (bytes)
[0xab,0xcd,0x00,0x01,0xff,0xff,0xab,0xcd,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ]
using swift
One option is to remove the 0x from each string, then split the remaining comma separated values into an array. Finally, use flatMap to convert each hex string into a number.
// Your original string
let hexString = "0xab,0xcd,0x00,0x01,0xff,0xff,0xab,0xcd,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00"
// Remove all of the "0x"
let cleanString = hexString.replacingOccurrences(of: "0x", with: "")
// Create an array of hex strings
let hexStrings = cleanString.components(separatedBy: ",")
// Convert the array of hex strings into bytes (UInt8)
let bytes = hexStrings.flatMap { UInt8($0, radix: 16) }
I used flatMap in case there are any values that aren't valid hex byte values.
Related
Trying to find the shortest / most compact way to write out ASCII characters in Swift into a single string. For example, in JavaScript you can do '\x00' for the decimal equivalent of 0 in ASCII, or you can write '\0, which is 2 characters shorter. So if you have a lot of these characters, that is 2x smaller file size.
Wondering how to write the ASCII characters 0-31 and 127 in Swift so they are minimal, into a single string. In JavaScript, that sort of looks like this:
'\0...\33abcdef...\127¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½...'
In general, you would use \u{x} where x is the hex value. In your case \u{0} through \u{1f} and \u{7f}.
As in C based languages, Swift strings also supports \0 for "null", \t for "tab", \n for "newline", and \r for "carriage return". Unlike C, Swift does not support \b or \f.
If you want to create single String will all 128 ASCII characters then you can do:
let ascii = String(Array(0...127).map { Character(Unicode.Scalar($0)) })
If you have a lot of these characters, maybe put them in a Data object and then convert it to a string:
let data = Data(bytes: Array(0...31) + [127])
let text = String(data: data, encoding: .utf8)!
Based on your comment, you could do:
let tab = Data(bytes: [9])
let null = Data(bytes: [0])
let data = "abc".data(using: .utf8)! + tab + null + "morechars".data(using: .utf8)! + tab
I have code as below after converting to hex value trying to appending data object but it gives me the below error:
Unexpectedly found nil while unwrapping an Optional value
let n = 585
let result = 255 - n % 256 //182 is result
let hexValue = String(result, radix: 16) //b6 is result
var returnMsg = "[1,1,1, ,#00300".data(using: .utf8) as! Data
returnMsg.append(UInt8(hexValue)!)
Here I am trying to add b6 to data object.
Your use of a string to get result as a hex string is of no use just to append to returnMsg. Simply append the result.
let n = 585
let result = 255 - n % 256 //182 is result
var returnMsg = "[1,1,1, ,#00300".data(using: .utf8)!
returnMsg.append(UInt8(result))
Your crash is resulting from force-unwrapping UInt8(hexValue). Passing in the string b6 gives a nil result and the force-unwrap of nil always results in a crash and the error message you are seeing. The UInt8 initializer that takes a string only accepts a base-10 integer. You can see this in the documentation:
The string passed as description may begin with a plus or minus sign character (+ or -), followed by one or more numeric digits (0-9).
If description is in an invalid format, or if the value it denotes in base 10 is not representable, the result is nil.
I was wondering what is the best way for converting an UTF8 Array or String to its base 2 representation(each UTF8 value of each character to its base 2 representation) . Since you could have two values representing the code for the same character, I suppose extracting values from the array and then converting it is not a valid method. So which one is? Thank you!
Here is a possible approach:
Enumerate the unicode scalars of the string.
Convert each unicode scalar back to a string, and enumerate its
UTF-8 encoding.
Convert each UTF-8 byte to a "binary string".
The last task can be done with the following generic method which
works for all unsigned integer types:
extension UnsignedIntegerType {
func toBinaryString() -> String {
let s = String(self, radix: 2)
let numBits = 8 * sizeofValue(self)
return String(count: numBits - s.characters.count, repeatedValue: Character("0")) + s
}
}
// Example:
// UInt8(100).toBinaryString() = "01100100"
// UInt16.max.toBinaryString() = "1111111111111111"
Then the conversion to a UTF-8 binary representation can be
implemented like this:
func binaryUTF8Strings(string: String) -> [String] {
return string.unicodeScalars.map {
String($0).utf8.map { $0.toBinaryString() }.joinWithSeparator(" ")
}
}
Example usage:
for u in base2UTF8("H€llö 🇩🇪") {
print(u)
}
Output:
01001000
11100010 10000010 10101100
01101100
01101100
11000011 10110110
00100000
11110000 10011111 10000111 10101001
11110000 10011111 10000111 10101010
Note that "🇩🇪" is a single character (an "extended grapheme cluster")
but two unicode scalars.
How is it possible to endIndex and count of a String be different in swift2? its the code sample that I've used.it's not happen when all characters are english only.
print("count:",self.Label.text!.characters.count)
print("endIndex:",self.Label.text!.characters.endIndex)
print("String:",self.Label.text!)
output :
count: 32
endIndex: 34
String: • (دستور زبان) مفعولبه، مفعولعنه
The raw value of String.CharacterView.Index is irrelevant and should not be used. Its raw value only has meaning from within String and CharacterView.
In your case, some Unicode characters are merely combining characters that modify adjacent characters to form a single grapheme. For example, U+0300, Combining Grave Accent:
let str = "i\u{0300}o\u{0300}e\u{0300}"
print("String:",str)
print("count:",str.characters.count)
print("endIndex:",str.characters.endIndex)
var i = str.characters.startIndex
while i < str.characters.endIndex
{
print("\(i):\(str.characters[i])")
i = i.successor()
}
results in
String: ìòè
count: 3
endIndex: 6
0:ì
2:ò
4:è
Like some other emoji characters, the 0x0001F1E9 0x0001F1EA combination (German flag) is represented as a single character on screen although it is really two different Unicode character points combined. Is it represented as one or two different characters in Swift?
let flag = "\u{1f1e9}\u{1f1ea}"
then flag is 🇩🇪 .
For more regional indicator symbols, see:
http://en.wikipedia.org/wiki/Regional_Indicator_Symbol
Support for "extended grapheme clusters" has been added to Swift in the meantime.
Iterating over the characters of a string produces a single character for
the "flags":
let string = "Hi🇩🇪!"
for char in string.characters {
print(char)
}
Output:
H
i
🇩🇪
!
Swift 3 implements Unicode in its String struct. In Unicode, all flags are pairs of Regional Indicator Symbols. So, 🇩🇪 is actually 🇩 followed by 🇪 (try copying the two and pasting them next to eachother!).
When two or more Regional Indicator Symbols are placed next to eachother, they form an "Extended Grapheme Cluster", which means they're treated as one character. This is why "🇪🇺 = 🇫🇷🇪🇸🇩🇪...".characters gives you ["🇪🇺", " ", "=", " ", "🇫🇷🇪🇸🇩🇪", ".", ".", "."].
If you want to see every single Unicode code point (AKA "scalar"), you can use .unicodeScalars, so that "Hi🇩🇪!".unicodeScalars gives you ["H", "i", "🇩", "🇪", "!"]
tl;dr
🇩🇪 is one character (in both Swift and Unicode), which is made up of two code points (AKA scalars). Don't forget these are different! 🙂
See Also
Why are emoji characters like 👩👩👧👦 treated so strangely in Swift strings?
The Swift Programming Language (Swift 3.1) - Strings and Characters - Unicode
With Swift 5, you can iterate over the unicodeScalars property of a flag emoji character in order to print the Unicode scalar values that compose it:
let emoji: Character = "🇮🇹"
for scalar in emoji.unicodeScalars {
print(scalar)
}
/*
prints:
🇮
🇹
*/
If you combine those scalars (that are Regional Indicator Symbols), you get a flag emoji:
let italianFlag = "🇮" + "🇹"
print(italianFlag) // prints: 🇮🇹
print(italianFlag.count) // prints: 1
Each Unicode.Scalar instance also has a property value that you can use in order to display a numeric representation of it:
let emoji: Character = "🇮🇹"
for scalar in emoji.unicodeScalars {
print(scalar.value)
}
/*
prints:
127470
127481
*/
You can create Unicode scalars from those numeric representations then associate them into a string:
let scalar1 = Unicode.Scalar(127470)
let scalar2 = Unicode.Scalar(127481)
let italianFlag = String(scalar1!) + String(scalar2!)
print(italianFlag) // prints: 🇮🇹
print(italianFlag.count) // prints: 1
If needed, you can use Unicode.Scalar's escaped(asASCII:) method in order to display a string representation of the Unicode scalars (using ASCII characters):
let emoji: Character = "🇮🇹"
for scalar in emoji.unicodeScalars {
print(scalar.escaped(asASCII: true))
}
/*
prints:
\u{0001F1EE}
\u{0001F1F9}
*/
let italianFlag = "\u{0001F1EE}\u{0001F1F9}"
print(italianFlag) // prints: 🇮🇹
print(italianFlag.count) // prints: 1
String's init(_:radix:uppercase:) may also be relevant to convert the scalar value to an hexadecimal value:
let emoji: Character = "🇮🇹"
for scalar in emoji.unicodeScalars {
print(String(scalar.value, radix: 16, uppercase: true))
}
/*
prints:
1F1EE
1F1F9
*/
let italianFlag = "\u{1F1EE}\u{1F1F9}"
print(italianFlag) // prints: 🇮🇹
print(italianFlag.count) // prints: 1
Swift doesn't tell you what the internal representation of a String is. You interact with a String as a list of full-size (32-bit) Unicode code points:
for character in "Dog!🐶" {
println(character)
}
// prints D, o, g, !, 🐶
If you want to work with a string as a sequence of UTF-8 or UTF-16 code points, use its utf8 or utf16 properties. See Strings and Characters in the docs.