Свифт Царство.Как положить 3 миллиона объектов в базу данных - PullRequest
0 голосов
/ 02 марта 2019

Я делаю автономное словарное приложение.И теперь я преобразую файл словаря в базу данных области.

Функция преобразования:

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)
        }
     }

Когда я пытаюсь немедленно преобразовать словарь, файл базы данных становится много гигабайт и вылетает в середине

Разделение словаря по частям не вариант, так как в нем около 3 миллионов строк.Это займет очень много ... (сбои плагина области)

Мне нужна помощь о том, как добавить столько значений в базу данных с нашими сбоями.

1 Ответ

0 голосов
/ 02 марта 2019

Проблема в том, что ваш файл имеет большой размер, и в этот момент вы загружаете его в память:

        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)
}

Если у вас есть какие-либо вопросы относительно кода, пожалуйста, спросите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...