본문 바로가기

Java 길찾기/이것이 자바다

[Java] 기본 API 클래스 - Format

정수 세 자리마다 쉼표( , )를 넣고 싶다면 어떻게 해야 할까? 정수를 문자열로 변환한 다음, 세자리씩 끊어서 쉼표를 넣을 수 있을 것이다. 하지만 이 작업은 매우 귀찮은 작업이고 코드가 지저분해진다. 다른 예로 많은 수의 점수를 리스트화해서 출력할 때 소수점 한 자리로 일정하게 맞추어 출력하려면 어떻게 해야 할까? 각 점수에 10을 곱해서 정수화하고, 다시 10.0으로 나누어 소수점 한 자리로 만들어야 한다. 이 작업 역기 지저분하게 보인다. 날짜 역시 원하는 문자열로 출력하기 위해서는 Calendar로부터 년, 월, 일, 시, 분, 초를 얻어 원하는 문자열로 조합하는 과정을 거쳐야 한다. 자바에서는 이러한 문제들을 쉽게 해결할 수 있는 방법을 제공하는데, 이것이 형식 클래스이다. 형식 클래스는 java.text 패키지에 포함되어 있는데, 숫자 형식을 위해 DecimalFormat, 날짜 형식을 위해 SimpleDateFormat, 매개 변수화 된 문자열 형식을 위해 MessageFormat 등을 제공한다.

 

숫자 형식 클래스(DecimalFormat)

DecimalFormat은 숫자 데이터를 원하는 형식으로 표현하기 위해서 패턴을 사용하는데 다음 표는 패턴의 예를 보여준다.

기호 의미 패턴 예 1234567.89 -> 변환 결과
0 10진수(빈자리는 0으로 채움) 0
0.0
0000000000.00000
1234568
1234567.9
0001234567.89000
# 10진수(빈자리는 채우지 않음) #
#.#
##########.#####
1234568
1234567.9
1234567.89
. 소수점 #.0 1234567.9
- 음수 기호 +#.0
-#.0
+1234567.9
-1234567.9
, 단위 구분 #,###.0 1,234,567.9
E 지수 문자 0.0E0 1.2E6
; 양수와 음수의 패턴을 모두 기술할 경우, 패턴 구분자 +#,### ; -#,### +1,234,568(양수일 때)
-1,234,568(음수일 때)
% 100을 곱한 후에 % 문자 붙임 #.# % 123456789 %
\u00A4 통화 기호 \u00A4 #,### \ 1,234,568

 

적용할 패턴을 선택했다면 DecimalFormat 생성자 매개값으로 지정해서 객체를 생성하면 된다. 그리고 나서 format() 메소드를 호출해서 패턴이 적용된 문자열을 얻으면 된다.

DecimalFormat df = new DecimalFormat("#,###.0");
String result = df.format(1234567.89);

 

다음은 다양한 패턴을 적용해서 얻을 문자열을 출력한다.

// DecimalFormatExample.java -- 숫자를 원하는 형식으로 출력
public class DecimalFormatExample {
    public static void main(String[] args) {
        double num = 1234567.89;
        
        DecimalFormat df = new DecimalFormat("0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("0.0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("0000000000.00000");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("#");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("#.#");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("##########.#####");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("#.0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("+#.0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("-#.0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("#,###.0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("0.0E0");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("+#,### ; -#,###");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("#.# %");
        System.out.println(df.format(num));
        
        df = new DecimalFormat("\u00A4 #,###");
        System.out.println(df.format(num));
    }
}

 

날짜 형식 클래스(SimpleDateFormat)

Date 클래스의 toString() 메소드는 영문으로 된 날짜를 리턴하는데 만약 특정 문자열 포맷으로 얻고 싶다면 java.text.SimpleDateFormat 클래스를 이용하면 된다. SimpleDateFormat 클래스도 날짜를 원하는 형식으로 표현하기 위해서 패턴을 사용하는데 다음 표는 SimpleDateFormat의 패턴 작성에 사용되는 기호들이다.

패턴 문자 의미 패턴 문자 의미
y H 시(0~23)
M h 시(1~12)
d K 시(0~11)
D 월 구분이 없는 일(1~365) k 시(1~24)
E 요일 m
a 오전/오후 s
w 년의 몇 번째 주 S 밀리세컨드(1/1000초)
W 월의 몇 번째 주    

 

패턴에는 자릿수에 맞게 기호를 반복해서 작성할 수 있다. 예를 들어 yyyy는 년도를 4자리로 표시하라는 의미이고, MM, dd는 각각 달과 일을 2자리로 표시하라는 의미이다. 적용할 패턴을 작성했다면 이 패턴을 SimpleDateFormat의 생성자 매개값으로 지정해서 객체를 생성하면 된다. 그리고나서 format() 메소드를 호출해서 패턴이 적용된 문자열을 얻으면 된다.

SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일");
String strDate = sdf.format(new Date());

 

다음은 다양한 패턴을 적용해서 얻은 문자열을 출력한다.

// SimpleDateFormatExample.java -- 날짜를 원하는 형식으로 출력
public class SimpleDateFormatExample {
    public static void main(String[] args) {
        Date now = new Date();
        
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        System.out.println(sdf.format(now));
        
        sdf = new SimpleDateFormat("yyyy년 MM월 dd일");
        System.out.println(sdf.format(now));
        
        sdf = new SimpleDateFormat("yyyy.MM.dd a HH:mm:ss");
        System.out.println(sdf.format(now));
        
        sdf = new SimpleDateFormat("오늘은 E요일");
        System.out.println(sdf.format(now));
        
        sdf = new SimpleDateFormat("올해의 D번째 날");
        System.out.println(sdf.format(now));
        
        sdf = new SimpleDateFormat("이달의 d번째 날");
        System.out.println(sdf.format(now));
    }
}

 

문자열 형식 클래스(MessageFormat)

데이터를 파일에 저장하거나, 네트워크로 전송할 때, 그리고 데이터베이스 SQL문을 작성할 때 등 많은 부분에서 일정한 형식의 문자열을 사용한다. MessageFormat 클래스를 사용하면 문자열에 데이터가 들어갈 자리를 표시해 두고, 프로그램이 실행하면서 동적으로 데이터를 삽입해 문자열을 완성시킬 수 있다. 예를 들어 다음과 같이 회원 정보를 출력한다고 가정해보자.

회원 ID: blue
회원 이름: 홍길동
회원 전화: 010-123-1234

 

만약 id, name, tel이라는 변수에 회원 정보가 저장되어 있을 경우 다음과 같이 문자열 연결 연산자(+)로 출력할 문자열을 생성할 수 있을 것이다.

String result = "회원 ID: " + id + "\n회원 이름: " + name + \n회원 전화: " + tel;

 

이 방법도 나쁜 방법은 아니지만, + 연산자로 인해 복잡해 보이고, 전체 문자열을 파악하기 힘들다. 다음과 같이 MessageFormat 클래스를 사용하면 좀 더 깔끔하게 데이터를 삽입시켜주고 전체 문자열을 쉽게 예측할 수 있다.

String message = "회원 ID: {0} \n회원 이름: {1} \n회원 전화: {2}";
String result = MessageFormat.format(message, id, name, tel);

 

MessageFormat은 정적 format() 메소드를 호출해서 완성된 문자열을 리턴시킨다. format() 메소드의 첫 번째 매개값은 매개 변수화된 문자열을 지정하고, 두 번째 이후의 매개값은 인덱스 순서에 맞게 값을 나열하면 된다. 값을 나열하는 대신, 다음과 같이 배열을 대입해도 좋다.

String text = "회원 ID: {0} \n회원 이름: {1} \n회원 전화: {2}";
Object[] arguments  { id, name, tel };
String result = MessageFormat.format(text, arguments);

 

다음은 매개 변수화된 문자열을 이용해서 회원 정보 및 SQL문을 콘솔에 출력한다.

// MessageFormatExample.java -- 매개 변수화된 문자열 형식
public class MessageFormatExample {
    public static void main(String[] args) {
        String id = "java";
        String name = "홍길동";
        String tel = "010-123-1234";
        
        String text = "회원 ID: {0} \n회원 이름: {1} \n회원 전화 {2}";
        String result1 = MessageFormat.format(text, id, name, tel);
        System.out.println(result1);
        System.out.println();
        
        String sql = "insert into member values({0}, {1}, {2})";
        Object[] arguments = {"'java'", "'홍길동'", "'010-123-1234'"};
        String result2 = MessageFormat.format(sql, arguments);
        System.out.println(result2);
    }
}