10-2. 형식화 클래스

Hyun Jun·2022년 1월 27일
0

자바의 정석

목록 보기
38/52
post-thumbnail
post-custom-banner

형식화 클래스

숫자, 날짜, 텍스트 데이터를 일정한 형식에 맞게 formatting 시켜주는 클래스

formatting을 위한 패턴을 정의하면 그 패턴에 맞게 데이터가 가공됨.

 

DecimalFormat

숫자를 formatting 하는데에 사용 (반대로, formatting된 데이터를 숫자로 변환도 가능)

DecimalFormat의 인스턴스를 생성하고, 생성자 인자로 패턴을 넣으면 사용할 준비 완료 (패턴의 종류와 설명은 교재 p.541)

→ 정수, 부동소수점, 금액 등 다양한 형식

 

  1. String format()

    DecimalFormat의 인스턴스 메서드

    매개변수 타입은 long, double, Object 등...

    인자를 패턴에 맞게 formatting 해줌

    DecimalFormat df = new DecimalFormat("#.#E0");
    df.format(1234567.89); // 1.2E6

    위 예시는 "#.#E0" 패턴을 사용했는데, 다음과 같은 의미를 지님

    10진수(#) + 소수점(.) + 10진수(#) + 지수(E) + 10진수(0 = 값이 없을 경우에 0 처리)

 

  1. Number parse()

    DecimalFormat의 조상인 NumberForamt의 인스턴스 메서드

    String또는 StringBuffer 타입의 문자열을 받아와 기호와 문자를 제거하고 숫자로 변환해줌

 

👨‍💻 특정 패턴으로 format 했다가 다시 parse 하여 원래의 값으로 돌아오는 예제

class FormatAndParseExample {
    public static void main(String[] args) {
        double num = 1234567.89;
        DecimalFormat df = new DecimalFormat("#,###.##"); // 정수부는 3자리 단위로 쉼표를 넣고, 소수점 아래는 2자리까지 표현

        String formattedNum = df.format(num);
        System.out.println(formattedNum); // 1,234,567.89

        try {
            Number parsedNum = df.parse(formattedNum);
            double result = parsedNum.doubleValue(); // parse를 한 결과가 Number 타입이므로 double로 변환해줌
            System.out.println(result); // 1234567.89
        } catch (ParseException e) {
            System.out.println("parse failed.");
        }
    }
}

📌 [주의] parse()를 사용할 때는 반드시 예외처리를 해주어야함 (parse의 선언부에 예외가 선언되어 있음)

public Number parse(String source) throws ParseException { ... }

 

SimpleDateFormat

DateCalendar 클래스를 이용해서 얻을 수 있는 날짜 데이터를 좀 더 입맛에 맞게 formatting 시켜줌

생성자에 문자열로 된 패턴을 넣어 인스턴스를 생성해주고, format 메서드를 사용하면 됨.

📌 [주의] format 메서드는 Date 인스턴스를 가지고만 쓸 수 있기 때문에 Calendar를 사용한다면 Date로 변환해주어야함.

Date today = new Date();
System.out.println(today); // Wed Jan 26 18:06:56 KST 2022

SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 E요일 HH:mm:ss", Locale.KOREA);
System.out.println(sdf.format(today)); // 2022년 01월 26일 수요일 18:06:56

생성자의 두번째 인자로 넣은 Locale.KOREA는 기준 지역을 나타내는 상수

(요일 같은 데이터가 한글로 나오게 하기 위해 넣음)

 

패턴에 사용되는 기호들

기호의미
G연대(BC, AD)
y연도
M월(1 ~ 12)
w연도의 몇번째 주(1 ~ 53)
W월의 몇번째 주(1 ~ 5)
D연도의 몇번째 일(1 ~ 366)
d월의 몇번째 일(1 ~ 31)
F월의 몇번째 요일(1 ~ 5)
E요일
a오전/오후(AM, PM)
H시간(0 ~ 23)
k시간(1 ~ 24)
K시간(0 ~ 11)
h시간(1 ~ 12)
m분(0 ~ 59)
s초(0 ~ 59)
S밀리초(0 ~ 999)
zGMT
ZRFC 822 time zone
'이스케이프 문자

 

parse 메서드를 이용하면 문자열을 Date 인스턴스로 변환해줌.

Date today = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일", Locale.KOREA);

String formatted = sdf.format(today);
System.out.println(formatted); // 2022년 01월 26일

try {
        Date parsed = sdf.parse("2022년 01월 26일");
        System.out.println(parsed); // Wed Jan 26 00:00:00 KST 2022
} catch (ParseException e) {
        System.out.println("parse failed.");
}

사용자로부터 입력받은 날짜 문자열을 날짜로 인식하는데에 유용함

예시) 사용자로부터 날짜 텍스트 입력받아 Date 데이터로 인식하기

class SDFExample {
    public static void main(String[] args) {
        String pattern = "(\\d{4})-(\\d{2})-(\\d{2})";
        String datePattern = "yyyy-MM-dd";
        Scanner scanner = new Scanner(System.in);
        SimpleDateFormat sdf = new SimpleDateFormat(datePattern);
        Date d = null;

        while (d == null) {
            System.out.println("날짜를 yyyy-mm-dd 형태로 입력해주세요!");
            String userInput = scanner.nextLine();

            try {
                Pattern p = Pattern.compile(pattern);
                Matcher m = p.matcher(userInput);
                if(!m.matches()) throw new Exception();

                d = sdf.parse(userInput);
                System.out.println(d + " 날짜 데이터가 정상 인식되었습니다.");
            } catch (Exception e) {
                System.out.println("잘못된 형식입니다.");
            }
        }
    }
}

실행 결과)

날짜를 yyyy-mm-dd 형태로 입력해주세요!
hello
잘못된 형식입니다.
날짜를 yyyy-mm-dd 형태로 입력해주세요!
123-4-56
잘못된 형식입니다.
날짜를 yyyy-mm-dd 형태로 입력해주세요!
1996-10-28
Mon Oct 28 00:00:00 KST 1996 날짜 데이터가 정상 인식되었습니다.

 

ChoiceFormat

지정된 범위에 속하는 값을 지정된 문자열로 변환해줌

ChoiceFormat의 생성자는 2가지 버전이 있는데 하나는 문자열 패턴을 넘기는 방식, 다른 하나는 경계값과 치환값을 넘기는 방식임

  1. 문자열 패턴 지정

    • 구간은 |로 구분

    • #은 경계값을 범위에 포함, <은 미포함

    예시)

    class CFExample {
        public static void main(String[] args) {
            String pattern = "60#D|70#C|80#B|90#A|97<A+"; // 패턴
            int[] scoreData = {95, 63, 78, 100, 84, 92, 69};
    
            ChoiceFormat cf = new ChoiceFormat(pattern);
    
            for (int i = 0; i < scoreData.length; i++) {
                System.out.println(scoreData[i] + ": " + cf.format(scoreData[i]));
            }
        }
    }

 

  1. 경계값과 치환값 지정

    • 경계값은 double[], 치환값은 String[] 타입이어야함

    • 경계값은 오름차순으로 정렬되어 있어야하며, 치환값의 개수는 경계값으로 정해진 구간의 개수와 동일해야함

    예시)

    class CFExample {
        public static void main(String[] args) {
            double[] limits = {60, 70, 80, 90, 98}; // 경계값
            String[] grades = {"D", "C", "B", "A", "A+"}; // 치환값
            int[] scoreData = {95, 63, 78, 100, 84, 92, 69};
    
            ChoiceFormat cf = new ChoiceFormat(limits, grades);
    
            for (int i = 0; i < scoreData.length; i++) {
                System.out.println(scoreData[i] + ": " + cf.format(scoreData[i]));
            }
        }
    }

    실행 결과는 두 방법 모두 같음.

    실행 결과)

    95: A
    63: D
    78: C
    100: A+
    84: B
    92: A
    69: D

 

MessageFormat

데이터를 정해진 양식에 맞게 출력할 수 있도록 도와줌

다양한 데이터에 대해 같은 양식을 사용하여 출력할 때 유용함

예시)

class MessageFormatExample {
    public static void main(String[] args) {
        String message = "Title: {0}\nDirector: {1}\nGenre: {2}\nRunning Time: {3}\nRelease Date: {4}";
        Object[] arguments = {"The Dark Knight", "Christopher Nolan", "Action", "152 min", "2008-08-06"};

        String result = MessageFormat.format(message, arguments);
        System.out.println(result);
    }
}

실행 결과)

Title: The Dark Knight
Director: Christopher Nolan
Genre: Action
Running Time: 152 min
Release Date: 2008-08-06

format 메서드의 첫번째 인자로 문자열을 작성할 때, 데이터가 들어가길 원하는 자리에 {인덱스(숫자)}를 넣음

그 자리에 객체 배열의 원소인 각 데이터가 순서대로 들어가게됨.

 

미리 패턴을 제시해두고, 해당 패턴에 맞는 문자열을 대입하면 원하는 데이터를 추출해올 수 있음

예시)

class MessageFormatExample2 {
    public static void main(String[] args) {
        String[] data = {"NAME: Andy, POSITION: back-end, CONTACT: 010-1234-5678, EMAIL: andy@email.com", "NAME: Paul, POSITION: front-end, CONTACT: 010-8765-4321, EMAIL: paul@email.com", "NAME: Michael, POSITION: dev-ops, CONTACT: 010-1212-3434, EMAIL: michael@email.com"};
        String pattern = "NAME: {0}, POSITION: {1}, CONTACT: {2}, EMAIL: {3}";

        MessageFormat mf = new MessageFormat(pattern);

        for (int i = 0; i < data.length; i++) {
            try {
                Object[] objArr = mf.parse(data[i]);
                System.out.println(objArr[1]);
            } catch (ParseException e) {
                System.out.println("parse failed.");
            }
        }
    }
}

실행 결과)

back-end
front-end
dev-ops

MessageFormat의 생성자에 패턴 문자열을 넣어두고, parse 메서드에 패턴에 부합하는 문자열 데이터를 넘겼음

parse 메서드는 Object 배열에 지정된 위치의 데이터를 순서대로 담아 반환하기 때문에, 인덱싱을 통해 원하는 데이터를 추출하기 용이함.

profile
Back-end Engineer 👨‍💻
post-custom-banner

0개의 댓글