45일차 (1) - java (파일 입출력)

Yohan·2024년 4월 24일
0

코딩기록

목록 보기
65/156
post-custom-banner

파일 입출력 (IO)

파일, 폴더 생성

  • File을 import하여 폴더, 파일을 생성할 수 있다.
package day12.io;

import java.io.File;
import java.io.IOException;

public class FileExample {

    // 파일을 저장할 기본 경로
    public static final String ROOT_PATH = "C:/Users/smr78/OneDrive/바탕 화면/yocong";

    public static void main(String[] args) {

        // 폴더 생성 명령
        // 파일 정보 객체 생성
        File directory = new File(ROOT_PATH + "/hello");

        // 폴더 생성 (hello 폴더)
        if (!directory.exists()) directory.mkdir();

        // 파일 생성하기 (food.txt)
        File newFile = new File(ROOT_PATH + "/hello/food.txt");

        if (!newFile.exists()) {
            try {
                newFile.createNewFile();
            } catch (IOException e) {
                System.out.println("존재하는 파일입니다.");
            }
        }
    }
}

Stream이란?

  • 데이터가 들어오면 입력 스트림
  • 데이터가 나가면 출력 스트림
  • 스트림 클래스는 크게 두 종류로 구분 (byte기반, 문자 기반)
  • byte 기반의 입,출력 스트림의 최상위 클래스 InputStream과 OutputStream.
  • 문자 기반의 입, 출력 스트림의 최상위 클래스 Reader와 Writer.

InputStream 클래스

  • byte 기반의 입력 스트림

주요 메서드

  1. read(): 입력 스트림으로부터 1바이트를 읽고 읽은 바이트를 리턴.
  2. read(byte[] b): 입력 스트림으로부터 읽은 바이트들을 매개값으로 주어진 바이트 배열에 저장하고 실제로 읽은 바이트 수를 리턴
    public static void main(String[] args) {

        try (FileInputStream fis = new FileInputStream(FileExample.ROOT_PATH + "/hello/pet.txt")) {

            int data = 0; // 세이브파일 로드 명령
            while ((data = fis.read()) != -1) {

                // write() : 아스키코드를 문자로 출력
                System.out.write(data);
            }
            // 출력 버퍼 비우기
            System.out.flush();

        } catch (FileNotFoundException e) {
            System.out.println("해당 경로를 찾을 수 없습니다.");
        } catch (IOException e) {
            System.out.println("출력 시스템에 장애가 발생했습니다.");
        }
	 }

byte기반 OutputStream 클래스

  • byte 기반의 출력 스트림

주요 메서드

  1. write(byte b): 출력 스트림으로 1바이트를 내보냄.
  2. write(byte[] b): 출력 스트림으로 주어진 바이트 배열 b의 모든 바이트들을 내보냄.
public class FileOutputExample {

    public static void main(String[] args) {

        String message = "멍멍이는 멍멍멍 왈왈왈! 야옹이는 냐냐냥~";


        // try의 ()안에 입력해주는 코드는 자동으로 close해줌 -> finally에 close 할 필요 X
        try (FileOutputStream fos = new FileOutputStream(FileExample.ROOT_PATH + "/hello/pet.txt")) {
            fos.write(message.getBytes()); // 세이브파일 생성 명령, byte 기반이기 떄문에 byte로 변환
        } catch (FileNotFoundException e) {
            System.out.println("해당 경로를 찾을 수 없습니다.");
        } catch (IOException e) {
            System.out.println("출력 시스템에 장애가 발생했습니다.");
        }
    }
}
  • try with resource : close가 필요한 하드웨어 접근 코드에 대해 메모리 자원 반납 처리를 자동화해주는 문법
    -> 쉽게 이야기하면 try의 () 안에 있는 코드는 try ~ catch문이 끝나면 자동으로 close 된다는 이야기다.

문자 기반 Writer 클래스

  • 문자 기반의 입력 스트림
    public static void main(String[] args) {

        String targetPath = FileExample.ROOT_PATH + "/hello/hobby.txt";

        try (FileWriter fw = new FileWriter(targetPath)) {
            String hobby = SimpleInput.input("취미를 입력하세요!!\n>>");
            String outputMessage = String.format("내 취미는 %s입니다.\n", hobby);

            // 파일 생성 명령
            fw.write(outputMessage);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • FileWriter를 사용하여 파일에 쓰기를 수행
  • 입력한 것이 hobbt.txt 파일에 들어간다. outputMessage에 있는 내용 안으로 입력한 것이 들어간다.

문자 기반 Reader 클래스

  • 문자 기반의 출력 스트림
    public static void main(String[] args) {

        String targetPath = FileExample.ROOT_PATH + "/hello/member.txt";

        try (FileReader fr = new FileReader(targetPath)) {

            // 보조 스트림 활용
            // 텍스트를 라인단위로 읽어들이는 보조스트림
            BufferedReader br = new BufferedReader(fr);

            // 회원정보를 저장할 리스트 생성
            List<Member> memberList = new ArrayList<>();

            while (true) {
                String s = br.readLine();

                if (s == null) break;

                String[] split = s.split(",");
                // 읽어들인 회원정보로 회원 객체 생성
                Member member = new Member(
                        split[0],
                        split[2],
                        split[1],
                        split[3],
                        Integer.parseInt(split[4])
                );
//                System.out.println("member = " + member);
                memberList.add(member);
            }
            System.out.println(memberList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • BufferedReader 보조 스트림을 이용해 텍스트를 라인단위로 읽어들였다.
FileInputStream fis = new FileInputStream(new File("test.txt"));
BufferedInputStream bis = new BufferedInputStream(fis);

Writer rt = new FileWriter("파일 경로");
BufferedWriter bw = new BufferedWriter(rt);

Reader rd = new FileReader("파일 경로");
BufferedReader bf = new BufferedReader(rd);

-> BufferedReader, BufferedWriter 를 사용하면 비용과 속도적인 측면에서 빠르고 효율적이다.

Writer, Reader를 활용하여 파일에 저장하고 세이브된 파일을 불러와보기

  • 예전에 진행했던 Member에서 내가 적은 정보가 저장되고 다시 실행해도 세이브되어있게 해보았다.
		// 회원정보 텍스트파일에 저장하기
        try (FileWriter fw = new FileWriter(FileExample.ROOT_PATH + "/hello/member.txt", true)) {

            String newMemberInfo = String.format("%s,%s,%s,%s,%d\n"
                    , newMember.email, newMember.memberName
                    , newMember.password, newMember.gender, newMember.age);

            fw.write(newMemberInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • FileWriter를 사용하여 "member.txt" 파일을 열어주고 경로를 지정한다.
    true를 두 번째 매개변수로 전달하여 파일의 기존 내용 끝에 새로운 내용을 추가할 수 있게 해줬다.
  • fw.write(); 를 사용하여 새로운 회원 정보를 추가한다.
	// 회원 정보 세이브파일 불러오기
    public void loadFile() {
        String targetPath = FileExample.ROOT_PATH + "/hello/member.txt";

        try (FileReader fr = new FileReader(targetPath)) {

            // 보조 스트림 활용
            // 텍스트를 라인단위로 읽어들이는 보조스트림
            BufferedReader br = new BufferedReader(fr);

            // 회원정보를 저장할 리스트 생성
            List<Member> memberList = new ArrayList<>();

            while (true) {
                String s = br.readLine();

                if (s == null) break;

                String[] split = s.split(",");
                // 읽어들인 회원정보로 회원 객체 생성
                Member member = new Member(
                        split[0],
                        split[2],
                        split[1],
                        split[3],
                        Integer.parseInt(split[4])
                );
                this.members.push(member);
            }
            System.out.println(memberList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 보조 스트림을 활용하여 읽어와서 Member 객체로 변환하고, 이를 리스트에 저장한다.

객체를 파일에 저장하려면 직렬화가 필요 (serialize)

  • 객체를 파일에 저장하려면 직렬화가 필요하다.
  • write 할 때 serialize를 (직렬화) 확인하고 안되어있으면 implements serializabl 해준다.
package day12.io.obj;

import day12.io.FileExample;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.List;

public class SaveSnack {

    public static void main(String[] args) {

        List<Snack> snackList = List.of(
                new Snack("콘칲", 1970, 1500, Snack.Taste.GOOD)
                , new Snack("사브레", 1980, 2500, Snack.Taste.BAD)
                , new Snack("오징어집", 1985, 1800, Snack.Taste.SOSO)
        );

        try (FileOutputStream fos = new FileOutputStream(FileExample.ROOT_PATH + "/hello/snack.sav")) {

            // 객체를 통째로 저장할 수 있는 보조 스트림
            // serialize: 직렬화 - 데이터를 일렬로 늘여뜨려 놓는 것
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(snackList);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • Snack 객체 리스트를 파일에 저장하려고 할 때 직렬화가 필요하기 때문에 Snack 클래스에 implements Serializable 해준다.
public class Snack implements Serializable {
  • 그러면 파일이 저장이 되고 세이브된 파일을 다시 불러올 수 있다.
public static void main(String[] args) {

        // 세이브 파일 로딩하기
        try (FileInputStream fis = new FileInputStream(FileExample.ROOT_PATH + "/hello/snack.sav")) {

            // 객체를 로딩할 보조 스트림
            ObjectInputStream ois = new ObjectInputStream(fis);
            List<Snack> snackList = (List<Snack>) ois.readObject();

            System.out.println("snackList = " + snackList);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
profile
백엔드 개발자
post-custom-banner

0개의 댓글