简体   繁体   English

应用程序文档目录中的空文件

[英]Empty files in app documents directory

My app has a drafts table view that shows audio files the user saved. 我的应用程序有一个草稿表视图,其中显示了用户保存的音频文件。 For the data source array, I loop through the drafts directory (inside NSDocumentDirectory ). 对于数据源数组,我遍历了drafts目录(在NSDocumentDirectory内部)。 The code works fine, and it shows all the files I've saved so far. 该代码工作正常,并且显示了到目前为止我保存的所有文件。

The problem is, just recently, all the files besides the first two are empty. 问题是,就在最近,除了前两个文件以外,所有文件都是空的。 By empty, I mean this: when I use NSData's datatWithContentsOfFile method data length is 0, ie 0 bytes. 空的意思是:当我使用NSData的datatWithContentsOfFile方法时,数据长度为0,即0个字节。 The first two files still have data, around 267639 b each. 前两个文件仍具有数据,每个文件约267639 b。

But if there is no data in the file, why would it appear when I loop through the drafts directory? 但是,如果文件中没有数据,当我在草稿目录中循环浏览时,为什么会出现这些数据? These empty files were intact until just recently. 这些空文件直到最近才完好无损。 What could have caused them to become empty? 是什么原因导致它们变空了?

Below is the code used to loop through the drafts directory. 以下是用于遍历草稿目录的代码。

// 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);
        }
    }
}

UPDATE: 更新:

I downloaded the app directory's files via organizer per @Joride's suggestion and found all of the files intact and with data. 我按照@Joride的建议通过管理器下载了应用程序目录的文件,发现所有文件完整无缺,并带有数据。 Here they are: 他们来了:

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

I guess the question now is why are some of them not showing any data with the dataWithContentsOfFile method. 我想现在的问题是,为什么其中一些不使用dataWithContentsOfFile方法显示任何数据。

I use the following code to init the NSData object: 我使用以下代码初始化NSData对象:

NSData *fileData = [NSData dataWithContentsOfFile:filepath options:NSDataReadingMapped error:&readingError];

For the files that have zero data, the reading error says "The operation couldn't be completed. No such file or directory". 对于数据为零的文件,读取错误为“操作无法完成。没有这样的文件或目录”。

I figured out the problem. 我解决了这个问题。 The app's document directory changed at some point, so the location of the files changed. 该应用程序的文档目录有时已更改,因此文件的位置已更改。

Files were saved here: 文件保存在这里:

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

and later here: 然后在这里:

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

Notice the app's folder has a different token. 请注意,应用程序的文件夹具有不同的令牌。 So the files were "there" but not there I guess. 所以文件是“那里”,但我猜不是。 Apparently an app's directory can change when a new provisioning profile is used or there's an update from the app store (see this answer ). 显然,当使用新的配置文件或应用程序商店有更新时,应用程序的目录可以更改(请参阅此答案 )。

So the moral of the story is: don't save absolute paths as a reference to your file. 因此,故事的寓意是:不要将绝对路径保存为对文件的引用。

Allright, I've written what I think you want to achieve. 好吧,我已经写了我想你要实现的目标。 Note that in this example the code to load the files is done synchronously on the main queue (in some viewDidAppear: method). 请注意,在此示例中,加载文件的代码在主队列上同步完成(在某些viewDidAppear:方法中)。 This is off course a very bad design for real code, as it might block the UI and main queue. 对于实际代码,这当然是一个非常糟糕的设计,因为它可能会阻塞UI和主队列。 But this should work. 但这应该可行。 If it does, then I think your code has some problems with the URLS, or the options you use when loading the files. 如果是这样,那么我认为您的代码在URL或加载文件时使用的选项方面存在一些问题。 If this code also does not work, there is something else causing a problem. 如果此代码也不起作用,则可能是其他原因导致了问题。

Here you go: 干得好:

#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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 管理应用程序的Documents目录中的文件和目录 - Managing files and directories in an app's Documents directory 使用文档目录中的文件名填充TableView-空数组例外 - Populate TableView with names of files in documents directory - exception with empty array 将应用程序文档中的特定目录与文件共享 - Share Specific directory in app's Documents with Files app 将iOS应用程序音频文件应用程序存储在xcassets或文档目录中? - Store iOS app audio files app in xcassets or documents directory? 如何在App Sandbox中将文件添加到/ Documents目录 - How do I add files to /Documents directory in App Sandbox 更新应用程序后,文档目录中存储的文件会如何处理? - What happens to files stored in the documents directory when an app is updated? 在Cordova应用程序中播放位于iOS Documents目录中的音频和视频文件 - play audio and video files in Cordova app that reside in iOS Documents directory SwiftUI 2 使用 fileImporter 将文件从 Files 应用程序移动到文档目录 - SwiftUI 2 move file from Files app to documents directory with fileImporter 检查Documents Directory Url是否为空 - Check if Documents Directory Url empty 在NSManagedObject的documents目录中管理文件 - Managing files in the documents directory in NSManagedObject
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM