What is Data, and how do you convert it to and from text?
Predict first
What does this print?
print(Data("héllo".utf8).count)
- 5
- 6
- 7
Predict first
What does this print?
let bad = Data([0xff])
print(String(data: bad, encoding: .utf8) as Any, String(decoding: bad, as: UTF8.self))
- nil �
- � �
- nil nil
Mental model. Data is a sealed envelope of bytes. Whether it is text, an image or a JSON blob depends on who opens it.
Data is a value type holding a run of bytes, with copy-on-write storage. It is the currency of file, network and crypto APIs. Convert text with Data(string.utf8) and back with String(data:encoding:), which returns an optional (invalid UTF-8 gives nil) or String(decoding:as:), which never fails and substitutes U+FFFD for bad bytes. base64EncodedString() and Data(base64Encoded:) handle Base64.
A Data slice keeps its parent’s indices, exactly like an ArraySlice, so data[2...] starts at index 2. For large files, read with .mappedIfSafe so the file is memory-mapped instead of copied, or stream through a FileHandle.
Five characters, but é is two bytes in UTF-8, so six bytes.
String(data:encoding:) refuses invalid UTF-8 and returns nil. String(decoding:) repairs it with the replacement character.
Common traps
- Using
countof a string as its byte length."héllo".utf8.countis 6 becauseétakes two bytes. - Indexing a
Dataslice from 0. The slice’sstartIndexis not 0.
They might follow up with
- When do you want
[UInt8]instead? For pure in-memory byte work. UseDataat API boundaries. - How do you read a struct from bytes?
withUnsafeBytesandload(as:), with care about alignment.
Related questions
- 2.1.6 What is an ArraySlice, and why does slice[0] crash?
- 2.3.7 How do you read and write files safely, and why is fileExists-then-act a bug?
← Why use URLComponents and URLQueryItem, and what do they still not… Where should an iOS app put files: Documents, Application Support… →