Skip to content

Instantly share code, notes, and snippets.

@echoz
Created May 23, 2012 18:12
Show Gist options
  • Save echoz/2776772 to your computer and use it in GitHub Desktop.
Save echoz/2776772 to your computer and use it in GitHub Desktop.
Simple class that takes an input stream and writes it to a file by streaming. Duh.
//
// LBCStreamWriter.h
// LBCCore
//
// Created by Jeremy Foo on 23/5/12.
// Copyright (c) 2012 BOB FTW PTE LTD. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import <Foundation/Foundation.h>
typedef void (^LBCStreamWriterCompletionHandler)(BOOL hasError, NSError *error);
typedef enum {
LBCStreamWriterOutputFileAlreadyExistsError
} LBCStreamWriterErrorStatus;
extern NSString *const LBCStreamWriterErrorDomain;
@interface LBCStreamWriter : NSObject <NSStreamDelegate>
@property (readonly) NSInputStream *inputStream;
@property (nonatomic, copy) NSURL *outputFileURL;
+(void)stream:(NSInputStream *)input toDestinationFileURL:(NSURL *)url completion:(LBCStreamWriterCompletionHandler)completion;
-(id)initWithInputStream:(NSInputStream *)input destinationFileURL:(NSURL *)url;
-(void)performStreamWithCompletion:(LBCStreamWriterCompletionHandler)completion;
@end
//
// LBCStreamWriter.m
// LBCCore
//
// Created by Jeremy Foo on 23/5/12.
// Copyright (c) 2012 BOB FTW PTE LTD. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
#import "LBCStreamWriter.h"
NSString *const LBCStreamWriterErrorDomain = @"LBCStreamWriterErrorDomain";
@interface LBCStreamWriter (/* Private Method */)
@property (nonatomic, copy) LBCStreamWriterCompletionHandler _completion;
@property (nonatomic, retain) NSOutputStream *_outputStream;
@end
@implementation LBCStreamWriter
@synthesize inputStream = _inputStream, outputFileURL = _outputFileURL;
@synthesize _completion, _outputStream;
#pragma mark - Object Life Cycle
+(void)stream:(NSInputStream *)input toDestinationFileURL:(NSURL *)url completion:(LBCStreamWriterCompletionHandler)completion {
LBCStreamWriter *writer = [[LBCStreamWriter alloc] initWithInputStream:input destinationFileURL:url];
[writer performStreamWithCompletion:completion];
[writer release];
}
-(id)initWithInputStream:(NSInputStream *)input destinationFileURL:(NSURL *)url {
if ((self = [super init])) {
_inputStream = [input retain];
self.outputFileURL = url;
}
return self;
}
-(void)dealloc {
[_inputStream release], _inputStream = nil;
[_outputFileURL release], _outputFileURL = nil;
[_completion release], _completion = nil;
[_outputStream release], _outputStream = nil;
[super dealloc];
}
#pragma mark - Stream Writer
-(void)performStreamWithCompletion:(LBCStreamWriterCompletionHandler)completion {
NSAssert1([_outputFileURL isFileURL], @"Please use a file URL for the destination file", nil);
NSAssert1(_inputStream != nil, @"Input stream must exist for this to even work properly", nil);
if ([[NSFileManager defaultManager] fileExistsAtPath:[_outputFileURL path]]) {
if (completion)
completion(YES, [NSError errorWithDomain:LBCStreamWriterErrorDomain code:LBCStreamWriterOutputFileAlreadyExistsError userInfo:nil]);
return;
}
self._completion = completion;
self.inputStream.delegate = self;
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
self._outputStream = [NSOutputStream outputStreamToFileAtPath:[self.outputFileURL path] append:NO];
[self._outputStream open];
[self retain];
}
#pragma mark - NSStreamDelegate
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {
if (aStream == self.inputStream) {
uint8_t buf[1024*100];
NSUInteger len = 0;
switch(eventCode) {
case NSStreamEventOpenCompleted:
// Media file open
break;
case NSStreamEventHasBytesAvailable:
len = [self.inputStream read:buf maxLength:1024];
if (len) {
[self._outputStream write:buf maxLength:len];
} else {
if (_completion)
_completion(NO, nil);
[self release];
}
break;
case NSStreamEventErrorOccurred:
if (_completion)
_completion(YES, [aStream streamError]);
[self release];
break;
default:
// Unhandled Stream event
break;
}
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment