Iphone 如何确定调用MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:时所需的时间:

Iphone 如何确定调用MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:时所需的时间:,iphone,objective-c,xcode,cocoa,nsfilemanager,Iphone,Objective C,Xcode,Cocoa,Nsfilemanager,在将文件从一个位置移动到另一个位置或替换文件时,我总是使用NSFileManager中的MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:方法 调用这些方法时,我想确定需要多少时间,这样我就可以使用NSProgressIndicator告诉用户需要多长时间。就像使用OSX移动文件一样,它会告诉您还有多少时间 我看了苹果的文档,但是找不到任何关于这个的信息。 想知道这是否可以实现,请告知。您无法提前知道需要多长时间。您可

在将文件从一个位置移动到另一个位置或替换文件时,我总是使用NSFileManager中的MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:方法

调用这些方法时,我想确定需要多少时间,这样我就可以使用NSProgressIndicator告诉用户需要多长时间。就像使用OSX移动文件一样,它会告诉您还有多少时间

我看了苹果的文档,但是找不到任何关于这个的信息。
想知道这是否可以实现,请告知。

您无法提前知道需要多长时间。您可以在复制文件时计算完成百分比。但要做到这一点,您需要使用较低级别的API。您可以使用NSFileManager AttributesFiteMatPath:error获取文件大小和NSStreams以进行复制,有很多方法可以做到这一点。完成百分比为BytesWrite/totalBytesInFile

--编辑:在NSURL上添加示例代码作为一个类别,回调块传递写入的总字节数、percen complete和估计剩余时间(以秒为单位)

#import <mach/mach_time.h>

@interface NSURL(CopyWithProgress)<NSObject>
- (void) copyFileURLToURL:(NSURL*)destURL withProgressBlock:(void(^)(double, double, double))block;
@end

@implementation NSURL(CopyWithProgress)

- (void) copyFileURLToURL:(NSURL*)destURL
        withProgressBlock:(void(^)(double, double, double))block
{
    ///
    // NOTE: error handling has been left out in favor of simplicity
    //       real production code should obviously handle errors.
    NSUInteger fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil].fileSize;

    NSInputStream  *fileInput  = [NSInputStream inputStreamWithURL:self];
    NSOutputStream *copyOutput = [NSOutputStream outputStreamWithURL:destURL append:NO];

    static size_t bufferSize = 4096;
    uint8_t *buffer = malloc(bufferSize);
    size_t   bytesToWrite;
    size_t   bytesWritten;
    size_t   copySize = 0;
    size_t   counter  = 0;

    [fileInput open];
    [copyOutput open];

    uint64_t time0 = mach_absolute_time();

    while (fileInput.hasBytesAvailable) {
        do {
            bytesToWrite = [fileInput read:buffer maxLength:bufferSize];
            bytesWritten = [copyOutput write:buffer maxLength:bytesToWrite];
            bytesToWrite -= bytesWritten;
            copySize     += bytesWritten;
            if (bytesToWrite > 0)
                memmove(buffer, buffer + bytesWritten, bytesToWrite);
        }
        while (bytesToWrite > 0);

        if (block != nil && ++counter % 10 == 0) {
            double percent  = (double)copySize / fileSize;
            uint64_t time1  = mach_absolute_time();
            double elapsed  = (double)(time1 - time0)/NSEC_PER_SEC;
            double estTimeLeft = ((1 - percent) / percent) * elapsed;
            block(copySize, percent, estTimeLeft);
        }
    }

    if (block != nil)
        block(copySize, 1, 0);
}

@end


int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSURL *fileURL = [NSURL URLWithString:@"file:///Users/eric/bin/data/english-words.txt"];
        NSURL *destURL = [NSURL URLWithString:@"file:///Users/eric/Desktop/english-words.txt"];

        [fileURL copyFileURLToURL:destURL withProgressBlock:^(double bytes, double pct, double estSecs) {
            NSLog(@"Bytes=%f, Pct=%f, time left:%f s",bytes,pct,estSecs);
        }];
    }
    return 0;
}

你不可能事先知道要花多长时间。您可以在复制文件时计算完成百分比。但要做到这一点,您需要使用较低级别的API。您可以使用NSFileManager AttributesFiteMatPath:error获取文件大小和NSStreams以进行复制,有很多方法可以做到这一点。完成百分比为BytesWrite/totalBytesInFile

--编辑:在NSURL上添加示例代码作为一个类别,回调块传递写入的总字节数、percen complete和估计剩余时间(以秒为单位)

#import <mach/mach_time.h>

@interface NSURL(CopyWithProgress)<NSObject>
- (void) copyFileURLToURL:(NSURL*)destURL withProgressBlock:(void(^)(double, double, double))block;
@end

@implementation NSURL(CopyWithProgress)

- (void) copyFileURLToURL:(NSURL*)destURL
        withProgressBlock:(void(^)(double, double, double))block
{
    ///
    // NOTE: error handling has been left out in favor of simplicity
    //       real production code should obviously handle errors.
    NSUInteger fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:self.path error:nil].fileSize;

    NSInputStream  *fileInput  = [NSInputStream inputStreamWithURL:self];
    NSOutputStream *copyOutput = [NSOutputStream outputStreamWithURL:destURL append:NO];

    static size_t bufferSize = 4096;
    uint8_t *buffer = malloc(bufferSize);
    size_t   bytesToWrite;
    size_t   bytesWritten;
    size_t   copySize = 0;
    size_t   counter  = 0;

    [fileInput open];
    [copyOutput open];

    uint64_t time0 = mach_absolute_time();

    while (fileInput.hasBytesAvailable) {
        do {
            bytesToWrite = [fileInput read:buffer maxLength:bufferSize];
            bytesWritten = [copyOutput write:buffer maxLength:bytesToWrite];
            bytesToWrite -= bytesWritten;
            copySize     += bytesWritten;
            if (bytesToWrite > 0)
                memmove(buffer, buffer + bytesWritten, bytesToWrite);
        }
        while (bytesToWrite > 0);

        if (block != nil && ++counter % 10 == 0) {
            double percent  = (double)copySize / fileSize;
            uint64_t time1  = mach_absolute_time();
            double elapsed  = (double)(time1 - time0)/NSEC_PER_SEC;
            double estTimeLeft = ((1 - percent) / percent) * elapsed;
            block(copySize, percent, estTimeLeft);
        }
    }

    if (block != nil)
        block(copySize, 1, 0);
}

@end


int main (int argc, const char * argv[])
{
    @autoreleasepool {

        NSURL *fileURL = [NSURL URLWithString:@"file:///Users/eric/bin/data/english-words.txt"];
        NSURL *destURL = [NSURL URLWithString:@"file:///Users/eric/Desktop/english-words.txt"];

        [fileURL copyFileURLToURL:destURL withProgressBlock:^(double bytes, double pct, double estSecs) {
            NSLog(@"Bytes=%f, Pct=%f, time left:%f s",bytes,pct,estSecs);
        }];
    }
    return 0;
}
方法MoveItemAttribute:toURL:和ReplaceItemAttribute:WithItemAttribute:是高级操作。虽然它们提供了移动/替换所需的语义,但正如您所发现的,它们并没有提供您在这些操作期间所希望的反馈

苹果正在改变较低级别的文件处理例程,许多例程现在在10.8中被标记为已弃用,因此您需要仔细选择要使用的。但是,在最低级别,即系统调用手册第2节和库函数手册第3节,您可以使用一些未被弃用的函数

还有一个选项是函数copyfile manual section 3,它将复制文件或文件夹层次结构,并提供进度回调。这将为您提供MoveItemAttribute:toURL:的大部分语义以及进度,但您需要为ReplaceItemAttribute:WithItemAttribute:做更多的工作,以保护安全,在发生错误时不会丢失数据

如果这还不能满足你的所有需求,你还可以查看低级别的统计数据和朋友,以了解文件大小等

HTH

方法MoveItemAttribute:Tour:和ReplaceItemAttribute:WithItemAttribute:是高级操作。虽然它们提供了移动/替换所需的语义,但正如您所发现的,它们并没有提供您在这些操作期间所希望的反馈

苹果正在改变较低级别的文件处理例程,许多例程现在在10.8中被标记为已弃用,因此您需要仔细选择要使用的。但是,在最低级别,即系统调用手册第2节和库函数手册第3节,您可以使用一些未被弃用的函数

还有一个选项是函数copyfile manual section 3,它将复制文件或文件夹层次结构,并提供进度回调。这将为您提供MoveItemAttribute:toURL:的大部分语义以及进度,但您需要为ReplaceItemAttribute:WithItemAttribute:做更多的工作,以保护安全,在发生错误时不会丢失数据

如果这还不能满足你的所有需求,你还可以查看低级别的统计数据和朋友,以了解文件大小等


HTH

我大部分同意CRD。我只想指出,在某些常见情况下,-moveItemAttribute:toURL:和-replaceItemAttribute:WithItemAttribute:。。。你跑得很快。当源和目标位于同一卷上时,不必复制或移动数据,只需复制或移动元数据。当卷是本地卷而不是网络装载卷时,这通常需要的时间可以忽略不计。这就是说,对可能需要花费大量时间的可能性进行规划是适当的

此外,他还提到了移动文件的copyfile例程。在卷之间移动文件时,复制后删除原始文件是必要的方法,但是重命名系统调用将在卷内执行移动,而无需复制任何内容。因此,一个合理的方法是首先尝试重命名,如果EXDEV失败,则返回copyfile

最后,exchangedata系统调用可以用作-replaceItemAttribute:WithItemAttribute:….重新实现的一部分。。。。


我不推荐aLevelOfIndirection建议的方法,因为复制文件有很多繁琐的细节。依赖系统库要比尝试使用自己的库好得多。例如,他的示例完全忽略了文件元数据、文件日期、扩展属性等。

我基本上同意CRD。我只想指出,在某些常见情况下,-moveItemAttribute:toURL:和-replaceItemAttribute:WithItemAttribute:。。。你跑得很快。当源和目标位于同一卷上时,不必复制或移动数据,只需复制或移动元数据。当卷是本地卷而不是网络装载卷时,这通常需要的时间可以忽略不计。这就是说,对可能需要花费大量时间的可能性进行规划是适当的

此外,他还提到了移动文件的copyfile例程。在卷之间移动文件时,复制后删除原始文件是必要的方法,但是重命名系统调用将在卷内执行移动,而无需复制任何内容。因此,一个合理的方法是首先尝试重命名,如果EXDEV失败,则返回copyfile

最后,exchangedata系统调用可以用作-replaceItemAttribute:WithItemAttribute:….重新实现的一部分


我不推荐aLevelOfIndirection建议的方法,因为复制文件有很多繁琐的细节。依赖系统库要比尝试使用自己的库好得多。例如,他的示例完全忽略了文件元数据、文件日期、扩展属性等。

找到pct complete也很好@aLevelOfIndirection能否请您提供一些示例代码,或者请包含一个示例代码链接,说明如何实现这一点。谢谢找到完整的pct也很好@aLevelOfIndirection能否请您提供一些示例代码,或者请包含一个示例代码链接,说明如何实现这一点。感谢有示例代码演示如何使用copyfile、rename0和exchangedata?因为我对c不太熟悉。感谢您的帮助。有没有示例代码来演示如何使用copyfile、rename0和exchangedata?因为我对c不太熟悉。感谢您的帮助。