J2SE 5.0에서는 C 언어의 printf 과 비슷한 출력물을 포맷하는 새로운 방법을 소개하고 있다. 이 방법에서는 포맷되어야 하는 각각의 인수가 %로 시작하고 포맷된 객체의 타입으로 끝나는 스트링을 이용하여 표현된다. 이번 테크팁에서는 새로운 Formatter 클래스와 클래스에 실행될 포맷 구문을 소개한다.
다음 두가지와 비슷한 호출을 할 때 새로운 포맷 접근법을 가장 많이 사용하게 될 것이다.
System.out.format("Pi is approximately %f", Math.Pi);
System.out.printf("Pi is approximately %f", Math.Pi);
printf()와 format() 메서드는 같은 기능을 한다. System.out은 java.io.PrintStream의 인스턴스이다. PrintStream과 java.io.PrintWriter, java.lang.String는 각각 4개의 새로운 공개 메서드를 보유한다.
format( String format, Object... args); printf( String format, Object... args); format( Locale locale, String format, Object... args); printf( Locale locale, String format, Object... args);
이들은 기본적인 워커 클래스인 java.util.Formatter의 format() 메서드와 일치한다.
format(String format, Object... args) format(Locale l, String format, Object... args)
String과 PrintStream, PrintWriter에서 이런 메서드를 사용하고자 하겠지만 결국 Formatter 클래스를 위한 문서에서 여러 포맷 옵션이 가능한 문서를 찾게될 것이다.
format() 메서드에 대한 다음의 예제에서 시작해보기로 하자.
formatter.format("Pi is approximately %1$f," +
"and e is about %2$f", Math.PI, Math.E);
format() 메서드에는 J2SE 5.0에 소개된 새로운 언어 기능들 중 몇 가지가 필요하다. 그 중 하나는 varargs로써 인수의 임의의 숫자를 메서드에 전달하는 경로를 간단하게 만든다. Object 인스턴스의 변수 숫자가 포맷하는 데 입력될 수 있다는 것과, 예제의 객체들이 autoboxed and unboxed된다는 것을 주의하기 바란다. Autoboxing/Unboxing 역시 J2SE 5.0의 새로운 속성이다. Autoboxing는 수동으로 int와 같은 이전 타입을 Integer같은 래퍼 클래스로 자동으로 변환하며, unboxing은 그 반대 과정을 자동화하는 것이다. 예제에서 Math.PI는 Double(Object처럼 취급)로 autoboxed되는 double이다. 덧붙여, 새로운 기능이 J2SE 5.0에 출시되었는데도 예제에서는 포맷된 출력물은 java.lang.StringBuilder에 작성되었다.
형식은 각각 a %로 시작하는 0 또는 그 이상의 형식 엘리먼트를 포함한 String이다. 각각의 형식 엘리먼트는 전달된 Object를 중 하나에 적용된다. 각 형식 엘리먼트에는 일반적인 폼이 있다.
%[argument_index$][flags][width][.precision]conversion
인수 인덱스(argument index)는 인수들의 목록에서 그 인수의 위치를 지정해주며, 양의 정수로 표현한다. 숫자는 0이 아닌 1에서 첫번째 위치가 시작된다. 따라서 앞서 본 코드에서는 Math.PI가 첫번째에 위치하고 1$를 사용하여 나타난다. Math.E가 두번째 위치이며 2$를 사용한다.
너비(width)는 출력물로써 작성된 글자 중 가장 작은 숫자를 지정한다.
정확도(precision)는 0이 아닌 글자들을 제한하기 위해 사용한다.
변환(conversion)은 객체가 포맷되는 타입을 묘사한다. printf() 명령어를 Java로 구현한 것이므로 대부분의 경우 C 프로그래머들에게 익숙할 것이다. float의 f, time의 t, decimal 의 d, octal의 o, hexadecimal의 x, general의 s, Unicode character의 c가 일반적인 코드들이다. 다음의 샘플 애플리케이션 UsingFormatter에서는 커멘드 라인의 서로 다른 형식들을 입력하고 출력 결과를 볼 수 있다. 이 애플리케이션은 destination의 인스턴스를 생성한다는 사실에 주의하기 바란다.(이번 예에서는 StringBuilder) 그 후 Formatter의 인스턴스를 생성하고 이를 destination과 결합시킨다. 그러면 Formatter는 몇가지 String을 포맷하고 출력물을 destination에 전송하고, 이 변환의 결과가 나타나게 된다.
package format;
import java.util.Formatter;
public class UsingFormatter {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("usage: " +
"java format/UsingFormatter ");
System.exit(0);
}
String format = args[0];
StringBuilder stringBuilder = new StringBuilder();
Formatter formatter = new Formatter(stringBuilder);
formatter.format("Pi is approximately " + format +
", and e is about " + format, Math.PI, Math.E);
System.out.println(stringBuilder);
}
}
다음을 커멘드 라인 인수 %f와 컴파일하고 구동시키자.
java format/UsingFormatter %f
아래와 같은 결과가 나타난다. Pi is approximately 3.141593
Pi is approximately 3.141593, and e is about 2.718282
이것을 리턴하고 정확도(precision)를 소수 둘째 자리까지 나타내자.
java format/UsingFormatter %.2f
아래와 같은 결과가 나타난다.
Pi is approximately 3.14, and e is about 2.72
숫자들의 계산과정이 끝난 것이 아니다. e의 값은 소수 둘째자리를 반올림한다. 이에 덧붙여 커멘드 라인 인수 code>%6.2f를 제공하여 너비를 지정할 수 있다. 정도에서는 세개의 글자와 소수 둘째 자리로 제한되지만 이번에는 숫자가 여섯 글자를 사용해야만 하기 때문에 숫자 앞에 빈공간이 삽입된다. 커멘트를 입력하면,
java format/UsingFormatter %6.2f
다음과 같이 나온다.
Pi is approximately 3.14, and e is about 2.72
위치(position)는 어떤 인수를 포맷할 것인지 지정하는 데 사용한다. 커멘드 라인 인수 %1$.2f로 UsingFormatter를 리턴하자. 이는 Math.PI를 두 번 사용하고자 함을 명시한다. 다음 출력물을 확인해야 한다.
Pi is approximately 3.14, and e is about 3.14
숫자들을 포맷하는데 사용하던 Locale을 import 명령문을 추가하고 서로 다른 컨스트럭터를 호출하여 바꿀 수 있다. 다음은 그 예이다.
package format;
import java.util.Formatter;
import java.util.Locale;
public class UsingFormatter {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("usage: " +
"java format/UsingFormatter <format string>");
System.exit(0);
}
String format = args[0];
StringBuilder stringBuilder = new StringBuilder();
Formatter formatter = new Formatter(stringBuilder,
Locale.FRANCE);
formatter.format("Pi is approximately " + format +
", and e is about " + format, Math.PI, Math.E);
System.out.println(stringBuilder);
}
}
이것을 인수 %.2f로 컴파일하고 구동하면 소수점이 쉼표로 바뀐 것을 볼 수 있을 것이다.
Pi is approximately 3,14, and e is about 2,72
앞에서 언급했듯이, 일반적으로 Formatter 클래스를 명확하게 사용하지는 않을 것이다. 대신, 예를 들어 printf()과 format() 메서드를 PrintStream클래스에 직접 사용할 수 있다. 다음의 프로그램 UUsingSystemOut은 stand out 을 사용하기 위한 UsingFormatter프로그램의 재작성된 버전이다.
package format;
public class UsingSystemOut {
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("usage: " +
"java format/UsingSystemOut <format string>");
System.exit(0);
}
String format = args[0];
System.out.format("Pi is approximately " + format +
", and e is approximately " + format, Math.PI, Math.E);
}
}
UsingSystemOut의 실행은 UsingFormatter의 실행과 약간 다르다. UsingFormatter 프로그램은 println()을 사용하지만 UsingSystemOut프로그램은 사용하지 않는다. 이 때문에 커멘드 라인에서 UsingSystemOut를 구동하면 다음 커멘드 길잡이 기호가 출력물과 같은 줄에 있을 것이다. 새로운 줄을 삽입해야 된다. %.2f%n로 UsingSystemOut를 구동시키자.
java format/UsingSystemOut %.2f%n
다음과 같은 결과가 나타난다.
Pi is approximately 3.14 , and e is about 2.72
선호도에 따라 마지막 메서드 콜을 printf()로 대체할 수도 있다. System.out.format()과 System.out.printf()에는 다른 점이 없다.
마지막 예제로 날짜와 시간 객체가 어떻게 포맷되는지 알아보자. 이 객체들은 대화타입 t또는 T를 가지고 있다. 이 글자들 뒤에 어떤 부분의 시간이 표시되고 어떻게 표시되어야 하는 지 지정해주는 두 번째 글자가 뒤따른다. 예를 들어 tH 또는 tI, tk, tl을 사용하여 여러가지 폼으로 시각을 표시하고 tM으로 분을 표현할 수 있다. 이들은 tr로 조합되어 tH:tM으로 표시될 수도 있다. 이와 비슷하게 Formatter API에 자세히 나와있는 포맷 대화 키를 이용하여 요일, 월 등을 표시할 수 있다.
다음은 tr을 이용해서 시각과 분이 나와있는 현재 시간을 포맷팅하여 날짜를 보여주는 예제이다. tA는 요일을, tB는 월을 te는 날짜를, tY는 연도를 표시한다. 이들은 모두 첫번째 위치를 가리키기 위해 1$ 대신 %tr를 둔다. 다른 포맷 스트링의 <는 이전에 포맷한 위치를 조회한다.
package format;
import java.util.Calendar;
public class FormattingDates {
public static void main(String[] args) {
System.out.printf("Right now it is %tr on " +
"%<tA, %<tB %<te, %<tY.%n",
Calendar.getInstance());
}
}
FormattingDates 프로그램을 컴파일하고 구동하라. 다음과 같은 출력물을 얻게될 것이다.
Right now it is 01:55:19 PM on Wednesday, September 22, 2004.
포맷 출력을 위한 새로운 Formatter 기능의 사용을 권장하기 위해 이번 테크팁을 설명하였다. 어떻게 보면, 이 옵션들은 printf()방식에 익숙한 사용자들에게 친숙할 것이다. 예전과 같이 많은 가능성이 존재한다. 서로 다른 옵션들을 사용해 보고 어떤 것이 니즈에 가장 적합한지 결정하면서 이들을 배울 수 있을 것이다.
새로운 Formatter로 포맷하는 것에 대해 좀 더 자세히 알고 싶으면, Formatter 클래스에 대한 문서를 참조하기 바란다.
"Java SE" 카테고리의 다른 글
- JSSE 이용한 안전한 커뮤니케이션 (댓글 2개 / 트랙백 0개) 2004/08/31
- 3D 화면(scene)에 빛 효과 주기 (댓글 1개 / 트랙백 0개) 2004/07/30
- Java SE & Java SE for Business 지원 로드맵 (댓글 0개 / 트랙백 0개) 2009/09/11
- 클래스에서 enhanced For-Loop 사용 (댓글 0개 / 트랙백 1개) 2007/10/09
- VARIABLE CONTENT로 메세지 포맷하기 (댓글 7개 / 트랙백 2개) 2003/08/19
- CONTENTPANE 작업의 변화 (댓글 1개 / 트랙백 0개) 2004/11/11
- 새로운 포매터로 출력물 포맷하기 (댓글 1개 / 트랙백 0개) 2004/10/27
- 스윙 유저 인터페이스에서 컴포넌트의 방향성 (댓글 2개 / 트랙백 0개) 2003/09/26
- 쓰레드의 상태정보를 저장할 때 사용되는 THREADLOCAL 변수들 (댓글 4개 / 트랙백 0개) 2003/12/12
- 2개의 스트링이 같은 경우는? (댓글 2개 / 트랙백 0개) 2004/05/27
댓글을 달아 주세요
좋은 정보 감사해요~
2007/09/19 05:38