Iphone 如何确定调用MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:时所需的时间:
在将文件从一个位置移动到另一个位置或替换文件时,我总是使用NSFileManager中的MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:方法 调用这些方法时,我想确定需要多少时间,这样我就可以使用NSProgressIndicator告诉用户需要多长时间。就像使用OSX移动文件一样,它会告诉您还有多少时间 我看了苹果的文档,但是找不到任何关于这个的信息。Iphone 如何确定调用MoveItemAttribute:toURL:或ReplaceItemAttribute:WithItemAttribute:时所需的时间:,iphone,objective-c,xcode,cocoa,nsfilemanager,Iphone,Objective C,Xcode,Cocoa,Nsfilemanager,在将文件从一个位置移动到另一个位置或替换文件时,我总是使用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不太熟悉。感谢您的帮助。