1
NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL* url = [[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
NSString* directory = [url path];
NSString* filePath = [directory stringByAppendingPathComponent:FILE_NAME];
if ([fileManager fileExistsAtPath:filePath])
{
    [fileManager removeItemAtPath:filePath error:nil];
}   

这是我的代码。执行时,文件被删除,但空间仍然被占用。这是将某些内容存储到文件中的代码。

NSFileManager* fileManager = [NSFileManager defaultManager];
NSURL* url = [[fileManager URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject];
NSString* directory = [url path];
NSString* filePath = [directory stringByAppendingPathComponent:FILE_NAME];
NSArray* oldArray = nil;
if ([fileManager fileExistsAtPath:filePath])
{
    oldArray = [[NSArray alloc] initWithContentsOfFile:filePath];
    [fileManager removeItemAtPath:filePath error:nil];
}
NSMutableArray* mergeArray = [[NSMutableArray alloc] initWithArray:arrayOfPersons];
[mergeArray addObjectsFromArray:oldArray];
if ( [mergeArray writeToFile:filePath atomically:YES]) NSLog(@"Written");

顺便说一句,存储一个只有 1 个对象的数组(一个 NSDictionary 有 2 个键)需要 1 MB。有没有更便宜的存储方式?

4

3 回答 3

2

你需要对你的实验更加小心。unix 文件系统对文件做了很多事情。事实上,当你“删除”一个文件时,你所做的只是将它从文件系统中取消链接。如果该文件使用另一个文件描述符打开,则在操作系统的任何位置,它将保持打开状态。

此外,还有很多优化可以重用文件节点。仅仅因为您删除了一个文件,并不意味着空间会自动返回。它可能出于多种原因在您的应用程序中“保留”,以供其他文件使用。在文件系统需要它之前将其返回给文件系统是没有意义的。

settings->general->usage是对文件系统利用率的非常粗略的衡量。更好的测量方法是直接访问文件和文件系统的属性。

使用您的代码作为基础,请考虑以下事项:

- (NSString*)workingDirectory {
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSURL* url = [[fileManager URLsForDirectory:NSCachesDirectory
                                      inDomains:NSUserDomainMask] lastObject];
    return [url path];
}

- (NSString*)filePath {
    return [[self workingDirectory] stringByAppendingPathComponent:FILE_NAME];
}

现在,您可以看到整个文件系统的所有属性:

NSDictionary *attributes = [[NSFileManager defaultManager]
    attributesOfFileSystemForPath:[self workingDirectory] error:0];
NSLog(@"file system attributes: %@", attributes);

以及带有此特定文件的那些:

NSDictionary *attributes = [[NSFileManager defaultManager]
    attributesOfItemAtPath:[self filePath] error:0];
NSLog(@"file attributes: %@", attributes);

注意NSFileSystemFreeSizeNSFileSize

运行您的应用程序,并转储这两个值。创建您的文件,然后再次转储它们。删除文件,然后再次转储它们。

毕竟NSFileSystemFreeSize,即使在删除之后,您实际上也可能会看到 go UP。请记住,系统本身正在创建临时文件,并且可能正在缓存这些文件系统节点以供将来使用。

如果您退出所有其他应用程序,您可以获得更一致的结果。然后,退出你的(双击电源按钮,X 所有正在运行的应用程序)。在执行此操作之前删除文件。

  1. 现在,在文件不存在的情况下启动您的应用程序。

  2. 转储文件系统数据。

  3. 创建文件。

  4. 转储文件系统数据。

  5. 转储文件数据。

您应该看到文件占用了大约 200-250 字节,并且文件系统可用大小应该下降 8192。

  1. 删除文件。

  2. 转储文件系统数据。可能至少与删除文件之前一样大。

  3. 退出应用程序(不在 XCode 中——双击电源,X 应用程序)。

  4. 运行应用程序。

  5. 转储文件系统数据。您应该看到数据回到您之前开始时的状态。


总而言之,虽然看起来文件系统没有发布数据,但实际上已经发布了,但是您用来查询的工具可能只是不知道文件系统的详细信息。

另请注意,当应用程序运行时,它将使用大量文件系统资源来处理您未明确执行的操作。

我希望这是有道理的...

于 2012-09-08T00:27:54.273 回答
0

您删除文件的代码看起来是正确的,但是当您不需要时,您正在 URL 和路径之间切换。当您尝试删除文件时,您还应该检查错误,以便了解它为什么不起作用。尝试这个:

    NSFileManager   *fileManager    = [NSFileManager defaultManager];
    NSArray         *directoryURLs  = [fileManager URLsForDirectory:NSCachesDirectory 
                                                          inDomains:NSUserDomainMask];
    NSURL           *directoryURL   = [directoryURLs objectAtIndex:0];
    NSURL           *fileURL        = [directoryURL URLByAppendingPathComponent:FILE_NAME];
    if (!fileURL)
    {
        NSLog(@"Could not create URL for file.");
        return;
    }

    NSError *err = nil;
    if (![fileURL checkResourceIsReachableAndReturnError:&err])
    {
        NSLog(@"File is not reachable.\n"
               "Error: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        return;
    }

    err = nil;
    [fileManager removeItemAtURL:fileURL error:&err];
    if (err)
    {
        NSLog(@"Unable to delete existing file.\n"
              "Error: %@ %d %@", [err domain], [err code], [[err userInfo] description]);
        return;
    }
于 2012-07-27T09:23:29.253 回答
0

可能是 ˚FILE_NAME` 的长度大于或等于 300 个字符?前段时间这让我遇到了与 NSFileManager 类似的问题......

于 2012-09-06T16:30:52.303 回答