源码解析
public class OriginTrackedPropertiesLoader {
private final Resource resource;
public OriginTrackedPropertiesLoader ( Resource resource) {
Assert . notNull ( resource, "Resource must not be null" ) ;
this . resource = resource;
}
public Map < String , OriginTrackedValue > load ( ) throws IOException {
return load ( true ) ;
}
Map < String , OriginTrackedValue > load ( boolean expandLists) throws IOException {
try ( CharacterReader reader = new CharacterReader ( this . resource) ) {
Map < String , OriginTrackedValue > result = new LinkedHashMap < > ( ) ;
StringBuilder buffer = new StringBuilder ( ) ;
while ( reader. read ( ) ) {
String key = loadKey ( buffer, reader) . trim ( ) ;
if ( expandLists && key. endsWith ( "[]" ) ) {
key = key. substring ( 0 , key. length ( ) - 2 ) ;
int index = 0 ;
do {
OriginTrackedValue value = loadValue ( buffer, reader, true ) ;
put ( result, key + "[" + ( index++ ) + "]" , value) ;
if ( ! reader. isEndOfLine ( ) ) {
reader. read ( ) ;
}
} while ( ! reader. isEndOfLine ( ) ) ;
}
else {
OriginTrackedValue value = loadValue ( buffer, reader, false ) ;
put ( result, key, value) ;
}
}
return result;
}
}
private String loadKey ( StringBuilder buffer, CharacterReader reader) throws IOException {
buffer. setLength ( 0 ) ;
boolean previousWhitespace = false ;
while ( ! reader. isEndOfLine ( ) ) {
if ( reader. isPropertyDelimiter ( ) ) {
reader. read ( ) ;
return buffer. toString ( ) ;
}
if ( ! reader. isWhiteSpace ( ) && previousWhitespace) {
return buffer. toString ( ) ;
}
previousWhitespace = reader. isWhiteSpace ( ) ;
buffer. append ( reader. getCharacter ( ) ) ;
reader. read ( ) ;
}
return buffer. toString ( ) ;
}
private OriginTrackedValue loadValue ( StringBuilder buffer, CharacterReader reader, boolean splitLists)
throws IOException {
buffer. setLength ( 0 ) ;
while ( reader. isWhiteSpace ( ) && ! reader. isEndOfLine ( ) ) {
reader. read ( ) ;
}
Location location = reader. getLocation ( ) ;
while ( ! reader. isEndOfLine ( ) && ! ( splitLists && reader. isListDelimiter ( ) ) ) {
buffer. append ( reader. getCharacter ( ) ) ;
reader. read ( ) ;
}
Origin origin = new TextResourceOrigin ( this . resource, location) ;
return OriginTrackedValue . of ( buffer. toString ( ) , origin) ;
}
private static class CharacterReader implements Closeable {
}
}
案例
test-properties.properties配置文件
# foo
blah = hello world
bar foo=baz
hello world
proper\\ty=test
foo
bat = a\\
bling = a=b
#commented-property=test
test=properties
test-unicode=properties\u0026test
# comment ending \
test\=property=helloworld
test-colon-separator: my-property
test-tab-property=foo\tbar
test-return-property=foo\rbar
test-newline-property=foo\nbar
test-form-feed-property=foo\fbar
test-whitespace-property = foo bar
test-multiline= a\
b\\\
c
foods[]=Apple,\
Orange,\
Strawberry,\
Mango
languages[perl]=Elite
languages[python]=Elite
language[pascal]=Lame
test-multiline-immediate=\
foo
!commented-two=bang\
test-bang-property=foo!
another=bar
test-property-value-comment=foo \
!bar #foo
test-multiline-immediate-bang=\
!foo
#test ISO 8859-1
test-iso8859-1-chars=����������
test-with-trailing-space= trailing
private ClassPathResource resource;
private Map < String , OriginTrackedValue > properties;
@Test
void compareToJavaProperties ( ) throws Exception {
String path = "test-properties.properties" ;
this . resource = new ClassPathResource ( path, getClass ( ) ) ;
this . properties = new OriginTrackedPropertiesLoader ( this . resource) . load ( ) ;
Properties java = PropertiesLoaderUtils . loadProperties ( this . resource) ;
Properties ours = new Properties ( ) ;
new OriginTrackedPropertiesLoader ( this . resource)
. load ( false )
. forEach ( ( k, v) -> System . out. println ( k+ ":" + v. getValue ( ) ) ) ;
}
运行结果
blah:hello world
bar:foo= baz
hello:world
proper\ ty:test
foo:
bat:a\
bling:a= b
test:properties
test-unicode:properties& test
test = property:helloworld
test-colon-separator:my-property
test-tab-property:foo bar
bar
test-newline-property:foo
bar
test-form-feed-property:foobar
test-whitespace-property:foo bar
test-multiline:ab\ c
foods[ ] :Apple,Orange,Strawberry,Mango
languages[ perl] :Elite
languages[ python] :Elite
language[ pascal] :Lame
test-multiline-immediate:foo
test-bang-property:foo!
another:bar
test-property-value-comment:foo ! bar
test-multiline-immediate-bang:! foo
test-iso8859-1-chars:����������
test-with-trailing-space:trailing