자바(JAVA)

자바 - 입/출력(IO, Input/Output)

BlueNoa 2023. 10. 5. 02:38
728x90
반응형

<목차>

 

 


• 자바의 입출력 방법

자바에서는 다양한 입출력 방법을 제공하고 있다. 입출력이란 데이터를 읽고 쓰는 과정을 의미하며, 다양한 소스와 대상 간의 데이터 전송을 다룬다. 각각의 유형에 대해 설명하면 다음과 같다.

 

자바의 입출력 유형

1. 콘솔 입력과 출력(Console I/O)

- 콘솔 입력은 주로 키보드로부터 입력 받는 것을 의미한다.

- 콘솔 출력화면에 정보를 표시하는 과정을 의미한다.

- 'System.in'은 Standard Input으로, 'System.out'과 'System.err'는 Standard Output으로 사용된다.

 

2. 파일 입출력(File I/O)

- 파일 입출력은 파일에서 데이터를 읽어오거나 파일에 데이터를 쓰는 과정을 의미한다.

- 'java.io' 패키지의 클래스를 통해 파일 입출력을 수행한다.

- 대표적인 예로 'FileInputStream', 'FileOutputStream', 'FileReader', 'FileWreter' 등의 클래스가 있다.

 

3. 네트워크 입출력(Network I/O)

- 네트워크 입출력은 네트워크를 통해 데이터를 송수신하는 과정을 의미한다.

- 'java.net' 패키지의 클래스들을 사용하여 네트워크 통신을 수행한다.

- 소켓(Socket)을 생성하고 데이터를 전송하거나 수신한다.

 

4. 직렬화(Serialization)

- 직렬화는 객체를 *바이트 스트림으로 변환하는 과정을 의미한다.

- 'java.io.Serializable' 인터페이스를 구현한 클래스의 객체는 직렬화를 통해 파일에 저장하거나 네트워크 전송이 가능하다.

- 역직렬화를 통해 바이트 스트림을 다시 객체로 변환하는 것이 가능하다.

 

※ 바이트 스트림(Byte Streams)이란?

데이터를 바이트(byte) 단위로 처리하는 스트림이다. 텍스트와 같은 문자 데이터 뿐만 아니라 모든 종류의 데이터(오디오, 이미지, 비디오 등)를 이진 데이터 처리하는 데 사용된다. 

 

입출력 클래스와 메서드

자바의 입출력 클래스들은 'InputStream', 'OutputStream', 'Reader', 'Writer' 등과 같은 추상 클래스를 기반으로 하고 있으며, 해당 클래스들을 사용하여 입출력 작업을 수행한다. 각 클래스는 다양한 하위 클래스를 갖고 있다.

또한 입출력 작업은 예외 처리가 필요하므로 'try - catch' 블록을 사용하여 예외 처리를 해야만 한다.

 

예외 처리

입출력 작업은 파일이 존재하지 않거나 권한이 없는 경우 등 예상할 수 없는 상황이 발생하는 것을 대비하여 준비해놓는 작업이다. 따라서 입출력 코드는 예외 처리를 통해 오류를 관리해야 한다. 주로 'IOException'를 통해 예외 처리를 한다.

 

반응형

• 콘솔 입출력(Console Input/Output)

콘솔 입출력은 키보드로부터 입력을 받아 화면에 출력을 표시하는 작업이다. 이를 위해 자바에서 'System' 클래스의 'in'과  'out' 객체를 사용하여 구현한다.

 

각 예시를 순서대로 byte, char, String 데이터를 읽는다고 생각하면 좋다.

그리고 각 예시에 try - catch 문을 사용하여 예외처리도 하였다. 간단히 설명하면 try에서는 실행문을 작성하고 catch문은 오류 내용을 출력하는 역할을 한다.

 

InputStream

'java.io.InputStream'은 자바에서 바이트 기반 입력 스트림을 처리하기 위한 추상 클래스다.

해당 클래스를 사용하면 파일, 네트워크, 키보드 등 다양한 자료로부터 바이트 데이터를 읽어올 수 있다.

 

<예시 - InputStream>

더보기
import java.io.InputStream;
import java.io.IOException;


public class sample {
    public static void main (String[] args) throws IOException {
        try {
            InputStream value = System.in; // 값을 받아오는 역할

            byte[] a = new byte[4];
            int byteValues = 0; // 읽은 바이트 수
            while (byteValues < a.length) {
                int byteValue = value.read(); // 바이트 하나씩 읽기
                if (byteValues == '\n' || byteValues == '\r') { // 엔터 입력하면 입력을 종료
                    break;
                }
                a[byteValues] = (byte) byteValue; // 하나씩 읽은 바이트를 저장
                byteValues++; // 읽은 바이트의 수 증가
            }
			// 출력
            for (int i = 0; i < byteValues; i++) {
                System.out.println(a[i]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

<결과>

made <- 입력값
109
97
100
101

 

InputStreamReader

위 예시를 보면 알겠지만 문자를 입력하면 아스키 코드로 변환해서 출력한다. 이는 사람이 보기에는 매우 불편하다. 때문에 바이트 기반의 입력 스트림인 'InputStream'을 문자 기반의 입력 스트림인 'Reader'로 변환해주는 클래스이다.

해당 클래스는 주로 텍스트 파일을 읽거나 네트워크로부터 텍스트 데이터를 읽어올 때 사용된다.

 

<예시 - InputStreamReader>

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'


public class sample {
    public static void main (String[] args) throws IOException {
        try {
            InputStream value = System.in; // 값을 받아오는 역할
            InputStreamReader reader = new InputStreamReader(value);

            char[] a = new char[4];
            int charValues = 0;
            while (charValues < a.length) {
                int charValue = reader.read();
                if (charValues == '\n' || charValues == '\r') {
                    break;
                }
                a[charValues] = (char) charValue;
                charValues++;
            }

            for (int i = 0; i < charValues; i++) {
                System.out.println(a[i]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

해당 코드는 위에서 처음 예시 글을 변형하여 만들었다. 기존에 byte로 선언된 배열을 char 배열을 사용하여 InputStreamReader를 이용했다. 만약 글자 하나하나 출력하는 것이 싫다면 그냥 'System.out.println(a)'를 사용하면 된다.

<결과>

made <- 입력값
m
a
d
e

 

BufferedReader

입력 스트림을 버퍼링(고정되지 않는다.)하여 효율적으로 문자열을 읽을 수 있게 해주는 클래스이다. 버퍼링은 데이터를 한 번에 조각조각 읽어오는 것보다 효율적인 방식으로 데이터를 읽어올 수 있도록 도와준다.

 

<예시 - BufferedReader>

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'

public class sample {
    public static void main (String[] args) throws IOException {
        try {
            InputStream value = System.in; // 값을 받아오는 역할
            InputStreamReader reader = new InputStreamReader(value);
            BufferedReader br = new BufferedReader(reader);

            String result = br.readLine(); // 입력한 문자열 전체를 읽어올 수 있다.
            System.out.println(result);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

만약 BufferedInputStream을 사용해서 값을 읽어왔다면 한 번에 읽어와서 처리했을 것이다. 여러 가지 클래스가 있으므로 한 번 찾아보는 것도 좋다.

 

<결과>

made <- 입력값
made

 

Scanner

스캐너는 사용자의 입력을 읽는 데 사용되는 클래스다. 해당 입력값을 원하는 형식으로 파싱하고 처리할 수 있다.

해당 클래스를 사용하기 위해서는 객체를 생성해야 하며 'System.in'을 'Scanner'의 생성자로 전달해서 사용한다.

 

Scanner와 관련된 메서드로는 다음과 같이 있다.

1. next() : 공백 문자를 기준으로 문자열을 읽는다.

2. nextInt() : 정수 값을 읽는다.

3. nextDouble() : 실수 값을 읽는다.

4. nextLine() : 한 줄의 문자열을 읽는다. 공백을 포함한 전체 줄을 읽는다.

5. hasNext() : 입력에서 다음 토큰(문자열, 정수, 실수 등)이 있는지 확인한다.

 

<예제 - Scanner>

더보기
import java.util.Scanner;

public class sample {
    public static void main (String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);

        System.out.println("이름을 입력해주세요 : ");
        String name = sc.next();
        System.out.println("학번을 입력해주세요 : ");
        int stNum = sc.nextInt();

        System.out.println("안녕하세요. " + stNum + "학번 " + name + "님 ");
    }
}

<결과>

이름을 입력해주세요 : 
이순신
학번을 입력해주세요 : 
20
안녕하세요. 20학번 이순신님 

 

System.out과 System.err

이전 게시물을 포함한 지금의 게시글에서도 계속해서 나오는 문장이 있다. 'System.out.println'은 콘솔에 값을 출력한 후 한 줄을 띄어서 입력하는 메서드다. 이와 마찬가지로 'System.out.print' 문은 엔터만 입력되지 않고 문자만 출력하는 키워드다. 이와 유사하게 'System.out.err'가 존재하는데 역할을 동일하나 오류가 발생했을때 출력된다는 조건이 있다.

 

728x90

• 파일 입출력(File Input/Output)

파일을 읽고 쓰는 기본적인 기능으로 다음과 같은 클래스들을 지원한다.

 

File

파일 및 디렉토리의 경로를 나타내는 클래스로, 생성과 삭제, 이름 변경 등의 작업을 수행한다.

FileInputStream / FileOutputStream

파일로부터 바이트를 읽거나 쓰는 데 사용되는 클래스

 

FileReader 및 FileWriter

파일로부터 문자를 읽거나 쓰는 데 사용되는 클래스

 

BufferedReader 및 BufferedWriter

버퍼링된 파일 입력 및 출력을 수행하기 위한 클래스이며 한 번에 한 줄씩 데이터를 읽을 수 있다.

 

<예시1 - File : 파일 생성>

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'

public class sample {
    public static void main (String[] args) {
        String fileName = "out.txt";
        String data = "Hello!";

        // 파일이 존재하지 않을 때만 생성하고 데이터 출력
        File file = new File(fileName);
            if (!file.exists()) {
                try {
                    FileWriter writer = new FileWriter("C:/Users/사용자명/OneDrive/Desktop/" + file);
                    writer.write(data);
                    writer.close();
                    System.out.println("파일을 생성 완료!");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
                System.out.println("파일이 이미 존재합니다.");
        }
    }
}

FileWriter를 사용하면 \r 또는 \n을 문자열에 입력해줘야지만 행 바꿈이 된다.

이런 것이 불편하다면 PrintWriter를 사용하면 된다. 그렇게 하면 println을 사용할 수 있다.

 

*FileReader를 사용하여 줄 단위로 문자열을 읽어올 수 있다.

 

<예시2 - FileOutputStream / FileInputStream>

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'

public class sample {
    public static void main (String[] args) {
        String fileName = "output.txt";
        String data = "파일 내용!";
        String local = "C:/Users/사용자명/OneDrive/Desktop/";

        try {
            FileOutputStream output = new FileOutputStream(local + fileName);
            byte[] byteData = data.getBytes(); // 문자열을 바이트 배열로 변환
            output.write(byteData);

            output.close();

            FileInputStream input = new FileInputStream(local + fileName);
            // 한글 깨짐 방지
            InputStreamReader reader = new InputStreamReader(input, "UTF-8");

            int datas; // 정보를 받아오기 위한 변수
            while ((datas = reader.read()) != -1) { // 파일의 끝(-1)이 아니면 계속 불러온다.
                System.out.print((char) datas);
            }
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileOutputStream을 사용할 때 문자열을 바이트 배열로 변환한 후 'write()' 메서드를 사용하여 파일에 데이터를 쓸 수 있다. 파일이 이미 존재하면 이전 데이터는 덮어쓰게 된다.

 

<예제3 - BufferedReader 및 BufferedWriter>

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'

public class sample {
    public static void main (String[] args) {
        String fileName = "output.txt";
        String data = "Buffered!!!\n파일내용!";
        String local = "C:/Users/사용자명/OneDrive/Desktop/";

        try {
            BufferedWriter buffw = new BufferedWriter(new FileWriter(local + fileName));
            buffw.write(data);
            buffw.newLine(); // 줄 이동
            buffw.write("새 라인에서 입력한 글");

            buffw.close();

            BufferedReader buffr = new BufferedReader(new FileReader(local + fileName));
            String line; // 줄 단위로 읽어와서 저장할 변수
            while ((line = buffr.readLine()) != null) { // readLine()은 행 단위로 값을 가져온다.
                System.out.println(line);
            }
            buffr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedWriter는 줄 단위로 읽어올 수 있기 때문에 좀 더 편하다.

<결과>

Buffered!!!
파일내용!
새 라인에서 입력한 글

 

파일 내용 추가 및 삭제하기

파일을 생성하고 읽는 것 뿐만 아니라 내용을 추가하거나 삭제하는 것도 가능하다.

더보기
import java.io.*; // 모든 클래스를 가져오는 '*'

class Reader {
    public String fileName = "output.txt";
    public String local = "C:/Users/사용자명/OneDrive/Desktop/";
    // 파일 읽어오기
    public void readFile() {
        try {
            FileReader fr = new FileReader(local + fileName);
            BufferedReader br = new BufferedReader(fr);
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
            br.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


public class sample {
    public static void main (String[] args) {
        String data = "기본 내용입니다.";
        String appendData = "추가된 내용입니다.";
        Reader reader = new Reader();

        try {
            // 파일 생성
            FileWriter fw = new FileWriter(reader.local + reader.fileName);
            fw.write(data);
            fw.close(); reader.readFile(); // 읽기 실행
            
            // 파일 내용 추가 true : 추가 모드로 설정
            FileWriter fwa = new FileWriter(reader.local + reader.fileName, true);
            fwa.write("\n" + appendData);
            fwa.close(); reader.readFile(); // 읽기
            
            // 파일 삭제
            File file = new File(reader.local + reader.fileName);
            if (file.exists()) {
                if (file.delete()) {
                    System.out.println("파일 삭제 완료");
                } else {
                    System.out.println("파일 삭제 실패");
                }
            } else {
                System.out.println("파일이 존재하지 않습니다.");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

<결과>

기본 내용입니다.
기본 내용입니다.
추가된 내용입니다.
파일 삭제 완료

 

 

 

 

728x90
반응형