# 4.3 - Load and Save
As a document-based application, *Money.app* has to be able to load and save files. Otherwise, the user will lose their work when they quit the application.
Depending on the structure of the files, I have several choices to
override in `NSDocument`:
**Table 4-1. Methods for loading and saving files**
|
Load file |
Save file |
Single file |
loadDataRepresentation:ofType: |
dataRepresentationOfType: |
Bundle |
loadFileWrapperRepresentation:ofType: |
fileWrapperRepresentationOfType: |
Low level |
readFromFile:ofType:, readFromURL:ofType: |
writeToFile:ofType:, writeToURL:ofType: |
Read [*How do I implement saving and loading for simple
files?*](https://web.archive.org/web/2004if_/http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Tasks/FAQ.html#//apple_ref/doc/uid/20000954/BAJBFGAG),
[*How do I implement document packages (documents that are really
folders, but appear to be opaque
documents)?*](https://web.archive.org/web/2004if_/http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Tasks/FAQ.html#//apple_ref/doc/uid/20000954/BAJHBHGJ),
and [*How do I implement loading and saving when the simple data or file
wrapper API won't
do?*](https://web.archive.org/web/2004if_/http://developer.apple.com/documentation/Cocoa/Conceptual/Documents/Tasks/FAQ.html#//apple_ref/doc/uid/20000954/BAJIGEFI). (Don't open all the links at once -- they're all on the same FAQ page.)
In this case, `-loadDataRepresentation:ofType:` and
`-dataRepresentationOfType:` are enough.
`Document.m:`
```objc
- (NSData*) dataRepresentationOfType: (NSString*) type
{
if (type == nil) {
type = @"mon";
}
if ([type isEqualToString: @"mon"]) {
return [NSArchiver archivedDataWithRootObject: records];
} else {
return nil;
}
}
- (BOOL) loadDataRepresentation: (NSData*) data ofType: (NSString*) type
{
if ([type isEqualToString: @"mon"]) {
[records setArray: [NSUnarchiver unarchiveObjectWithData: data]];
return YES;
}
return NO;
}
```
When the user saves the document, `Document` will recieve
`-dataRepresentationOfType:`. The type will be the `NSName` of the `NSType` in the property
list of this application (`MoneyInfo.plist`), which is `mon`. Here, we use `NSArchiver` to
transform the whole `NSArray` into `NSData`, and we don't need to worry about
the format of the file. When document is going to be loaded, it will call
`-loadDataRepresentation:ofType:`. We use `NSUnarchiver` to transform
the `NSData` into `NSArray`. That's all. If you are using your own data
structure, you have to deal with [*data
archives*](https://web.archive.org/web/2004if_/http://developer.apple.com/documentation/Cocoa/TasksAndConcepts/ProgrammingTopics/Archiving/index.html)
by yourself.
> Here is a related article: [*Using the Property List
Objects and the NSCoding
Protocol*](http://cocoadevcentral.com/articles/000059.php).
```{note}
If you've ever used Python's `pickle`, `NSArchiver` is similar, but doesn't have the problem that pickles actually contain commands that are executed. `NSArchiver` simply represents the data itself as a binary file, not as a list of commands to piece together the data like `pickle` does.
```
The saved data is in binary format, which is usually undesired. Since we
only use the basic data structure, we could save it into an OpenStep-style property list,
which is human-readable.
`Document.m:`
```objc
- (NSData*) dataRepresentationOfType: (NSString*) type
{
if (type == nil) {
type = @"mon";
}
if ([type isEqualToString: @"mon"]) {
return [[records description]
dataUsingEncoding: [NSString defaultCStringEncoding]];
} else {
return nil;
}
}
- (BOOL) loadDataRepresentation: (NSData*) data ofType: (NSString*) type
{
if ([type isEqualToString: @"mon"]) {
NSString *string = [[NSString alloc]
initWithData: data
encoding: [NSString defaultCStringEncoding]];
[records setArray: [string propertyList]];
RELEASE(string);
return YES;
}
return NO;
}
```
I use -description to get the property list, which is NSString. Then use
-dataUsingEncoding to transform property list (NSString) into NSData for
saving. And do the opposite for the loading. Now, you can look at the
saved file, which is very easy to read.
> Here is the source code for the easy-read version:
[LoadSave-src.tar.gz](http://gnustep.made-it.com/GSPT/LoadSave/LoadSave-src.tar.gz).
```{note}
On macOS, this will save as an XML or binary property list, since macOS no longer uses OpenStep-style property lists.
```
If you are saving the document into a directory, such as if your app saves rich text documents with images, you may want to use
`-loadFileWrapperRepresentation:ofType:` and
`-fileWrapperRepresentationOfType:`. The methods `-readFromFile:ofType:` and
`-writeToFile:ofType:` offer the ability to access the file system
directly.
------------------------------------------------------------------------