如何获得coredata商店中存在的数据大小?

Dee*_*pak 8 xcode core-data ios

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

Tom*_*ton 6

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

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

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

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


App*_*Guy 5

使用 Swift 5,我想出了这个答案。它不仅获取存储和文件的大小,还使用 ​​Apple 的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 ""
    }
}
Run Code Online (Sandbox Code Playgroud)

使用方法非常简单:

// 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))")
Run Code Online (Sandbox Code Playgroud)

这里的一个小细节是确保您检查您的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)!))")
Run Code Online (Sandbox Code Playgroud)


Zel*_*lko 0

- (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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这将丢失 SQLite 日志文件,这意味着结果将严重不准确。日志文件通常包含 iOS 7 及更高版本上的几乎所有实际数据。 (3认同)