Блок за блок копирование файлов - PullRequest
2 голосов
/ 23 декабря 2011

Есть ли хороший способ скопировать некоторый файл или каталог (с файлами и подкаталогами) на блок в Mac OS с целью c?

Ответы [ 2 ]

2 голосов
/ 24 декабря 2011

Вы можете скопировать файл на блоки, создав NSInputStream и NSOutputStream и запланировав их в 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, а затем получаете атрибуты файла:

  • Если файлдиректории, вы создаете новую директорию в директории назначения
  • Если файл является обычным файлом, вы запускаете задачу копирования файла и ждете, пока не будет вызван обработчик завершения.
0 голосов
/ 23 декабря 2011

Вы можете скопировать файл или каталог с помощью -[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);
...