Writing Files in Objective-C

Here’s the translation of the Go code example to Objective-C, formatted in Markdown suitable for Hugo:

Writing files in Objective-C follows similar patterns to the ones we saw earlier for reading.

#import <Foundation/Foundation.h>

void check(NSError *error) {
    if (error != nil) {
        @throw [NSException exceptionWithName:NSGenericException
                                       reason:[error localizedDescription]
                                     userInfo:nil];
    }
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // To start, here's how to dump a string (or just bytes) into a file.
        NSString *content = @"hello\nobjective-c\n";
        NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        [data writeToFile:@"/tmp/dat1" options:NSDataWritingAtomic error:&error];
        check(error);

        // For more granular writes, open a file for writing.
        NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/dat2"];
        if (fileHandle == nil) {
            [[NSFileManager defaultManager] createFileAtPath:@"/tmp/dat2" contents:nil attributes:nil];
            fileHandle = [NSFileHandle fileHandleForWritingAtPath:@"/tmp/dat2"];
        }

        // It's good practice to close the file when we're done.
        @try {
            // You can write NSData objects as you'd expect.
            NSData *d2 = [NSData dataWithBytes:(char[]){115, 111, 109, 101, 10} length:5];
            [fileHandle writeData:d2];
            NSLog(@"wrote %lu bytes", (unsigned long)[d2 length]);

            // A string write is also available.
            NSData *writeString = [@"writes\n" dataUsingEncoding:NSUTF8StringEncoding];
            [fileHandle writeData:writeString];
            NSLog(@"wrote %lu bytes", (unsigned long)[writeString length]);

            // Synchronize to flush writes to stable storage.
            [fileHandle synchronizeFile];

            // NSOutputStream provides buffered writers.
            NSOutputStream *outputStream = [[NSOutputStream alloc] initToFileAtPath:@"/tmp/dat2" append:YES];
            [outputStream open];
            NSString *bufferedString = @"buffered\n";
            const uint8_t *rawString = (const uint8_t *)[bufferedString UTF8String];
            NSInteger written = [outputStream write:rawString maxLength:[bufferedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
            NSLog(@"wrote %ld bytes", (long)written);

            // Close the stream to ensure all buffered operations have been applied.
            [outputStream close];
        }
        @finally {
            [fileHandle closeFile];
        }
    }
    return 0;
}

Try running the file-writing code.

$ clang -framework Foundation writing-files.m -o writing-files
$ ./writing-files 
wrote 5 bytes
wrote 7 bytes
wrote 9 bytes

Then check the contents of the written files.

$ cat /tmp/dat1
hello
objective-c
$ cat /tmp/dat2
some
writes
buffered

Next, we’ll look at applying some of the file I/O ideas we’ve just seen to the stdin and stdout streams.