2022.08.09/자바 정리/

Jimin·2022년 8월 9일
0

비트캠프

목록 보기
19/60
post-thumbnail
  • board-app 프로젝트 수행
      1. 입출력 API를 사용하여 데이터를 파일로 저장하기: 바이너리 저장(계속)
      1. Primitive 타입 및 String 타입 데이터를 가공하여 입출력하는 기능을 객체화하기
  • FileOutputStream/FileInputStream 사용법(board-app: com.bitcamp.study.*)

입출력 API를 사용하여 데이터를 파일로 저장하기: 바이너리 저장

  • 입출력 스트림 API를 사용하여 데이터를 파일로 저장하고 읽는 방법
  • 바이너리 형식으로 데이터를 입출력 하는 방법

FIleOutputStream & FIleInputStream

- 1바이트 쓰고 읽기

  • output
// FileOutputStream: write(int) 사용법
package com.bitcamp.study;

import java.io.FileOutputStream;

public class Test01_out {

  public static void main(String[] args) throws Exception{ // FIleOutputStream의 사용법을 배우는 것이 목적이지, 오류 처리하는 것이 목적이 아니기 때문이다.
    // TODO Auto-generated method stub
    FileOutputStream out = new FileOutputStream("test.data");

    // 1바이트 출력
    out.write(3278); // 0x00000cce -> 1바이트만 출력하기 때문에 ce만 출력된다.

    out.close();

    System.out.println("finish!");
  }

}
  • input
//FIleInputStream: read() 사용법
package com.bitcamp.study;

import java.io.FileInputStream;

public class Test01_in {

  public static void main(String[] args) throws Exception{
    // TODO Auto-generated method stub
    FileInputStream in = new FileInputStream("test.data");

    // 1바이트 읽기
    int b = in.read(); // 얘가 int 값 받는다고 해서 read가 4바이트를 읽는 것은 아니다!
    System.out.printf("%08x\n", b);

    in.close();
    System.out.println("finish!");
  }

}

- 4바이트 쓰고 읽기

  • output
// FileOutputStream: write(int) 사용법
package com.bitcamp.study;

import java.io.FileOutputStream;

public class Test02_out {

  public static void main(String[] args) throws Exception{ // FIleOutputStream의 사용법을 배우는 것이 목적이지, 오류 처리하는 것이 목적이 아니기 때문이다.
    // TODO Auto-generated method stub
    FileOutputStream out = new FileOutputStream("test2.data");

    // 4바이트 출력
    out.write(3278 >> 24); //             00|000cee
    out.write(3278 >> 16); //        0000|0cce
    out.write(3278 >> 8); //      00000c|ce
    out.write(3278); //            0x00000cce -> 1바이트만 출력하기 때문에 ce만 출력된다.

    out.close();

    System.out.println("finish!");
  }

}
  • input
//FIleInputStream: read() 사용법
package com.bitcamp.study;

import java.io.FileInputStream;

public class Test02_in {

  public static void main(String[] args) throws Exception{
    // TODO Auto-generated method stub
    FileInputStream in = new FileInputStream("test2.data");

    // 4바이트 읽기
    int result = 0;
    int b = in.read(); // 얘가 int 값 받는다고 해서 read가 4바이트를 읽는 것은 아니다!
    result += b << 24;
    System.out.printf("%08x\n", b);

    b = in.read(); // 얘가 int 값 받는다고 해서 read가 4바이트를 읽는 것은 아니다!
    result += b << 16;

    System.out.printf("%08x\n", b);

    b = in.read(); // 얘가 int 값 받는다고 해서 read가 4바이트를 읽는 것은 아니다!
    result += b << 8;

    System.out.printf("%08x\n", b);

    b = in.read(); // 얘가 int 값 받는다고 해서 read가 4바이트를 읽는 것은 아니다!
    result += b;
    System.out.printf("%08x\n", b);
    System.out.println(result);
    in.close();
    System.out.println("finish!");
  }

}

-1을 리턴하면 더 이상 리턴할 것이 없다는 뜻이다.


Primitive type 및 String type 데이터를 가공하여 입출력하는 기능 객체화하기

  • Primitive 타입과 String 타입의 값을 쉽게 입출력해
  • Primitive 타입 및 String 타입 데이터를 가공하여 String 타입의 값을 바이트 또는 바이트 배열로 가공하는 기능을 객체화 한다.
  • 중간에서 공해주는클래스를 만드들어 클래스

1단계 - Primitive type 또는 String type 을 바이트 또는 바이트 배열로 가공하여 출력하는 일을 할 클래스를 정의한다.

  • util.DataOutputStream 클래스 생성
  • DataOutputStream class
package com.bitcamp.util;

import java.io.FileOutputStream;
import java.io.IOException;

// Primitive 타입이나 String 타입의 값을 바이트 또는 바이트 배열로 만들어 
// 의존 객체를 사용하여 출력하는 일을 한다.
// => 즉 출력 데이터를 중간에서 가공하는 일을 한다.
public class DataOutputStream implements AutoCloseable {
  FileOutputStream out;

  public DataOutputStream(FileOutputStream out) {
    this.out = out;
  }

  @Override
  public void close() throws IOException {
    out.close();
  }

  public void writeByte(byte value) throws Exception {
    out.write(value);
  }

  public void writeShort(short value) throws Exception {
    out.write(value >> 8);
    out.write(value);
  }

  public void writeInt(int value) throws Exception {
    out.write(value >> 24);
    out.write(value >> 16);
    out.write(value >> 8);
    out.write(value);
  }

  public void writeLong(long value) throws Exception {
    out.write((int)(value >> 56));
    out.write((int)(value >> 48));
    out.write((int)(value >> 40));
    out.write((int)(value >> 32));
    out.write((int)(value >> 24));
    out.write((int)(value >> 16));
    out.write((int)(value >> 8));
    out.write((int)(value));
  }

  public void writeFloat(float value) throws Exception {
    int temp = Float.floatToIntBits(value);
    writeInt(temp);
  }

  public void writeDouble(double value) throws Exception {
    long temp = Double.doubleToLongBits(value);
    writeLong(temp);
  }

  public void writeBoolean(boolean value) throws Exception {
    out.write(value ? 1 : 0);
  }

  public void writeUTF(String str) throws Exception {
    byte[] bytes = str.getBytes("UTF-8");

    out.write(bytes.length >> 24);
    out.write(bytes.length >> 16);
    out.write(bytes.length >> 8);
    out.write(bytes.length);
    out.write(bytes);
  }


}

2단계 - 바이트 또는 바이트 배열을 읽어 Primitive type 또는 String type의 값으로 변환시켜줄 클래스를 정의한다.

  • util.DataInputStream 클래스 생성
  • DataInputStream class
package com.bitcamp.util;

import java.io.FileInputStream;
import java.io.IOException;

public class DataInputStream implements AutoCloseable {
  FileInputStream in;

  public DataInputStream(FileInputStream in) {
    this.in = in;
  }

  @Override
  public void close() throws IOException {
    in.close();
  }

  public byte readByte() throws Exception {
    return (byte) in.read();
  }

  public short readShort() throws Exception {
    int result = (in.read() << 8) + in.read();
    return (short) result;
  }

  public int readInt() throws Exception {
    return (in.read() << 24) + (in.read() << 16) + (in.read() << 8) + in.read();
  }

  public long readLong() throws Exception {
    return ((long)in.read() << 56) 
        + ((long)in.read() << 48) 
        + ((long)in.read() << 40)
        + ((long)in.read() << 32)
        + ((long)in.read() << 24)
        + ((long)in.read() << 16)
        + ((long)in.read() << 8)
        + in.read();
  }

  public float readFloat() throws Exception {
    int value = readInt();
    return Float.intBitsToFloat(value);
  }

  public double readDouble() throws Exception {
    long value = readLong();
    return Double.longBitsToDouble(value);
  }

  public boolean readBoolean() throws Exception {
    return in.read() == 1 ? true : false;
  }

  public String readUTF() throws Exception {
    int len = readInt();
    byte[] bytes = new byte[len];
    in.read(bytes);
    return new String(bytes, "UTF-8");
  }


}

3단계 - XxxDao에서 데이터를 읽거나 쓸 때 DataInputStream/DataOutputStream을 사용한다.

  • board.dao.XxxDao 클래스 변경
  • BoardDao class
package com.bitcamp.board.dao;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.bitcamp.board.domain.Board;
import com.bitcamp.util.DataInputStream;
import com.bitcamp.util.DataOutputStream;

// 게시글 목록을 관리하는 역할
//
public class BoardDao {

  List<Board> list = new LinkedList<>();
  private int boardNo = 0;
  String filename;

  public BoardDao(String filename) {
    this.filename = filename;
  }

  public void load() throws Exception {
    try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
      int size = in.readInt();
      for (int i = 0; i < size; i++) {
        Board board = new Board();
        board.no = in.readInt();
        board.title = in.readUTF();
        board.content = in.readUTF();
        board.writer = in.readUTF();
        board.password = in.readUTF();
        board.viewCount = in.readInt();
        board.createdDate = in.readLong();

        list.add(board);
        boardNo = board.no;
      }
    }
  }

  public void save() throws Exception {
    try (DataOutputStream out = new DataOutputStream(new FileOutputStream(filename))) {
      out.writeInt(list.size());
      for (Board board : list) {
        out.writeInt(board.no);
        out.writeUTF(board.title);
        out.writeUTF(board.content);
        out.writeUTF(board.writer);
        out.writeUTF(board.password);
        out.writeInt(board.viewCount);
        out.writeLong(board.createdDate);
      }
    }
  }

  public void insert(Board board) {
    board.no = nextNo();
    list.add(board);
  }

  public Board findByNo(int boardNo) {
    for (int i = 0; i < list.size(); i++) {
      Board board = list.get(i);
      if (board.no == boardNo) {
        return board;
      }
    }
    return null;
  }

  public boolean delete(int boardNo) {
    for (int i = 0; i < list.size(); i++) {
      Board board = list.get(i);
      if (board.no == boardNo) {
        return list.remove(i) != null;
      }
    }
    return false;
  }

  public Board[] findAll() {

    // 목록에서 값을 꺼내는 일을 할 객체를 준비한다.
    Iterator<Board> iterator = list.iterator();

    // 역순으로 정렬하여 리턴한다.
    Board[] arr = new Board[list.size()];

    int index = list.size() - 1;
    while (iterator.hasNext()) {
      arr[index--] = iterator.next();
    }
    return arr;
  }

  private int nextNo() {
    return ++boardNo;
  }
}
  • MemberDao class
package com.bitcamp.board.dao;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import com.bitcamp.board.domain.Member;
import com.bitcamp.util.DataInputStream;
import com.bitcamp.util.DataOutputStream;

// 회원 목록을 관리하는 역할
//
public class MemberDao {

  List<Member> list = new LinkedList<Member>();
  String filename;

  public MemberDao(String filename) {
    this.filename = filename;
  }

  public void load() throws Exception {
    try (DataInputStream in = new DataInputStream(new FileInputStream(filename))) {
      int size = in.readInt();
      for (int i = 0; i < size; i++) {
        Member member = new Member();
        member.no = in.readInt();
        member.name = in.readUTF();
        member.email = in.readUTF();
        member.password = in.readUTF();
        member.createdDate = in.readLong();
        list.add(member);
        System.out.println("============>");
      }
    } // try () ==> try 블록을 벗어나기 전에 in.close()가 자동으로 실행된다.
  }

  public void save() throws Exception {
    try (DataOutputStream out = new DataOutputStream(new FileOutputStream(filename))) {
      out.writeInt(list.size());
      for (Member member : list) {
        out.writeInt(member.no);
        out.writeUTF(member.name);
        out.writeUTF(member.email);
        out.writeUTF(member.password);
        out.writeLong(member.createdDate);
      }
    } // try () ==> try 블록을 벗어나기 전에 out.close()가 자동으로 실행된다.
  }

  public void insert(Member member) {
    list.add(member);
  }

  public Member findByEmail(String email) {
    for (int i = 0; i < list.size(); i++) {
      Member member = list.get(i);
      if (member.email.equals(email)) {
        return member;
      }
    }
    return null;
  }

  public boolean delete(String email) {
    for (int i = 0; i < list.size(); i++) {
      Member member = list.get(i);
      if (member.email.equals(email)) {
        return list.remove(i) != null;
      }
    }
    return false;
  }

  public Member[] findAll() {
    Iterator<Member> iterator = list.iterator();

    Member[] arr = new Member[list.size()];

    int i = 0;
    while (iterator.hasNext()) {
      arr[i++] = iterator.next(); 
    }
    return arr;
  }
}
profile
https://github.com/Dingadung

0개의 댓글