Java 解析文本文件并有效地拆分它

Java 解析文本文件并有效地拆分它,java,parsing,kotlin,Java,Parsing,Kotlin,我想解析一个大致如下的文本文件: TYPE1=123 TYPE2="SOMETEXT" TYPE3="SOMETEXT_BUT ON_MULTIPLE_ LINES" TYPE4=456 如果一个值跨越多行,它总是有引号。如果它只跨一行,则它要么有引号,要么没有引号(不幸的是,不管它是数字还是字符串——也可能有没有引号的字符串——格式不太一致) 我目前正在研究如何按类型拆分它们,并有效地解析它们。我可以做一个readlines并按“=”进行拆分。这将适用

我想解析一个大致如下的文本文件:

TYPE1=123
TYPE2="SOMETEXT"
TYPE3="SOMETEXT_BUT
ON_MULTIPLE_
LINES"
TYPE4=456
如果一个值跨越多行,它总是有引号。如果它只跨一行,则它要么有引号,要么没有引号(不幸的是,不管它是数字还是字符串——也可能有没有引号的字符串——格式不太一致)

我目前正在研究如何按类型拆分它们,并有效地解析它们。我可以做一个
readlines
并按
“=”
进行拆分。这将适用于除上述示例中的
TYPE3
之外的所有内容,因为它跨越多行

因此,我正在考虑将整个文件读入一个
字符串
,然后执行一些
正则表达式
,例如
(.*)=(“([^”]*)”|.*\n)
,这将导致第一个捕获组始终使用类型,最后一个捕获组使用值。我只是担心对于较大的文件,这可能会减慢速度并导致问题


有没有更好/更有效的方法来解决这个解析问题?

我提出了一种直接读取行的方法。不确定它是否比加载整个文件并使用正则表达式更有效,但它可能对大型文件有用,因为它一次只读取一行

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
}
fun readCustomPropertiesFile(file:file):映射{
val map=mutableMapOf()
var entry=“”
var entryComplete=true
file.forEachLine{line->
if(entryComplete&&'='!行中){
println(“行无效:$Line”)
return@forEachLine
}
entry=if(entryComplete)行else“$entry\n$line”
val(键,值)=条目。拆分('=',限制=2)
val startQuote=value.startsWith(“”)
val endQuote=value.endsWith(“”)
entryComplete=!startQuote | | startQuote==endQuote
if(entryComplete){
map[key]=if(startQuote&&endQuote)值。子字符串(1,value.length-1)else值
}
}
返回图
}

我提出了一种直截了当的行读取方法。不确定它是否比加载整个文件并使用正则表达式更有效,但它对于大型文件可能有用,因为它一次只能读取一行

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
}
fun readCustomPropertiesFile(file:file):映射{
val map=mutableMapOf()
var entry=“”
var entryComplete=true
file.forEachLine{line->
if(entryComplete&&'='!行中){
println(“行无效:$Line”)
return@forEachLine
}
entry=if(entryComplete)行else“$entry\n$line”
val(键,值)=条目。拆分('=',限制=2)
val startQuote=value.startsWith(“”)
val endQuote=value.endsWith(“”)
entryComplete=!startQuote | | startQuote==endQuote
if(entryComplete){
map[key]=if(startQuote&&endQuote)值。子字符串(1,value.length-1)else值
}
}
返回图
}

您的格式非常接近,具有
=
和一点不同的多行属性形式,因此我将调整数据,并使用
属性
。使用UTF-8将需要一个小的调整,您完成了:生产质量。

您的格式非常接近,具有
=/code>和一点不同的多行属性形式使用UTF-8需要进行一些小的调整,您已经完成了:生产质量。

我认为您将文件读入字符串,然后应用正则表达式的想法会很好。以下几点:

您不需要(也可能不想要)模式中的
\n

  • 您可能只希望
    123
    作为
    TYPE1
    的值,而不是
    123\n
  • \n
    不匹配,因此
    *
    在遇到
    \n
    时停止匹配
  • 如果文件结束时没有换行符,则带-
    \n
    的模式将无法匹配,但不带换行符的模式将成功

如果字符串值可能包含
=
,则
(.*)=
将不起作用。例如,如果一行是
TYPE2=“SOME=TEXT”
,则
(.*)
将匹配
TYPE2=“SOME
,这可能是您不想要的。您可以通过使用
([^=]*)=
(\w*)=
来解决此问题,具体取决于格式的细节。

我认为您将文件读入字符串,然后应用正则表达式的想法会很好。有几点:

您不需要(也可能不想要)模式中的
\n

  • 您可能只希望
    123
    作为
    TYPE1
    的值,而不是
    123\n
  • \n
    不匹配,因此
    *
    在遇到
    \n
    时停止匹配
  • 如果文件结束时没有换行符,则带-
    \n
    的模式将无法匹配,但不带换行符的模式将成功
如果字符串值可能包含
=
,则
(.*)=
将不起作用。例如,如果一行是
TYPE2=“SOME=TEXT”
,那么
(.*)
将匹配
TYPE2=“SOME
,这可能是您不想要的。您可以使用
([^=]*)=
(\w*)=
来解决这个问题,具体取决于格式的细节