ios - 迅捷领域。如何将 300 万个对象放入数据库
问题描述
我制作离线词典应用程序。现在我将字典文件转换为领域数据库。
转换功能:
if let path = Bundle.main.path(forResource: "dictionary", ofType: "dsl") {
do {
let data = try String(contentsOfFile: path, encoding: .utf8)
let myStrings = data.components(separatedBy: .newlines)
for (index, row) in myStrings.enumerated() {
if(row.containsChineseCharacters)
{
let firstWord = CNDict()
firstWord.word = row
firstWord.pinyin = myStrings[index+1]
firstWord.translate = myStrings[index+2]
try! realm.write {
realm.add(firstWord)
}
}
}
print("The task end.")
} catch {
print(error)
}
}
当我尝试立即转换字典时,数据库文件变成了很多 GB 并在中间崩溃
将字典分成几部分不是一种选择,因为大约有 300 万行。这将需要很多......(领域插件崩溃)
我需要有关如何在崩溃时向数据库添加尽可能多的值的帮助。
解决方案
问题是您的文件很大,此时您将其加载到内存中:
let data = try String(contentsOfFile: path, encoding: .utf8)
然后在这里将内存占用加倍:
let myStrings = data.components(separatedBy: .newlines)
所以我的猜测是你从系统收到了内存不足的信号。
lazy
您可以使用collection ,而不是将所有数据加载到内存中并将其加倍。它只会在需要写入时读取和解析该行。它不会一次加载所有行。Swift 中惰性集合的一个缺点是它们无法提供我们习惯的所有功能。
这是解决您问题的游乐场的完整代码。您可以并且也许应该优化其中的某些部分,但无论如何它只是展示了如何通过lazy
收集来完成它。(我改变了一些名字,但它仍然是你想要的)。
import Foundation
extension String {
var containsOneSymbol: Bool {
return contains("1")
}
}
extension Character {
var isNewLine: Bool {
let string = String(self)
let set = CharacterSet(charactersIn: string)
return !set.isDisjoint(with: CharacterSet.newlines)
}
}
/// Add Object subclass for Realm
@objcMembers
final class CNDict {
dynamic var word = ""
dynamic var pinyin = ""
dynamic var translate = ""
}
final class ModelWriterWrapper {
private let bufferCapacity = 3
private var buffer: [String] = []
init() {
buffer.reserveCapacity(bufferCapacity)
}
func proccess(line: String) {
guard buffer.count == bufferCapacity else {
assert(buffer.count < bufferCapacity, "Buffer failer count: \(buffer.count)!")
buffer.append(line)
return
}
if let firstLine = buffer.first, firstLine.containsOneSymbol {
let dict = CNDict()
dict.word = firstLine
dict.pinyin = buffer[1]
dict.translate = buffer[2]
print("Ready for writing into DB \n word: \(dict.word) pinyin: \(dict.pinyin) translate: \(dict.translate)")
}
buffer.removeFirst()
buffer.append(line)
}
}
let data = stride(from: 0, to: 100_000, by: 1).map { "Line number \($0)\n"}.joined()
var line: String = ""
let myLines = data.lazy.map { char -> String in
line.append(char)
guard !char.isNewLine else {
defer { line = "" }
return line
}
return ""
}.filter { !$0.isEmpty }
let databaseWritter = ModelWriterWrapper()
myLines.forEach {
databaseWritter.proccess(line: $0)
}
如果对代码有任何疑问,请询问。
推荐阅读
- python - 如何在 Python 中实现这个 R 泊松分布?
- android - 如何在不获取 ResourcesNotFound 的情况下检查 getResources 是否为空
- git - 如何使用私有 fork 或存储库公开我的 dotfiles?
- flutter - 查找已停用小部件的祖先是不安全的
- python - 需要将随机输出转换为字符串
- string - 在go中遍历字符串字符的最正确方法是什么
- python-3.x - 如何刷新或销毁在 tkinter python 的画布中创建的框架?
- angular - Angular 7 LOCALE_ID 使用普通旧对象注入
- iis - VB6 ActiveX DLL 暴露表单 IIS
- python - 除 UserDoesNotExist 中的 Django 标识错误