Thraug
Thraug

Reputation: 43

Groovy: Read properties file, then write file with original comments

In Groovy, is there a way to read a .properties file containing comments, make some property changes in code, then write to the same file while retaining all comments and whitespace still in their correct locations in the file?

I'm currently using something simple like this to read and write a 'app.properties' but the resulting file loses all of its comments:

// read
props = new Properties()
propsFile = new File('C:\\path\\app.properties')
props.load(propsFile.newDataInputStream())

// write
props.setProperty('property.one', 'New value one')
props.store(propsFile.newWriter(), null)

I've come up with two following solutions, but was wondering if there was a better way?

  1. Create my own writer, keeping track of the comments + whitespace. Yuk!

  2. Using the PropertiesConfiguration classes in the Apache Commons Configuration Java library, which can retain whitespace and comments while writing .properties. I haven't tested this yet. My preference would not to use any external libs.

Upvotes: 1

Views: 2122

Answers (2)

LiborStefek
LiborStefek

Reputation: 410

Working example, based on injecter's answer:

Map mapping = [ "property.one":"new property value" ]

def propsFile = new File('app.properties')
def propLines = propsFile.text.readLines()
def newProps = propLines.collect{ line ->
  line.eachMatch( /([\w\.]+)=(.*)/ ) { k ->
    if (mapping.get(k[1])) line = "${k[1]}=${mapping.get(k[1])}";
  }
  line;
}
propsFile.createNewFile()
propsFile.withWriter{ out ->
  newProps.each{ out << it << '\n' }
}

Upvotes: 0

injecteer
injecteer

Reputation: 20699

I'm not aware of any comments retaining properties-files readers.

On the other hand it should be fairly simple to pipe the input to output with modifications.

Something like

props = new Properties()
propsFile = new File('C:\\path\\app.properties')
props.load(propsFile.newDataInputStream())

Map key2comments = [:]
propFile.eachLine{ line ->
  line.eachMatch( /(\w+)=([^#]+)(.*)/ ){ String[] parts ->
    key2comments[ parts[ 1 ] ] = parts[ 3 ] ?: ''
  }
}

props.setProperty('property.one', 'New value one')

propFile.createNewFile()
propFile.withWriter{ out ->
  props.each{ k, v ->
    out << k << '=' << v << key2comments[ k ] << '\n'
  }
}

You may want to play with the regex to cut the comments more accurate out.

Upvotes: 1

Related Questions