[java] 파일 입출력

young-gue Park·2023년 7월 28일
0

Java

목록 보기
10/11
post-thumbnail

⚡ 파일 입출력


📌 I/O와 Stream

🔷 I/O

  • 데이터의 입력(Input) / 출력(Output)
  • 컴퓨터 내부 혹은 외부의 장치와 데이터를 주고 받는 행위

🔷 Stream

  • 데이터를 운반하는데 사용되는 통로
  • 물흐름과 같이 단방향으로만 통신 가능
  • 하나의 스트림을 이용하여 입력과 출력 처리 불가능

🔷 입출력 스트림

  • 바이트 스트림: byte로 구성
    • 입력 바이트 스트림(InputStream), 출력 바이트 스트림(OutputStream)
  • 문자 스트림: 문자 단위(char)로 구성
    • 입력 문자 스트림(Reader), 출력 문자 스트림(Writer)

      💡 추상 클래스로 구현되어 있다.

⭐ 바이트 스트림(byte stream)

  • 바이트 단위로 입출력

  • 주로 이진데이터를 읽고 쓰기 위해 사용

    🔷 InputStream

    메서드 명선언부와 설명
    public abstract int read()byte 하나를 읽어서 int로 반환한다. 더 이상 읽을 값이 없으면 -1을 리턴한다.
    public int read(byte b[])데이터를 읽어서 b를 채우고 읽은 바이트의 개수를 리턴한다.
    public int read(byte b[], int offset, int len)최대 len만큼 데이터를 읽어서 b의 offset부터 b에 저장하고 읽은 바이트 개수를 리턴한다.
    public void close()스트림을 종료해서 자원을 반납한다.

    🔷 OutputStream

    메서드 명선언부와 설명
    public abstract int write(int b)b의 내용을 byte로 출력한다.
    public int write(byte b[])주어진 배열 b에 저장된 모든 내용을 출력한다.
    public int read(byte b[], int off, int len)주어진 배열 b에 저장된 내용 중에서 off번째부터 len개 만큼만 읽어서 출력한다.
    public void flush()버퍼가 있는 스트림에서 버퍼의 내용을 출력하고 버퍼를 비운다.
    public void close()스트림을 종료해서 자원을 반납한다. 내부적으로 flush()를 호출한다.
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ByteStreamTest01 {
	public static void main(String[] args) {
		FileInputStream fis = null;
		FileOutputStream fos = null;
		
		try {
			fis = new FileInputStream("dog.jpg");
			fos = new FileOutputStream("dog-copy.jpg");
			
			int b; // 읽어온 데이터
			
			while((b=fis.read()) != -1) {
				fos.write(b);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				// 닫기
				if(fis != null) 
					fis.close();
				if(fos != null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}
}

⭐ 문자 스트림(character stream)

  • 문자 단위로 입출력

    🔷 Reader

    메서드 명선언부와 설명
    public int read()문자 하나를 읽어서 int로 반환한다. 더 이상 읽을 값이 없으면 -1을 리턴한다.
    public int read(char c[])데이터를 읽어서 배열 b를 채우고 읽은 char의 개수를 리턴한다.
    abstract public int read(char c[], int offset, int len)최대 len만큼 데이터를 읽어서 c의 offset부터 b에 저장하고 읽은 char 개수를 리턴한다.
    public int read(charBuffer target)데이터를 읽어서 target에 저장한다.
    public void close()스트림을 종료해서 자원을 반납한다.

    🔷 Writer

    메서드 명선언부와 설명
    public void write(int b)b의 내용을 char로 출력한다.
    public void write(char b[])주어진 배열 c에 저장된 모든 내용을 출력한다.
    abstract public void int write(char b[], int off, int len)주어진 배열 c에 저장된 내용 중에서 off번째부터 len개 만큼만 읽어서 출력한다.
    public void write(String str)주어진 문자열 str을 출력한다.
    public void write(String str, int off, int len)주어진 문자열의 일부를 출력한다.
    public void flush()버퍼가 있는 스트림에서 버퍼의 내용을 출력하고 버퍼를 비운다.
    public void close()스트림을 종료해서 자원을 반납한다. 내부적으로 flush()를 호출한다.
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CharacterStreamTest01 {
	public static void main(String[] args) throws IOException {
		
		try(FileReader reader = new FileReader("big_input.txt");
			FileWriter writer = new FileWriter("big_input_copy.txt")) {
			
			int c;
			
			while((c=reader.read()) != -1) {
				writer.write(c);
			}
		}
		
		System.out.println("끝");
	}
}

⭐ 보조 스트림

  • 스트림의 기능을 보완하기 위해 사용
  • 실제 데이터를 주고 받는 스트림이 아니므로 보조 스트림만으로 입출력 불가
  • 스트림 생성 후 보조 스트림 생성하여 사용 가능
  • 여러 보조 스트림을 연결하여 사용 가능
    new BufferedInputStream(System.in);
    new DataInputStream(new BufferedInputStream(new FileInputStream()));
  • 보조 스트림의 close()를 호출하면 노드 스트림의 close()까지 호출됨

📌 객체 직렬화

🔷 직렬화(serialization)

  • 객체가 가진 데이터를 순차적인 형태로 변환하는 절차
  • 객체를 데이터 스트림으로 만드는 것

    💡 데이터 송신을 위해 필요하다.

  • 반대의 경우 역직렬화(deserialization)

⭐ 직렬화 가능 클래스 만들기

  • serializable 인터페이스 구현(내용은 x)
  • 해당 인터페이스를 구현한 클래스를 상속받았다면 구현하지 않아도 된다.
  • 자손에만 구현했다면 조상클래스의 인스턴스 변수는 직렬화 대상에서 제외된다.
  • transient 키워드를 통해 직렬화 대상에서 제외시킬 수 있다.

🔷 serialVersionUID

  • 직렬화 된 객체를 역직렬화 할 때는 직렬화 했을 때와 같은 클래스를 사용해야 한다.
  • 따라서 해당 UID를 활용하여 클래스의 변경여부를 파악한다.
  • 작성하지 않으면 컴파일러가 자동으로 생성

    ❗ 멤버 변경시 자동 수정되어 위험하다. 따라서 작성하는 것을 권장한다.

import java.io.Serializable;

public class Person implements Serializable {
	// serialVersionUID
	private static final long serialVersionUID = -8296763453311971571L;
    
	private String name;
	private String pNum;
	
	public Person() {}
	
	public Person(String name, String pNum) {
		this.name = name;
		this.pNum = pNum;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", pNum=" + pNum + "]";
	}
}
profile
Hodie mihi, Cras tibi

0개의 댓글