0
votes

Analyser un fichier texte et le scinder efficacement

Je voudrais analyser un fichier texte qui ressemble plus ou moins à ceci: xxx

si une valeur couvre plusieurs lignes, il a toujours des guillemets. S'il s'agit seulement d'une ligne, il a des guillemets ou non (malheureusement, peu importe si c'est un nombre ou une chaîne - il peut également y avoir une chaîne sans guillemets - le format n'est pas très cohérent)

Et je suis en train de comprendre comment je pourrais les diviser par type et l'analyser efficacement. Je pourrais faire un Readlines et scinder par "=" . Cela fonctionnerait pour tout sauf type3 dans l'exemple ci-dessus, car il s'étend sur plusieurs lignes.

Donc, je pense à lire tout le fichier dans un String et ensuite faire des regex , par exemple (. *) = ("([^"] *) "| * \ n) ce qui aboutirait au premier groupe de capture qui aboutirait toujours le type et le dernier groupe de capture la valeur. Je viens Peurt que pour les fichiers plus importants, cela pourrait être de ralentir et de causer des problèmes.

existe une manière meilleure / plus efficace de résoudre ce problème d'analyse?


0 commentaires

3 Réponses :


1
votes

Je suis venu avec cette lecture directe des lignes. Pas sûr qu'il est plus efficace que de charger le fichier entier et de l'utilisation de regex, mais cela pourrait être utile pour des fichiers énormes car il ne lit qu'une ligne à la fois.

fun readCustomPropertiesFile(file: File): Map<String, String> {
    val map = mutableMapOf<String, String>()
    var entry = ""
    var entryComplete = true
    file.forEachLine { line ->
        if (entryComplete && '=' !in line){
            println("Line is invalid: $line")
            return@forEachLine
        }
        entry = if (entryComplete) line else "$entry\n$line"
        val (key, value) = entry.split('=', limit = 2)
        val startQuote = value.startsWith('"')
        val endQuote = value.endsWith('"')
        entryComplete = !startQuote || startQuote == endQuote
        if (entryComplete) {
            map[key] = if (startQuote && endQuote) value.substring(1, value.length - 1) else value
        }
    }
    return map
}


0 commentaires

1
votes

Votre format est si proche de .properties , avec = et dans un peu de formes différentes propriétés multi-lignes, que j'adapte les données et utilisez les propriétés . L'utilisation de UTF-8 aurait besoin d'une petite adaptation et vous avez terminé: Qualité de la production.


0 commentaires

0
votes

Je pense que votre idée de lire le fichier dans une chaîne puis d'appliquer une regex fonctionnerait bien. Quelques points:

Vous n'avez pas besoin (et probablement pas envie) le \ n dans le motif.

  • Vous voulez probablement seulement 123 comme valeur de type1 , pas 123 \ n . .
  • . ne correspond pas \ n , donc . * arrête de correspondre si / quand il frappe un \ n Quoi qu'il en soit.
  • et s'il arrive que le fichier se termine sans nouvelle ligne, le modèle - \ n ne correspondra pas à la correspondance, mais le modèle - sans réussira.

    S'il est possible qu'une valeur de chaîne puisse contenir un = , alors (. *) = ne va pas fonctionner. Par exemple, si une ligne est type2 = "certains = texte" , alors le (. *) correspondra type2 = "Quelques , que vous Vraisemblablement, je ne veux pas. Vous pouvez résoudre ce problème en utilisant ([^ =] *) = ou peut-être (\ w *) = , en fonction des détails du format .


0 commentaires