본문 바로가기
Spring

[7] 자바 고급 문법 - 문자

by 민지기il 2025. 3. 28.

1) 문자 인코딩

문자 인코딩: 문자 집합을 통해 문자->숫자로 변환하는 것

문자 디코딩: 문자 집합을 통해 숫자 -> 문자로 변환하는 것

UTF-8이 현대의 표준 인코딩 기술이다 - 저장 공간 절약 & 네트워크 효율성

2) 스트림

public class FileMemberRepository implements MemberRepository {
    private static final String FILE_PATH = "temp/members-txt.dat";
    private static final String DELIMITER = ",";
    @Override
    public void add(Member member) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(FILE_PATH, UTF_8, true))){
            bw.write(member.getId() + DELIMITER + member.getName() + DELIMITER + member.getAge());
            bw.newLine(); // 다음 줄로 이동함
        }catch (IOException e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Member> findAll() {
        List<Member> members = new ArrayList<>();
        try(BufferedReader br = new BufferedReader(new FileReader(FILE_PATH, UTF_8))){
            String line;
            while((line = br.readLine()) != null){
                String [] memberData = line.split(DELIMITER);
                //파일에 읽은 데이터를 기반으로 회원 객체 생성
                members.add(new Member(memberData[0], memberData[1], Integer.valueOf(memberData[2])));
            }
            return members;
        }catch (FileNotFoundException e){
            return new ArrayList<>();
        }catch (IOException e){
            throw new RuntimeException(e);
        }
    }
}

line=br.readLine()을 통해 각 회원 하나하나를 불러온다. 

회원 데이터를 DELIMETER 구분자로 구분해서 배열에 담는다.

members.add()함수로 파일에 읽은 데이터를 기반으로 회원 객체를 생성한다. 

id,name은 String이지만 age는 문자로 조회했기 때문에 Integer로 변경해야 한다.

 

3) ObjectStream

: 회원 인스턴스는 메모리 어딘가에 보관돼있는데 이 객체를 읽어서 파일에 저장할 때 ObjectStream을 사용한다.

> 객체 직렬화

: 메모리에 있는 객체 인스턴스를 바이트 스트림으로 변환해 파일에 저장하거나 네트워크로 전송한다. 

이 과정에서 객체의 상태를 유지하여 나중에 역직렬화로 원래의 객체로 복원할 수 있다.

public class ObjectMemberRepository implements MemberRepository{
    private static final String FILE_PATH = "temp/members-txt.dat";

    @Override
    public void add(Member member) {
        List<Member> members = findAll();
        members.add(member);
        try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(FILE_PATH))){
            oos.writeObject(members);
        }catch (IOException e){
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<Member> findAll() {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(FILE_PATH))){
            Object findObject = ois.readObject();
            return (List<Member>) findObject;
        }catch (FileNotFoundException e){
            return new ArrayList<>();
        }catch (IOException | ClassNotFoundException e){
            throw new RuntimeException(e);
        }
    }
}

ObjectOutputStream로 객체 인스턴스를 직렬화해서 byte로 변경할 수 있다.

우리는 회원 객체 하나가 아니라 회원 목록 전체를 파일에 저장해야 하므로 members 컬렉션을 직렬화 해야한 다.

oos.writeObject(members)를 호출하면 members 컬렉션과 그 안에 포함된 Member를 모두 직렬화해 서 byte로 변경한다.

그리고 oos와 연결되어 있는 FileOutputStream에 결과를 출력한다.

 

4) 정리

회원 정보를 계속 유지하려면 파일에 저장해야 한다.

그런데 Member 객체는 자바 메모리에만 있는 "객체"라서, 파일에 저장하려면 byte로 변환(=직렬화) 해야 함

자바에서는 ObjectOutputStream을 이용해 객체를 직렬화할 수 있고 반대로 byte → 객체로 복원하는 건 역직렬화(ObjectInputStream)로 가능하다.

직렬화 대상 클래스인 Member에는 public class Member implements Serializable로 구현해야 함!!

- add 함수

: oos.writeObject(members)는 List<Member> 전체를 한꺼번에 byte로 변환해서 파일에 씀

그 안에 들어있는 Member 객체들도 자동으로 함께 직렬화됨

- findAll 함수

: 파일에서 읽어올 땐 readObject() 사용해서 byte를 객체로 역직렬화

저장된 전체 회원 목록을 다시 List<Member>로 되살림