This article contains code examples of common tasks that apply to both immutable and mutable data objects, NSData
and NSMutableData
objects. Because of the nature of class clusters in Foundation, data objects are not actual instances of the NSData
or NSMutableData
classes but instead are instances of one of their private subclasses. Although a data object’s class is private, its interface is public, as declared by these abstract superclasses, NSData
and NSMutableData
.
Creating Data Objects From Raw Bytes
Creating Data Objects From Files or URLs
Accessing and Comparing Bytes
Copying Data Objects
Saving Data Objects
Generally, you create a data object from raw bytes using one of the data...
class messages to either the NSData
or NSMutableData
class object. These methods return a data object containing the bytes you specify.
Typically, the creation methods (such as dataWithBytes:length:
) make a copy of the bytes you pass as an argument. In this case, the copied bytes are owned by the data object and are freed when the data object is released. It is your responsibility to free the original bytes.
However, if you create an NSData
object with one of the methods whose name includes NoCopy
(such as dataWithBytesNoCopy:length:
), the bytes are not copied. Instead, the data object takes ownership of the bytes passed in as an argument and frees them when the object is released. (NSMutableData
responds to these methods, too, but the bytes are copied anyway and the buffer is freed immediately.) For this reason, the bytes you pass to the NoCopy
methods must have been allocated using malloc
.
If you prefer that the bytes not be copied or freed when the object is released, you can use the dataWithBytesNoCopy:length:freeWhenDone:
or initWithBytesNoCopy:length:freeWhenDone:
methods passing NO
as the freeWhenDone:
argument.
In Mac OS X v10.1 and earlier, use the CFData
bridged Core Foundation opaque type as follows. Because data objects are bridged, you can create a no-copy, no-free CFData
object and use it anywhere NSData
can be used. You create a no-copy, no-free data object by using the CFDataCreateWithBytesNoCopy
function and requesting kCFAllocatorNull
as the deallocator:
NSData *data = (NSData *)CFDataCreateWithBytesNoCopy( |
NULL, bytes, length, kCFAllocatorNull); |
You use the dataWithContentsOfFile:
or dataWithContentsOfURL:
class methods to create a data object containing the contents of a file or URL. The following code example creates a data object, myData
, initialized with the contents of myFile.txt
. The path must be absolute.
NSString *thePath = @"/u/smith/myFile.txt"; |
NSData *myData = [NSData dataWithContentsOfFile:thePath]; |
The two NSData
primitive methods—bytes
and length
—provide the basis for all other methods in the class. The bytes
method returns a pointer to the bytes contained in the data object. The length
method returns the number of bytes contained in the data object.
NSData
provides access methods for copying bytes from a data object into a specified buffer. The getBytes:
method copies all of the bytes into a buffer. For example, the following code fragment initializes a data object, myData
, with the string myString
. It then uses getBytes:
to copy the contents of myData
into aBuffer
.
unsigned char aBuffer[20]; |
NSString *myString = @"Test string."; |
const char *utfString = [myString UTF8String]; |
NSData *myData = [NSData dataWithBytes: utfString length: strlen(utfString)]; |
[myData getBytes:aBuffer]; |
If you use getBytes:
, you must ensure that the buffer is large enough to contain the data—the buffer must be at least as large as the length
of the data object. The getBytes:length:
method copies bytes into a buffer of a given length. The getBytes:range:
method copies a range of bytes from a starting point within the bytes themselves.
To extract a data object that contains a subset of the bytes in another data object, use the subdataWithRange:
method. For example, the following code fragment initializes a data object, data2
, to contain a subrange of data1
:
NSString *myString = @"ABCDEFG"; |
const char *utfString = [myString UTF8String]; |
NSRange range = {2, 4}; |
NSData *data1, *data2; |
data1 = [NSData dataWithBytes:utfString length:strlen(utfString)]; |
data2 = [data1 subdataWithRange:range]; |
To determine if two data objects are equal, use the isEqualToData:
method, which does a byte-for-byte comparison.
You can copy data objects to create a read-only copy or to create a mutable copy. NSData
and NSMutableData
adopt the NSCopying
and NSMutableCopying
protocols, making it convenient to convert between efficient, read-only data objects and mutable data objects. You use copy
to create a read-only copy, and mutableCopy
to create a mutable copy.
You can save data objects to a local file or to the internet. The writeToFile:atomically:
method lets you write the contents of a data object to a local file. The writeToURL:atomically:
method lets you write the contents of a data object to a location on the Internet.
© 2003, 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-05-06)