如何获取核心数据存储中存在的数据大小?

时间:2014-06-12 07:28:23

标签: ios xcode core-data

如何获取核心数据存储中存在的数据的总内存大小(以字节为单位)。如何获取特定数据行的内存大小。

3 个答案:

答案 0 :(得分:6)

在iOS 7及更高版本上,由于SQLite日志文件,older answers不再适用于SQLite支持的持久存储。对于每个持久性存储文件,您需要获取SQLite文件本身的大小(例如Foo.sqlite日志文件的大小(例如Foo.sqlite-wal和{{1} })并添加大小以获得总数。这非常重要,因为很可能大部分数据实际上都在日志文件中。您可以使用Foo.sqlite-shm获取每个文件的此信息。

如果您在模型中使用二进制属性,则为任何这些属性启用了“允许外部存储”,它会变得更加复杂。在这种情况下,您需要找到所有外部存储文件并添加其大小。它们的位置没有记录,但应该位于找到SQLite文件的目录的子目录中。对于名为NSFileManager的SQLite文件,查找名为Foo.sqlite的目录,外部二进制文件将在那里。 由于没有记录,因此可能会在没有警告的情况下进行更改。

更好的方法 - 如果不是太晚 - 就是将持久性存储放在它自己的子目录中。不要将其放在文档目录中,而是在文档中创建一个新目录并将SQLite文件放在那里。也就是说,创建一个名为.Foo_SUPPORT/_EXTERNAL_DATA的目录,并将data放入其中。要添加大小,只需递归扫描Foo.sqlite中的每个文件并添加大小。然后你会抓住所有东西,即使日记或外部二进制文件或iOS未来版本中的任何变化。使用data的{​​{1}}或NSFileManager方法进行扫描的好方法。

查找特定数据行的内存大小是一个非常不同的问题,并且没有通用的解决方案。任何对象实例的开销,加上您的属性,以及任何内部未记录的对象enumeratorAtPath:可能会创建(包括实例变量和动态分配的内存)。它甚至不是固定值,因为可以动态分配和释放数据。只添加属性的大小很容易 - 只需运行它们并加上每个的大小(字符串长度,数据长度等),但这不是完整的图片。

答案 1 :(得分:2)

使用Swift 5,我想出了这个答案。它不仅获取存储和文件的大小,而且使用Apples ByteCountFormatter格式化数据大小。

public func getSqliteStoreSize(forPersistentContainerUrl storeUrl: URL) -> String {
    do {
        let size = try Data(contentsOf: storeUrl)
        if size.count < 1 {
            print("Size could not be determined.")
            return ""
        }
        let bcf = ByteCountFormatter()
        bcf.allowedUnits = [.useMB] // optional: restricts the units to MB only
        bcf.countStyle = .file
        let string = bcf.string(fromByteCount: Int64(size.count))
        print(string)
        return string
    } catch {
        print("Failed to get size of store: \(error)")
        return ""
    }
}

使用非常简单:

// Get Core Data storage size:
guard let storeUrl = self.managedObjectContext!.persistentStoreCoordinator!.persistentStores.first?.url else {
    print("There is no store url")
    return
}
print("The size of the store is: \(self.getSqliteStoreSize(forPersistentContainerUrl: storeUrl))")

此处的一个次要细节是确保您检查mocpersistentStoreCoordinator确实具有价值-就我而言,由于我是如何初始化它们的,所以我知道它们确实具有价值。

关于以上考虑了walshm文件的答案,您可以通过在URL后面附加一个字符串来检查这些文件:

let newFileName = storeUrl.absoluteString.appending("\("-wal")")
let newFileName2 = storeUrl.absoluteString.appending("\("-shm")")
print("The size of the wal is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName)!))")
print("The size of the shm is: \(self.getSqliteStoreSize(forPersistentContainerUrl: URL(string: newFileName2)!))")

答案 2 :(得分:1)

- (void)reportFileSizeOfPersistentStores
{
    NSArray *allStores = self.persistentStoreCoordinator.persistentStores;
    NSFileManager *fileManager = [NSFileManager defaultManager];

    for (NSPersistentStore *store in allStores)
    {
        NSString *filePath = store.URL.path;
        NSDictionary *attributes = [fileManager attributesOfItemAtPath:filePath
                                                                 error:nil];

        NSString *fileSize = attributes[NSFileSize];

        NSLog(@"FileSize:%@", fileSize);
    }
}