[英]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.