阻止每块文件复制

时间:2011-12-23 11:08:18

标签: objective-c file-copying

是否有一种很好的方法可以在Mac OS中使用目标c复制某个文件或目录(包含文件和子目录)块?

2 个答案:

答案 0 :(得分:2)

您可以通过创建NSInputStreamNSOutputStream并在NSRunLoop中安排每个块来复制每个块的文件。然后,当您从输入流中获取字节时,将它们写入缓冲区,当输出流准备就绪时,将缓冲区的内容复制到其中。

@synthesize numberOfBytesTransferred = _numberOfBytesTransferred;

static const NSUInteger blockSize = 65536; // should be adjusted

- (void)startWithSourcePath:(NSString *)srcPath
            destinationPath:(NSString *)dstPath
          completionHandler:(void (^)(NSUInteger, NSError *))completionHandler
{
    _buffer = malloc(blockSize);
    _numberOfBytesTransferred = _bufferLength = _bufferOffset = 0;
    _completionHandler = [completionHandler copy];
    _srcStream = [[NSInputStream alloc] initWithFileAtPath:srcPath];
    _dstStream = [[NSOutputStream alloc] initToFileAtPath:dstPath append:NO];
    _srcStream.delegate = self;
    _dstStream.delegate = self;
    [_srcStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [_dstStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [_srcStream open];
    [_dstStream open];
}

- (void)processStreams
{    
    if ( _srcStream.hasBytesAvailable && ! _bufferLength )
        _bufferLength = [_srcStream read:_buffer maxLength:blockSize];

    if ( _dstStream.hasSpaceAvailable && _bufferLength ) {
        NSInteger length = [_dstStream write:_buffer + _bufferOffset maxLength:_bufferLength];
        _bufferOffset += length;
        _bufferLength -= length;
    }

    if ( _bufferOffset && !_bufferLength ) {
        [self willChangeValueForKey:@"numberOfBytesTransferred"];
        _numberOfBytesTransferred += _bufferOffset;
        _bufferOffset = 0;
        [self didChangeValueForKey:@"numberOfBytesTransferred"];
    }

    if ( _dstStream.hasSpaceAvailable && NSStreamStatusAtEnd == _srcStream.streamStatus ) {
        [_srcStream close];
        [_dstStream close];
        _completionHandler(_numberOfBytesTransferred, nil);
    }
}

- (void)cancel
{
    [_srcStream close];
    [_dstStream close];
}

- (void)pause
{
    _paused = YES;
}

- (void)resume
{
    _paused = NO;
    [self processStreams];
}

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    if ( NSStreamEventErrorOccurred == eventCode ) {
        [_srcStream close];
        [_dstStream close];
        _completionHandler(_numberOfBytesTransferred, stream.streamError);
        return;
    }

    if ( ! _paused )
        [self processStreams];
}

复制目录的内容需要枚举目录的内容。您可以使用NSDirectoryEnumerator创建-[NSFileManager enumeratorAtPath:]的实例。

获得枚举器后,调用nextObject,然后获取文件属性:

  • 如果文件是目录,则在目标目录中创建新目录
  • 如果文件是常规文件,则启动文件复制任务并等待调用完成处理程序。

答案 1 :(得分:0)

您可以使用-[NSFileManager copyItemAtPath:toPath:error:]复制文件或目录。

NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *srcPath = @"/Users/nicolas/Documents/Xcode projects";
NSString *dstPath = @"/Users/nicolas/Desktop/Backup/Xcode projects";
NSError *error;
if ( ! [fileManager copyItemAtPath:srcPath toPath:dstPath error:&error] )
    NSLog(@"Copy error: %@", error);