app documents目录中的空文件



我的应用程序有一个草稿表视图,显示用户保存的音频文件。对于数据源数组,我循环遍历drafts目录(在NSDocumentDirectory中)。代码运行良好,它显示了到目前为止我保存的所有文件。

问题是,就在最近,除了前两个文件之外的所有文件都是空的。通过空,我的意思是:当我使用NSData的datatWithContentsOfFile方法数据长度为0,即0字节。前两个文件仍然有数据,每个大约267639 b。

但是如果文件中没有数据,为什么当我循环遍历草稿目录时它会出现?这些空文件直到最近都完好无损。是什么导致它们变成空的呢?

下面是循环遍历drafts目录的代码。

// check if drafts folders exist
BOOL draftsFoldersExist = NO;
NSError *error = nil;
NSArray *folders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSArray *appFolderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[folders objectAtIndex:0] error:&error];
if ([appFolderContents count] > 0 && error == nil) {
    for (NSString *item in appFolderContents) {
        if ([item isEqualToString:@"drafts"])
            draftsFoldersExist = YES;
    }
}
_draftsArray = [[NSMutableArray alloc] init];
if (draftsFoldersExist) {
    // drafts data source
    NSString *draftsPath = [NSString stringWithFormat:@"%@/drafts", [folders objectAtIndex:0]];
    NSString *draftsPathEncoded = [draftsPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *draftsPathURL = [NSURL URLWithString:draftsPathEncoded];
    // enumerate files in drafts folders
    NSArray *desiredProperties = @[NSURLIsReadableKey, NSURLCreationDateKey];
    NSArray *drafts = [[NSFileManager defaultManager] contentsOfDirectoryAtURL:draftsPathURL includingPropertiesForKeys:desiredProperties options:0 error:&error];
    for (NSURL *item in drafts) {
        NSMutableDictionary *draftDict = [[NSMutableDictionary alloc] init];
        // name
        NSString *name = [item lastPathComponent];
        // is readable
        NSNumber *isReadableBoolValue = nil;
        [item getResourceValue:&isReadableBoolValue forKey:NSURLIsReadableKey error:&error];
        if ([isReadableBoolValue isEqualToNumber:@YES]) {
            // filename
            [draftDict setValue:[name stringByDeletingPathExtension] forKey:@"draftFilename"];
            // creation date
            NSDate *creationDate = nil;
            [item getResourceValue:&creationDate forKey:NSURLCreationDateKey error:&error];
            [draftDict setValue:creationDate forKey:@"creationDate"];
            // insert into first position of data source array
            _draftsArray = [[@[draftDict] arrayByAddingObjectsFromArray:_draftsArray] mutableCopy];
            // meta
        } else {
            NSLog(@"unreadable item: %@", name);
        }
    }
}
更新:

我按照@Joride的建议通过organizer下载了应用目录的文件,发现所有的文件都完好无损,并且有数据。如下:

2014-08-08_20-53-30.m4a
2014-08-09_19-11-08.m4a
2014-08-10_17-36-28.m4a
2014-08-11_18-53-46.m4a
2014-08-13_12-57-57.m4a
2014-08-16_20-44-33.m4a
2014-08-16_20-45-06.m4a

我想现在的问题是为什么他们中的一些人没有用dataWithContentsOfFile方法显示任何数据。

我使用以下代码初始化NSData对象:
NSData *fileData = [NSData dataWithContentsOfFile:filepath options:NSDataReadingMapped error:&readingError];

对于零数据的文件,读取错误提示"操作无法完成"。

我找到了问题所在。应用程序的文档目录在某个时候发生了变化,所以文件的位置也发生了变化。

文件保存在这里:

/var/mobile/Applications/09E7C349-6D03-4D2F-BE17-46C00B17C9F5/Documents/drafts/2014-08-13_12-57-57.m4a

和后面这里的

/var/mobile/Applications/1A444A31-C29D-4B0F-8B47-A5B57D7F3281/Documents/drafts/2014-08-16_20-45-06.m4a

注意应用的文件夹有一个不同的令牌。所以文件"在那里",但我猜不是在那里。显然,当使用新的配置文件或应用商店更新时,应用程序的目录可能会发生变化(参见此答案)。

所以这个故事的寓意是:不要将绝对路径保存为文件的引用。

好了,我已经写下了我认为你想要达到的目标。注意,在这个例子中,加载文件的代码是在主队列上同步完成的(在某个viewDidAppear:方法中)。对于实际代码来说,这当然是一个非常糟糕的设计,因为它可能会阻塞UI和主队列。但这应该行得通。如果是这样,那么我认为您的代码在url或加载文件时使用的选项方面存在一些问题。如果这段代码也不能工作,则说明有其他原因导致了问题。

给你:

#import "ViewController.h"
NSString * const kDraftsDir = @"drafts";
@interface ViewController ()
@property (nonatomic, readonly) NSMutableArray * drafts;
@end
@implementation ViewController
@synthesize drafts = _drafts;
- (NSMutableArray *) drafts
{
    if (nil == _drafts)
    {
        _drafts = [[NSMutableArray alloc] init];
    }
    return _drafts;
}
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear: animated];
    [self readDrafts];
}
- (void) readDrafts
{
    NSFileManager * fileManager = [[NSFileManager alloc] init];
    NSError * error;
    NSURL * appDocumentDirectoryURL = [fileManager URLForDirectory: NSDocumentDirectory
                                                         inDomain: NSUserDomainMask
                                                appropriateForURL: nil
                                                           create: YES
                                                            error: &error];
    if (nil == appDocumentDirectoryURL)
    {
        NSLog(@"Error getting appDocumentDirectoryURL: %@, %@", error, [error localizedDescription]);
    }
    NSURL * draftsDirectoryURL = [appDocumentDirectoryURL URLByAppendingPathComponent:  kDraftsDir];
    if ([fileManager fileExistsAtPath: draftsDirectoryURL.path isDirectory: NULL])
    {
        // the folder exists, there might be drafts
        NSArray * files = [fileManager contentsOfDirectoryAtURL: draftsDirectoryURL
                                     includingPropertiesForKeys: nil
                                                        options: NSDirectoryEnumerationSkipsHiddenFiles
                                                          error: &error];
        if (nil == files)
        {
            NSLog(@"Error loading drafts from disk: %@, %@", error, [error localizedDescription]);
        }
        else
        {
            for (NSURL * aDraftURL in files)
            {
                // This is just a check for debugging purposes
                NSData * draftData = [NSData dataWithContentsOfURL: aDraftURL];
                if (draftData.length == 0)
                {
                    NSLog(@"WARNING: no file, or zero-size file at URL: %@", aDraftURL);
                }
                NSMutableDictionary * draftDict = [[NSMutableDictionary alloc] init];
                NSString * draftName = [[aDraftURL lastPathComponent]stringByDeletingPathExtension];
                // let's make sure we won't crash because we are inserting nil into a dictionary
                if (nil != draftName)
                {
                    draftDict[@"draftFilename"] = [[aDraftURL lastPathComponent]stringByDeletingPathExtension];
                }
                else
                {
                    NSLog(@"WARNING: no fileName without extension for draft at URL: %@", aDraftURL);
                }

                NSDate * creationDate = nil;
                [aDraftURL getResourceValue: &creationDate forKey:NSURLCreationDateKey error:&error];
                // let's make sure we won't crash because we are inserting nil into a dictionary
                if (nil != creationDate)
                {
                    draftDict[@"creationDate"] = creationDate;
                }
                else
                {
                    NSLog(@"WARNING: no creationdate found for file at URL: %@", aDraftURL);
                }
                // self.drafts will always return a fully initialized NSMutableArray, so we
                // can safely add an object at index 0
                [self.drafts insertObject: draftDict atIndex: 0];
            }
        }
    }
    else
    {
        NSLog(@"The drafts folder does not exist.");
    }
    NSLog(@"%@ stored drafts: %@", @([self.drafts count]), self.drafts);
}
@end

相关内容

最新更新