CS/Kotlin

[Kotlin 문법] 10. 입출력 (1) - 콘솔 입출력, 문자열 포맷팅(출력 형식 지정)

졔졔311 2025. 2. 11. 09:30
728x90
반응형

지금까지는 kotlin의 전체적인 구조를 이해할 수 있도록 중요한 구조들을 공부하였다.

이제부터는 코딩테스트나 개발에 직접적으로 사용할 기본적인 기능과 함수들에 대해 공부할 예정이다.

그에 대한 첫 공부로, kotlin 입출력 방법에 대해 알아보겠다.

 

kotlin에서 입출력 받는 방법은 크게 '콘솔 입출력 / 파일 입출력 / 네트워크 입출력'이 있다.

다만, 네트워크 입출력은 사실 네트워크 관련 자세한 지식이 필요하기 때문에, 여기서 다루지는 않을 것이다.

이번에는 '콘솔 입출력'에 대해 공부하겠다.

 

입력 받기

입력을 받는 방법은 크게 세 가지가 존재한다.

1) readLine() / readln()

- 기본적인 입력을 받기 위해 사용

fun main() {
    val s1 = readLine() // 사용자가 입력한 값을 문자열(String)로 저장
}

readLine()은 String? 타입을 반환한다.

따라서, !!나 ?:를 사용해 null에 대한 처리를 할 수 있다.

반면에, readln()은 non-null 타입이라는 차이가 존재한다.

 

2) Scanner

- 여러 개를 입력받을 때 사용

import java.util.Scanner

fun main() {
    val scanner = Scanner(System.`in`)	// in이 키워드이므로 감싸주어야 함

    val num = scanner.nextInt()  // 정수 입력 받기
    val doub = scanner.nextDouble()	// 실수 입력 받기
    val text = scanner.next()    // 문자열 입력 받기
    val text2 = scanner.nextLine()	// 공백 포함 문자열 입력 받기
}

Scanner를 사용하면 nextInt()나 nextDouble() 등 다양한 타입을 입력받을 수 있다.

Scanner.next()는 공백을 기준으로 입력받으며,

Scanner.nextLine()은 띄어쓰기가 포함된 문자열을 입력받을 수 있다. 즉, 개행문자를 기준으로 입력받는다.

 

3) BufferedReader

- 대량의 데이터를 빠르게 읽을 때 사용

- 속도차이가 다른 입력 방식과 크게 나기 때문에, 속도가 중요하다면 이 클래스를 사용하는 것을 추천

import java.io.BufferedReader
import java.io.InputStreamReader

fun main() {
    val reader = BufferedReader(InputStreamReader(System.`in`))
    val input = reader.readLine()
}

이렇게 InputStreamReader를 사용하는 방식이 있고,

아래와 같이 한 번에 선언하는 방법이 있다.

import java.io.BufferedReader

fun main(){
	val reader = System.`in`.bufferedReader()
	val input = reader.readLine()
}

 


출력하기

출력하기 위해 사용할 수 있는 방법은 세 가지가 존재한다.

1)  print()

- 줄바꿈 없이 내용을 출력하는 함수

fun main(){
	print("Hello Kotlin")
}

 

2) println()

- 줄바꿈을 포함해 출력하는 함수

fun main(){
	println("Hello Kotlin")
}

 

3) BufferedWriter

- 대량의 데이터를 출력할 때 효율적

- 즉시 출력하는 println()과 달리, 버퍼에 저장 후 한 번에 출력하기 때문에 속도가 빠름

import java.io.BufferedWriter
import java.io.OutputStreamWriter

fun main() {
    val writer = BufferedWriter(OutputStreamWriter(System.out))

    writer.write("Hello, Kotlin!\n")  // 줄바꿈 포함
    writer.write("BufferedWriter 출력 예제\n")
    
    writer.flush()
    writer.close()
}

여기서 주의할 점은, 문자열만 버퍼에 저장할 수 있기 때문에 정수를 입력하더라도 그 값에 해당하는 유니코드 문자가 버퍼에 저장된다는 점이다.

예를 들어, writer.write(97)을 하면, 97이 출력되는 것이 아니라 a가 출력된다.

 

flush()를 호출해야 실제로 출력되며, write()를 여러 번 호출해도 한 번에 출력되어 성능이 향상된다.

close()는 버퍼를 비워서 출력하는 flush()의 역할과 동시에 버퍼를 닫아주는 역할도 포함하고 있다.

따라서, 둘 중 하나만 사용하더라도 정상적으로 출력 후 종료된다.

 

flush()는 스트림을 닫지 않으므로 추가 출력이 가능하다.

즉, 아래와 같은 사용이 가능하다.

import java.io.BufferedWriter
import java.io.OutputStreamWriter

fun main() {
    val writer = BufferedWriter(OutputStreamWriter(System.out))

    writer.write("Hello, Kotlin!\n")
    writer.flush()  // 버퍼에 있는 데이터를 즉시 출력

    writer.write("추가 출력\n")
    writer.flush()  // 다시 출력 가능 (스트림이 닫히지 않음)

    writer.close()  // 마지막에 닫아주기
}

 

반면에, 

close()는 자동으로 flush()가 실행되면서 스트림이 닫히게 된다.

따라서 아래처럼 close 후 다시 출력하는 일은 불가능하다.

import java.io.BufferedWriter
import java.io.OutputStreamWriter

fun main() {
    val writer = BufferedWriter(OutputStreamWriter(System.out))

    writer.write("Hello, Kotlin!\n")
    writer.close() // 스트림 닫기 (자동으로 flush() 실행됨)

    writer.write("출력 불가능!") // ❌ 오류 발생: 스트림이 닫혀서 write() 사용 불가
}

문자열 포맷팅

문자를 출력하는 과정에서 원하는 형식으로 지정해 출력할 수 있다.

예를 들어, a라는 변수의 값을 출력하고 싶을 때,

"a"

와 같이 단순히 a라는 변수의 값만 출력되도록 할 수 있지만,

"a = 5 and b = 2."

처럼 여러 개의 값을 형식을 지정해 출력할 수도 있다. 이것을 쉽게 만들어 주는 방식이 '문자열 포맷팅'이다.

 

print()만 사용한다면, 다음과 같은 방식으로 출력할 수 있을 것이다.

print("a = ")
print(a)
print(" and b = ")
print(b)
print(".")

그러나 이 방식은 너무 귀찮다.

이걸 좀더 빠르게 할 수 있게 두 가지 방법을 사용할 수 있다.

 

1) string interpolation (문자열 보간)

- 변수 이름에 '$' 문자를 붙이면 이 변수의 값으로 인식한다.

println("a = $a and b = $b.")

 

2) format()

- String.format() 함수를 사용해 형식을 지정한다.

- string interpolation과 다르게 변수의 값을 지정할 때는 %를 붙여 나타내며, '%[출력 형식]'으로 사용한다.

- 앞에서 사용된 변수의 개수만큼 뒤에 순서대로 변수의 이름을 나열해준다.

println(String.format("a = %d and b = %d.", a, b))
728x90
반응형