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*)=
来解决这个问题,具体取决于格式的细节