2011-12-23 3 views
2

Mac OS에서 목적 파일 c를 사용하여 블록 당 파일 또는 디렉토리 (파일 및 하위 디렉토리 포함) 블록을 복사하는 좋은 방법이 있습니까?블록 파일 복사 당 블록

+1

달성하려는 목표는 무엇입니까? 왜 블록 단위로 복사하고 싶습니까? 그리고 우리가 말하는 운영 체제는 무엇입니까? 맥 OS? IOS? 다른 것? – Codo

+0

"블록 당 블록"이란 무엇을 의미합니까? –

+0

죄송합니다. 우리는 MacOS에 대해 이야기합니다. 복사 프로세스를 일시 중지 할 수있는 기능이 필요합니다. 그런 다음 각 다음 블록 이후에 플래그를 확인한 다음 일시 중지하거나 일시 중지했다면 다시 시작할 수 있습니다. – Kira

답변

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]; 
} 

디렉토리 내용을 복사하려면 디렉토리의 내용을 열거해야합니다. -[NSFileManager enumeratorAtPath:]으로 NSDirectoryEnumerator의 인스턴스를 만들 수 있습니다.

당신이 열거가 있으면, 당신은 다음 파일을 얻을 nextObject를 호출 속성 : 파일이 디렉토리

  • 경우 파일이 정기적 인 경우, 대상 디렉토리
  • 에 새로운 디렉토리를 생성 파일에서 파일 복사 태스크를 시작하고 완료 핸들러가 호출 될 때까지 대기하십시오.
+0

고마워,하지만 나는 두 가지 질문이있다. 블록 당 파일을 복사하는 것이 좋은 생각입니까? 이 방법으로 파일을 복사하고 예를 들어 FSCopyObjectAsync를 사용하면 복사 속도는 어떻습니까? – Kira

+0

'FSFileOperation'을 사용하는 것이 더 효율적이라고 생각합니다. 작업이 미리 처리되어 시작하는 데 시간이 오래 걸립니다. 그러나 파일을 메모리에 매핑하는 것과 같은 I/O 성능을 향상시키는 최적화를 사용하기도합니다. –

+0

블록 단위로 복사하려는 경우 리소스 포크, 권한, 메타 데이터 등을 잊지 마세요. –

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); 
+0

-_- 정말로 내 질문을 읽었습니까? – Kira

+0

예,했으나 오해했습니다. 나는이 대답에 대해 완전히 부끄럽다. –

+0

나는 그것이 나쁜 질문 구조와 나의 나쁜 영어의 실수라고 생각한다. =) – Kira