관리 메뉴

나만을 위한 블로그

[JAVA] 버퍼란? BufferedReader/Writer란? + 예제 본문

JAVA

[JAVA] 버퍼란? BufferedReader/Writer란? + 예제

참깨빵위에참깨빵 2021. 9. 4. 01:07
728x90
반응형

딱 봤을 때 Bufferd와 reader, writer를 합친 단어같다. 그럼 프로그래밍에서 Buffer(버퍼)의 뜻이 뭔지부터 알아야 할 것 같다.

버퍼의 사전적 정의는 아래와 같다.

 

buffer : 완충제, 완충 장치, 완화하다
완충제 : 일반적으로 급격한 외부 변화를 완화시키는 작용을 하는 물질

 

일상생활에서 완충제는 충격을 완화하는 물건이란 뜻이 있다고 알고 있다. 이게 프로그래밍에선 무슨 의미로 사용될까?

위키백과에선 버퍼를 아래와 같이 정의하고 있다.

https://ko.wikipedia.org/wiki/%EB%B2%84%ED%8D%BC_(%EC%BB%B4%ED%93%A8%ED%84%B0_%EA%B3%BC%ED%95%99) 

 

버퍼 (컴퓨터 과학) - 위키백과, 우리 모두의 백과사전

컴퓨팅에서, 버퍼(buffer, 문화어: 완충기억기)는 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 메모리의 영역이다. 버퍼링(buffering)이란 버퍼를 활용하는

ko.wikipedia.org

버퍼는 데이터를 한 곳에서 다른 한 곳으로 전송하는 동안 일시적으로 그 데이터를 보관하는 메모리의 영역이다. 버퍼링(Buffering)이란 버퍼를 활용하는 방식 또는 버퍼를 채우는 동작을 말한다. 다른 말로 큐(Queue)라고도 표현한다.
버퍼는 컴퓨터 안의 프로세스 사이에서 데이터를 이동시킬 때 사용된다. 보통 데이터는 키보드와 같은 입력 장치로부터 받거나 프린터와 같은 출력 장치로 내보낼 때 버퍼 안에 저장된다. 이는 전자 통신의 버퍼와 비유할 수 있다. 버퍼는 하드웨어나 소프트웨어에 추가될 수 있지만 버퍼는 상당수가 소프트웨어에 추가된다. 버퍼는 보통 속도가 계속 바뀔 수 있으므로 데이터 수신, 처리 속도에 차이가 있다...(중략)

 

버퍼는 데이터 전송 시 사용되고, 데이터를 어디에 잠깐 보관하는 메모리 영역이란 것 같다. 영문 위키백과에선 버퍼를 롤러코스터에 비유하고 있다.

 

https://en.wikipedia.org/wiki/Data_buffer

 

Data buffer - Wikipedia

Region of a physical memory storage used to temporarily store data while it is being moved from one place to another In computer science, a data buffer (or just buffer) is a region of a physical memory storage used to temporarily store data while it is bei

en.wikipedia.org

롤러코스터 줄은 많은 유사점을 공유한다. 롤러코스터를 타는 사람들은 알려지지 않고 종종 가변적인 속도로 들어오지만 롤러코스터는 사람들을 순식간에 태울 수 있다. 대기줄 영역은 승차를 원하는 사람들이 승차가 가능할 때까지 기다리는 임시 공간인 완충제 역할을 한다

 

데이터를 담아서 한 번에 전달하는 놈이란 건 알겠다. 그런데 버퍼를 왜 써야 할까?

 

https://stackoverflow.com/questions/22436289/when-to-use-buffer-and-what-for

 

When to use buffer,and what for

I have a confusion regarding the input stream and output stream. When do we need to use Buffered output and input Streams. And same with the Buffered Reader and Buffered Writer?

stackoverflow.com

버퍼 I/O가 없으면 각 읽기 또는 쓰기 요청이 기본 OS에서 직접 처리됨을 의미한다. 이건 각각의 그러한 요청이 종종 디스크 액세스, 네트워크 활동 또는 상대적으로 비용이 많이 드는 기타 작업을 트리거하기 때문에 프로그램을 훨씬 덜 효율적으로 만들 수 있다. 이런 종류의 오버헤드를 줄이기 위해 자바 플랫폼은 버퍼링된 I/O 스트림을 구현한다. 버퍼링된 입력 스트림은 버퍼로 알려진 메모리 영역에서 데이터를 읽는다.

 

버퍼를 사용하지 않으면 특정 경우에서 프로그램이 덜 효율적으로 작동한다고 한다. 버퍼의 특징과 상관있는 말일까?

버퍼는 어떤 특징을 갖고 있는지 확인해봤다.

 

https://whatis.techtarget.com/definition/buffer

 

What is buffer? - Definition from WhatIs.com

 

whatis.techtarget.com

버퍼는 다른 속도로 또는 다른 우선순위 세트로 작동하는 하드웨어 장치 또는 프로그램 프로세스가 공유하는 데이터 영역이다. 버퍼를 쓰면 각 장치 또는 프로세스가 다른 장치에 의해 유지되지 않고 작동할 수 있다. 버퍼가 효과적이려면 버퍼 크기와 버퍼 안팎으로 데이터를 이동하는 알고리즘을 버퍼 설계자가 고려해야 한다.
캐시와 마찬가지로 버퍼는 "중간 지점 유지 장소"지만 개별 활동의 조정을 지원하기보다 활동의 속도를 가속화하기 위해 존재한다. 이 용어는 프로그래밍과 하드웨어 모두에서 사용된다

https://tcpschool.com/cpp/cpp_io_streamBuffer

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com

버퍼를 써서 얻을 수 있는 장점은 2개다.
1. 문자를 묶어서 한 번에 전달하므로 전송시간이 적게 걸려 성능이 향상된다
2. 사용자가 문자를 잘못 입력했을 경우 수정할 수 있다.
하지만 입력 작업에 버퍼를 쓰는 게 반드시 좋은 건 아니다. 빠른 반응이 요구되는 게임 등 프로그램에선 키를 누르는 즉시 전달돼야 한다.

https://stackoverflow.com/questions/648309/what-does-it-mean-by-buffer

 

What does it mean by buffer?

I see the word "BUFFER" everywhere, but I am unable to grasp what it exactly is. Would anybody please explain what is buffer in layman's language? When is it used? How is it used?

stackoverflow.com

입력 속도와 출력 속도의 차이를 줄이기 위해 임시로 뭔가를 저장하는 곳이다. 생산자가 소비자보다 빠르지만 생산자는 출력을 버퍼에 계속 저장할 수 있다. 소비자가 접근하면 버퍼에서 읽을 수 있다. 버퍼는 중간에 간격을 메우기 위해 있다.

 

흙더미를 삽으로 퍼서 옮길 때 한 번씩 삽에 흙을 담고 옮기는 것보다 자루 같은 것에 담아서 옮기는 편이 작업 시간이 좀 더 단축된다. 여기서 자루가 버퍼의 역할을 하는 것 같다.

 

 

그럼 자바에서 버퍼는 어떻게 사용할 수 있는가? 제목에 적은 대로 자바에선 BufferedWriter와 BufferedReader라는 클래스를 제공한다.

 

https://docs.oracle.com/javase/7/docs/api/java/io/BufferedReader.html

 

BufferedReader (Java Platform SE 7 )

Reads characters into a portion of an array. This method implements the general contract of the corresponding read method of the Reader class. As an additional convenience, it attempts to read as many characters as possible by repeatedly invoking the read

docs.oracle.com

문자 입력 스트림에서 텍스트를 읽고 문자, 배열, 행(lines)을 효율적으로 읽을 수 있게 문자를 버퍼링한다. 버퍼 크기를 지정하거나 기본 크기를 사용할 수 있다. 기본값은 대부분의 목적에 충분히 크다. 일반적으로 Reader의 각 읽기 요청은 기본 문자 또는 바이트 스트림에 대한 해당 읽기 요청을 발생시킨다. 따라서 FileReader 및 InputStreamReader와 같이 read() 작업에 비용이 많이 들 수 있는 Reader 주위에 BufferedReader를 아래처럼 래핑하는 게 좋다.

BufferedReader in  = new BufferedReader(new FileReader("foo.in"))

이 코드는 지정된 파일의 입력을 버퍼링한다. 버퍼링이 없으면 read() 또는 readLine()을 호출할 때마다 파일에서 바이트를 읽고 문자로 변환한 다음 반환할 수 있으므로 매우 비효율적일 수 있다. 텍스트 입력에 DataInputStream을 쓰는 프로그램은 각 DataInputStream을 적절한 BufferedReader로 교체해 지역화할 수 있다.

 

https://docs.oracle.com/javase/7/docs/api/java/io/BufferedWriter.html

 

BufferedWriter (Java Platform SE 7 )

Writes a portion of an array of characters. Ordinarily this method stores characters from the given array into this stream's buffer, flushing the buffer to the underlying stream as needed. If the requested length is at least as large as the buffer, however

docs.oracle.com

단일 문자, 배열, 문자열을 효율적으로 쓸 수 있도록 문자를 버퍼링해서 문자 출력 스트림에 텍스트를 쓴다. 버퍼 크기를 지정하거나 기본 크기를 쓸 수 있다. 기본값은 대부분의 목적에 충분히 크다. 시스템 속성 line.separator에 정의된 대로 플랫폼 고유의 줄 구분자 개념을 사용하는 newLine()이 제공된다. 모든 플랫폼이 줄 바꿈 문자(\n)를 써서 줄을 종료하는 건 아니다. 따라서 이 메서드를 호출해서 각 출력 라인을 종료하는 게 개행 문자를 직접 작성하는 것보다 선호된다. 일반적으로 Writer는 출력을 기본 문자 또는 바이트 스트림으로 즉시 내보낸다. 프롬프트 출력이 필요한 경우가 아니면 FileWriter 및 OutputStreamWriter와 같이 write() 작업에 비용이 많이 들 수 있는 모든 Writer 주위에 BufferedWriter를 아래처럼 래핑하는 것이 좋다.

PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")))

PrintWriter의 출력을 파일로 버퍼링한다. 버퍼링이 없으면 print()를 호출할 때마다 문자가 바이트로 변환되어 파일에 즉시 기록되므로 매우 비효율적일 수 있다.

 

BufferedWriter의 간단한 예제는 아래와 같다. 바탕화면에 txt 파일을 만들고 그 안에 특정 문자열을 입력한 후 저장하는 예제다.

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

public class WriteFile
{
    public static void main(String[] args)
    {
        BufferedWriter bw = null;
        try
        {
            String content = "이 내용을 메모장 파일에 입력할 것";
            File file = new File("C:\\Users\\Desktop\\임시파일.txt");

            FileWriter fw = new FileWriter(file);
            bw = new BufferedWriter(fw);
            bw.write(content);
            System.out.println("!!! 파일 작성이 완료됨");
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (bw != null)
                {
                    bw.close();
                }
            }
            catch (IOException e)
            {
                System.out.println("BufferedWriter를 종료할 때 에러 발생 : " + e);
            }
        }
    }
}

 

바탕화면의 절대경로와 파일명.txt를 적어두고 이 코드를 실행하면 바탕화면에 메모장이 만들어지고 content 변수 안의 문자열들이 입력되어 있는 걸 볼 수 있다.

BufferedReader는 아래와 같이 사용할 수 있다.

 

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile
{
    public static void main(String[] args)
    {
        BufferedReader br = null;
        BufferedReader br2 = null;

        try
        {
            br = new BufferedReader(new FileReader("C:\\Users\\Desktop\\임시파일.txt"));

            System.out.println("readLine() 써서 파일 내용 읽어오는 중...");
            String contentLine = br.readLine();
            while (contentLine != null)
            {
                System.out.println("contentLine : " + contentLine);
                contentLine = br.readLine();
            }

            br2 = new BufferedReader(new FileReader("C:\\Users\\Desktop\\임시파일.txt"));
            System.out.println("read() 써서 파일 내용 읽어오는 중...");
            int num = 0;
            char ch;
            while ((num = br2.read()) != -1)
            {
                ch = (char) num;
                System.out.println("ch : " + ch);
            }
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (br != null)
                {
                    br.close();
                }
                if (br2 != null)
                {
                    br2.close();
                }
            }
            catch (IOException e)
            {
                System.out.println("BufferedReader 종료 중 에러 발생");
            }
        }
    }
}

 

위에서 만들어진 파일을 readLine()과 read()로 읽어와서 출력하는 예제다.

이걸 실행하면 아래와 같이 나온다.

 

 

readLine()의 경우 한 줄 통째로 읽어와서 보여주는 걸 볼 수 있고, read()의 경우 스페이스 바를 포함해서 한 글자씩 읽어와 출력하는 걸 볼 수 있다.

반응형

'JAVA' 카테고리의 다른 글

[JAVA] enum(열거형)이란?  (0) 2021.12.04
[JAVA] JVM의 작동원리  (0) 2021.10.08
[JAVA] SOLID 원칙이란? - 2 -  (0) 2021.07.24
[JAVA] Stream API란?  (0) 2021.07.20
[JAVA] SOLID 원칙이란? - 1 -  (0) 2021.07.19
Comments