티스토리 뷰
Properties 기본
훌륭한 프로그래머는 설정정보를 하드코드하지 않는다. 대신 그들은 이 정보를 소스코드 영역의 외부에
저장하므로서 시스템설정이 변경되었을때 시스템을 재 컴파일하는 것을 막는다. 자바플랫폼의 경우에 이러한
프로그램 설정은 전형적으로 프로퍼티(properties)파일에 저장된다. 스스로 자신만의 방법으로 디자인과
개발을 할 수 있지만 java.util.Properties 클래스는 프로그램의 설정정보를 헛고생하지않고 개발코드에
불러오거나 또는 설정정보에 새로운 정보를 추가, 저장 할 수 있다.
프로퍼티 파일은 일련의 키-값의 쌍들로 이루어지며 파일에 저장된다. 파일의 이름은 .properties로
끝난다. 예를 들어 다음의 2라인은 두개의 프로퍼티들을 가진 프로퍼티파일을 나타낸다. 첫번째 hello
프로퍼티는 world라는 값을 갖으며 두번째 goodbye라는 프로퍼티는 cruel world라는 값을 갖는다.
hello=world
goodbye=cruel world
프로퍼티(Properties)클래스는 기본적으로 지속적인(persistent) 해시테이블을 제공하며 그곳에서 모든
키와 값들은 스트링형태이다. 잠시 데이터를 가져오는 부분을 무시하고 키-값에 접근하는 것은 해시테이블
(Hashtable)에서의 작용하는것과 유사하게 동작한다. 이유는 프로퍼티클래스는 해시클래스의 서브클래스
이기 때문이다.
String value = (String)aPropertiesObject.get("hello");
System.out.println("Value of hello is: " + value);
get메소드의 결과값을 스트링으로 캐스팅했다는 것을 눈치체을 것이다. 프로퍼티 클래스는 단지 스트링과
작용하도록 의도되어졌기 때문에 이것은 특별한 get과 put메소드를 제공한다: getProperty와 setProperty.
getProperty(key) 메소드로 특정한 프로퍼티(키)에 대한 값을 요청할 수 있으며 getProperty(key, default)
메소드로는 동일하게 작용하지만 프로퍼티(키)가 주어지지 않으면 디폴트(default)값이 반환된다. 해시테이블
에서 상속받은 get메소드와 같이 Object를 반환하는 대신 getProperty메소드는 스트링객체를 반환한다.
setProperty 메소드는 해시테이블에서 상속받은 put메소드와 동일하게 작용하지만 그것은 매개변수로 두개의
스트링타입을 받는다:setProperty(keyString, valueString).
프로퍼티 셋팅을 불러오는 것은 괴이하게 이름지어진 load 메소드를 통해 이루어진다. 단지 InputStream에
프로퍼티파일을 넣어서 그 스트림으로부터 프로퍼티들을 읽어온다. 비록 그러한 스트림이 스트링객체들의
라인들을 갖도록 되어있지만 load메소드는 Reader객체가 아닌 InputStream객체를 받아들인다. 8859_1 문자
인코딩은 클래스 정의에 하드 코딩되어 있기때문에 변경할 수 없다. 하지만 프로퍼티파일 안에 \uXXXX라는
상수를 넣으므로서 유니코드값을 기술할 수는 있다.
기본적인 불러오기 프로세스는 다음과 같이 진행된다.
InputStream is = ...
Properties props = new Properties();
try {
props.load(is);
} catch (IOException e) {
System.err.println("Load failed");
}
여기서 InputStream은 전형적인 하나의 FileInputStream이다. 만약 웹 애플리케이션을 jar로 묶었다면
FileInputStream을 이용하는대신 InputStream은 JAR파일로부터 불러들여야 할것이다. 그와 같은 경우
클래스 로더에게 그 스트림을 요청해야 하며 다음과 같다.
InputStream is =
this.getClass().getClassLoader().getResourceAsStream(
"foo.properties");
이것은 현재 실행되어지는 클래스와 같은 디렉토리에서 foo.properties 파일을 찾을 것이다. 위의 라인들은 다음과
같다. 현재 클래스에 대한 클래스 객체를 얻고, 그 클래스객체의 클래스 로더를 얻고, 마지막으로 프로퍼티 파일을
리소스로서 얻으며 그것을 스트림으로 제공한다.
일단 그 프로퍼티파일이 불러들여지면 getProperty메소드와 putProperty메소드를 사용할 수 있다.
어떠한 프로퍼티(키)들이 불러들여졌는지 확인하기 위해서는 list메소드들중의 하나를 사용할 수 있다.
OutputStream 또는 Writer객체에 프로퍼티파일을 불러들여서 프로퍼티들을 쓸수 있다. System.out에 던져
줌으로서 현재의 셋팅들을 콘솔창에서 쓸 수 있는 것이다.
프로퍼티들을 업데이트하고 재저장하려 한다면 Properties 클래스는 store메소드를 이용하면 된다.
그 메소드를 호출했을때 매개변수로 OutputStream과 String을 던져준다: store(OutputStream stream,
String string). 그 스트링은 프로퍼티파일의 첫번째줄에 코멘트로 저장되어지며 파일의 내용이 무엇인지
알수 있도록 한다. 그리고 또한 save메소드 파일이 있으나 그것은 저장 에러에 대해서 IOException을
던지지 않기때문에 비추천화 되어있다.
Properties클래스의 마지막 비트는 propertyNames메소드이며 이것은 Enumeration객체를 반환한다.
이 메소드는 현재의 모든 프로퍼티들과 결합되는데 이는 load메소드에 의해 불리워지는 프로퍼티들과 Properties
클래스의 생성자에 전달되어지는 기본 Properties 객체을 포함한다. 그러므로 리스트를 나열하기 원한다면
Properties클래스의 propertyNames메소드를 이용하여 elements를 반복해야 하며 Hashtable클래스로 부터
상속받은 elements메소드를 사용할 필요없다. elements메소드로는 단지 프로퍼티 리스트에서 특정한 키-값의
쌍을얻을부 있으며 기본 프로퍼티셋팅과는 결합되지 않는다.
이상은 Java Developer Connection Java Technology Fundamentals Newsletter에서 뽑은
Java Programming Language Basics: Properties Basics(Properties 기본) 입니다.
Properties클래스를 테스트 하기 위한 간단한 예제입니다.
package example;
/**
* <p>Title: Properties 클래스 테스트</p>
* <p>Description: 간단하게 프로퍼티파일을 만들어 보고 테스트 할 수 있다.</p>
* <p>Copyright: Copyright (c) 2003</p>
* <p>Company: mansoft.co.kr</p>
* @nofixing
* @version 1.0
*/
import java.util.Properties;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class Example01 {
public Example01() {
}
public static void main(String[] args) {
Properties properties = new Properties();
// Read properties file.
try {
properties.load(new FileInputStream("example01.properties"));
} catch (IOException e) {
}
String avalue = properties.getProperty("a");
System.out.println(avalue);
properties.setProperty("a", "properties test");
// Write properties file.
try {
properties.store(new FileOutputStream("example01.properties"), null);
} catch(IOException e) {
}
}
}
위의 내용을 Example01.java로 저장하여 컴파일을 하고 실행하게 되면 어떤 결과가 나올까요?
한번 실행후 다시 실행해 보시기 바랍니다. 그리고 그 결과가 왜 그렇게 나오는지를 분석하시면
공부하는데 도움이 되시리라 봅니다.
참고로 재미있는 사실은 프로퍼티파일이 생성되는 위치입니다.
자바가상머신이 실행되는 디렉토리를 중심으로 프로퍼티파일이 생성되더군요.
그럼 아무쪼록 좋은 결과를 얻으시기 바라며 자바 뉴스 레터의 원본은 아래와 같습니다.
Good programmers don't hard code configuration information. Instead, they store this information
outside the realm of the source code so that changing system configuration doesn't require
recompilation of the system. For the Java platform, those program settings are typically stored in
properties files. While you could design and develop your own home grown solution, the
java.util.Properties class offers an easy way to load and save these settings with little to no fuss
in your code.
A properties file is a series of key-value pairs, stored in a file. The name of the file ends
with .properties. For instance, the following two lines might represent a properties file with two
properties. The first property of hello has a value of world and the second of goodbye has a value of
cruel world.
hello=world
goodbye=cruel world
The Properties class basically offers a persistent hash table where all the keys and values are
strings. Ignoring the loading part for the moment, accessing key-value pairs works similarly to working
with a Hashtable, as Properties is a subclass of it:
String value = (String)aPropertiesObject.get("hello");
System.out.println("Value of hello is: " + value);
Notice the casting here to a String of results of get. Since the Properties class is only meant to
work with strings, it offers special get and put methods: getProperty and setProperty. With
getProperty, you can ask for the value of a specific property with getProperty(key) and also do the
same but provide a default value in the event the key is not present with getProperty(key, default).
Instead of returning an Object like the get method, getProperty will return a String object. The
setProperty method works identically to the put method, but it requires both arguments to be strings:
setProperty(keyString, valueString).
Loading of property settings is done through the mysteriously named load method. Just pass in an
InputStream and the properties will be read in from the stream. Even though the stream is meant to
contain lines of String objects, the load method accepts an InputStream, not a Reader object. The
8859_1 character encoding is hard-coded into the class definition and cannot be changed. You can
however specify Unicode values by putting \uXXXX constants into the file.
The basic loading process goes as follows:
InputStream is = ...
Properties props = new Properties();
try {
props.load(is);
} catch (IOException e) {
System.err.println("Load failed");
}
The InputStream is typically a FileInputStream. However, if you've jarred up your web application,
instead of using a FileInputStream, the InputStream would need to come from the JAR file. If that
is the case, then you need to ask the class loader for that stream, as shown here:
InputStream is =
this.getClass().getClassLoader().getResourceAsStream(
"foo.properties");
This will look for the foo.properties file in the same directory as the class that is executing. The line
says, get the Class object for the current class, get its class loader, and then finally get the properties
file as a resource and provide it as a stream.
Once the properties file is loaded, you can then use the getProperty and putProperty methods.
To see what properties got loaded, use one of the list methods. This allows you to pass in an
OutputStream or Writer object to write the properties to. By passing in System.out, the current
settings are written to the console.
If you need to update the properties and resave them, the Properties class offers a store method.
When called, you pass in an OutputStream and a String: store(OutputStream stream, String string).
The string is stored as a comment in the first line of the file, allowing a file viewer to see what
is supposed to be in the file. There is also a save method but it is deprecated because it didn't throw
an IOException upon error saving.
The final bit of the Properties class is the propertyNames method which returns an Enumeration.
This method will combine all of the current properties, including those loaded via the load method, with
a default set of Properties passed into the Properties constructor. Thus, if you'd like to replicate the
list behavior yourself, you should use the propertyNames method of Properties to enumerate
through the elements, not the elements method inherited from Hashtable. With the elements method,
you would only get the specific key-value pairs stored in the properties list, not a combined version
with the defaults.