백엔드/JAVA

입출력 스트림

두개의 문 2023. 6. 11. 17:28
입출력 스트림에 대해서

- 자바에서 데이터는 스트림(Stream)을 통해 입출력됨

- 스트림 : 단일 방향으로 연속적으로 흘러가는 것을 의미 

 

- 프로그램을 기준으로 프로세스가 데이터의 도착지라면 입력스트림(InputStream),

   프로세스가 데이터의 출발지라면 출력스트림(OutputStream)

  ※ 항상 기준은 프로그램!

 

 

 


입출력 스트림의 종류

 

- java.io 패키지에는 여러 가지 종류의 스트림 클래스를 제공하는데, 크게 두 종류로 구분됨

① 바이트(byte) 기반 스트림 : 그림, 멀티미디어 등의 바이너리 데이터를 읽고 출력할 때 사용

② 문자(text) 기반 스트림 : 문자 데이터를 읽고 출력할 때 사용

 

- 그렇다면 스트림 클래스가 바이트 기반인지, 문자기반인지 어떻게 구별할 수 있을까?

  → 하위 클래스의 경우, 클래스 접미사로 최상위 클래스의 이름이 붙는다. 최상위 클래스를 확인하자. 

 

구분 바이트 기반 스트림 문자 기반 스트림
입력 스트림 출력 스트림 입력 스트림 출력 스트림 
최상위 클래스 InputStream OutputStream Reader Writer
하위 클래스
(예시)
XXXInputStream
(FileInputStream)
XXXOutputStream
(FileOutputStream)
XXXReader
(FileReader)
XXXWriter
(FileWriter)

 

 


바이트 출력 스트림 : OutputStream

 

- OutputStream : 바이트 기반 출력 스트림의 최상위 클래스로 추상클래스

   즉, 모든 바이트 기반 출력 스트림 클래스는 OutputStream 클래스를 상속받아 생성됨

 

- OutputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음

리턴타입 메서드 설명
void write ( int b )   1byte를 출력함
void write ( byte [ ] b )   매개값으로 주어진 배열 b의 모든 바이트를 출력함
void write ( byte [ ] b, int off, int len )   매개값으로 주어진 배열 b[off]부터 len개까지의 바이트를 출력함
void flush ( )   출력 버퍼에 잔류하는 모든 바이트를 출력함
void close ( )    출력 스트림을 닫음

 

▷ write ( int b ) 메서드

- 매개 변수로 주어진 int( 4 byte )에서 4 byte를 모두 보내는 것이 아니라 끝 1byte만 출력 스트림으로 보냄 

 

( 예제 ) 10, 20, 30이 저장된 각각의 바이트를 파일 temp/test1.db로 출력해서 test1.db의 내용으로 저장해보자.

package stream.out;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class WriteExample {

	public static void main(String[] args) {
		try {
			OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test1.db");
							// java.io.FileOutputStream.FileOutputStream(String name) 
							//                           throws FileNotFoundException
			byte a = 10;
			byte b = 20;
			byte c = 30;
			
			os.write(a);	// void java.io.OutputStream.write(int b) throws IOException
			os.write(b);
			os.write(c);
			
			os.flush();		// 출력 버퍼에 잔류하는 모든 바이트 출
			os.close();		// 사용 후, 출력 스트림 항상 닫기 
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();		}
	}
}
- 데이터 도착지를 test1.db로 하는 바이트 기반 파일 출력스트림을 생성하고 OutputStream타입 변수에 대입
( 실제로 temp 폴더가 있어야 실행 결과 폴더 내에 test1.db가 생성됨 )
- 출력 스트림 : 출력할 바이트를 바로 보내는 것이 아니라 내부 버퍼(저장소)에 우선 저장해놓음
  → flush( ) 메서드 : 이 내부 버퍼에 잔류된 바이트를 모두 출력하는 역할
- OutputStream을 더 이상 사용하지 않을 경우, close( ) 메서드를 이용해 종료시키기

실행 결과, temp 폴더 내에 test1.db가 생성된 것 확인 가능
이 test1.db를 Visual Studio Code로 열어보면,,,,,, 뭐야 저거 

 

 

▷ write ( byte[ ] b ) 메서드

- 매개값으로 주어진 배열의 모든 바이트를 출력스트림으로 보냄 

 

( 예제 ) 10, 20, 30이 저장된 배열을 파일 temp/test2.db로 출력해서 test2.db의 내용으로 저장해보자.

package stream.out;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class WriteExample2 {

	public static void main(String[] args) {
		try {
			OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test2.db");
			
			byte[] array = { 10, 20, 30 };
			
			os.write(array);	// 배열의 모든 바이트를 출력 
			
			os.flush();
			os.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

▷ write ( byte[ ] b, int off, int len ) 메서드

- 매개값으로 주어진 배열 byte[off]부터 len개의 바이트를 출력 스트림으로 보냄

 

( 예제 ) 10, 20, 30, 40, 50이 저장된 배열에서 20, 30, 40을 추려서 파일 temp/test3.db로 출력해서 test3.db의 내용으로 저장해보자.

package stream.out;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class WriteExample3 {

	public static void main(String[] args) {
		try {
			OutputStream os = new FileOutputStream("/Users/dahee/Desktop/temp/test3.db");
			
			byte[] array = {10, 20, 30, 40, 50};
			
			os.write(array, 1, 3);
			
			os.flush();
			os.close();
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 


바이트 입력 스트림 : InputStream

- InputStream : 바이트 기반 입력 스트림의 최상위 클래스로 추상클래스

   즉, 모든 바이트 기반 입력 스트림 클래스는 InputStream 클래스를 상속받아 생성됨

 

- InputStream 클래스에는 모든 바이트 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음

리턴타입 메서드 설명
int read ( )   1byte를 읽고 읽은 바이트를 리턴함
int read ( byte [ ] b )   읽은 바이트를 매개값으로 주어진 배열에 저장하고 읽은 바이트 수를 리턴함
int read ( byte [ ] b, int off, int len )   len개의 바이트를 읽고 매개값으로 주어진 배열에서 b[off]부터 len개까지      저장함 그리고 읽은 바이트의 수를 리턴함
int close ( )   입력 스트림을 닫음

 

 

▷ read ( ) 메서드

- 입력 스트림으로부터 1 byte를 읽고 int(4 byte) 타입으로 리턴함

  → 4 byte 중 끝 1 byte에만 데이터가 들어있음

- 더 이상 입력 스트림으로부터 바이트를 읽을 수 없다면, read( ) 메서드는 -1을 리턴함

  → 이를 이용해 읽을 수 있는 마지막 바이트까지 반복해서 1 byte씩 읽을 수 있음

 

( 예제 ) stream.output.WriteExample에서 temp/test1.db에 저장한 내용을 1 byte씩 끝까지 읽어보자.

package stream.input;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class ReadExample {

	public static void main(String[] args) {
		
		try {
			// 데이터 스트림 출발지 : test1.db
			// 데이터 스트림 도착지 : is
			InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test1.db");
			
			while(true) {
				int data = is.read();	// 스트림에서 1byte씩 읽어오기 
				// 읽은 값이 파일의 끝인지 조사한다
				// 파일의 끝이라면 루프를 빠져 나가서 더 이상 읽기를 안함
				if(data == -1) {
					break;
				} System.out.println(data);
			}
			
			is.close(); 	// 입력 스트림 닫기 
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 

▷ read ( byte [ ] b ) 메서드 

- 입력 스트림으로부터 매개값으로 주어진 배열의 길이만큼 바이트를 읽고 해달 배열에 저장, 읽은 바이트의 수를 리턴

 

( 예제 ) 길이가 100인 배열을 생성하고 read(byte[ ] b) 메서드로 한꺼번에 100byte를 읽고 저장함

즉, 파일에 읽을 바이트가 100개 이상일 경우, 100byte를 한꺼번에 읽음

그렇지 않다면, 읽을 수 있는 바이트의 수만큼만 읽음

package stream.input;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class ReadExample2 {

	public static void main(String[] args) {
		// 데이터 스트림 출발지 : test2.db
		// 데이터 스트림 도착지 : is
		
		try {
			InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test2.db");
			
			// ① 길이가 100인 배열 생성 → 10 20 30 (한번에 읽음)
//			byte[] buffer = new byte[100];
			// ② 길이가 2인 배열 생성 → 10 20 / 30 (두번에 읽음)
			byte[] buffer = new byte[2];
			
			while(true) {
				// 배열의 길이만큼 파일로부터 데이터를 읽어옴  
				int readByteNum = is.read(buffer);
				if (readByteNum == -1) {
					// 파일의 끝에 도달하면 루프 빠져나가기 
					break;	
				}
				// 읽은 바이트 수만큼 반복하면서 배열에 저장된 바이트를 출
				for( int i = 0 ; i < readByteNum ; i++) {
					System.out.println(buffer[i]);
				}
			}
			is.close();			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 

▷ read ( byte [ ] b, int off, int len )

- 입력 스트림으로부터 len개의 바이트만큼 읽고, 매개값으로 주어진 바이트 배열 b[off]부터 len개까지 저장, 읽은 바이트의 수인 len개 리턴 ( 실제로 읽은 바이트의 수가 len개보다 작을 경우, 읽은 수만큼만 리턴함 )

- read(byte [ ] b) 메서드와 차이점

  ➊ 한번에 읽어들이는 바이트 수를 len 매개값으로 조절 가능

  ❷ 배열에서 저장이 시작되는 인덱스를 off 매개값으로 지정 가능 

  → off = 0, len = 배열의 길이로 할 경우, read(byte [ ] b) 메서드와 동일함 

 

( 예제 ) temp/test3.db에서 3byte를 읽고, 길이가 5인 배열의 배열[2], 배열[3], 배열[4]에 저장해보자

package stream.input;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class ReadExample3 {

	public static void main(String[] args) {
		try {
			InputStream is = new FileInputStream("/Users/dahee/Desktop/temp/test3.db");
			
			byte[] buffer = new byte[5];
			int readByteNum = is.read(buffer, 2, 3);
			// 입력 스트림으로부터 3byte를 읽고, buffer[2], buffer[3], buffer[4]에 각각 저장 
			
			if(readByteNum != -1) {	// 읽은 바이트가 있다면
				// 배열 전체 읽고 출력 
				for(int i = 0; i < buffer.length ; i++) {
					System.out.println(buffer[i]);
				}
			} 
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 


문자 출력 스트림 : Writer

- Writer : 문자 기반 출력 스트림의 최상위 클래스로 추상클래스

   즉, 모든 문자 기반 출력 스트림 클래스는 Writer 클래스를 상속받아 생성됨

 

 

- Writer 클래스에는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음

리턴타입 메서드 설명
void write ( int c )   매개값으로 주어진 한 문자를 보냄
void write ( char [ ] cbuf )   매개값으로 주어진 배열의 모든 문자를 보냄
void write ( char [ ] cbuf, int off, int len )   매개값으로 주어진 배열에서 cbuf[off]부터 len개까지의 문자를 보냄
void write ( String str )   매개값으로 주어진 문자열을 보냄
 void write ( String str, int off, int len )   매개값으로 주어진 문자열에서 off 순번부터 len개까지의 문자를 보냄  
void flush ( )   버퍼에 잔류하는 모든 문자를 출력
void close ( )    출력 스트림을 닫음

 

▷ write( int c ) 메서드

- 매개 변수로 주어지는 int(4 byte)에서 끝 2 byte(1개의 문자)만 출력 스트림으로 보냄

 

( 예제 ) 'A', 'B', 'C'가 저장된 각각의 char를 파일 temp/test7.txt로 출력해서 test7.txt의 내용으로 저장해보자

package stream.output;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterExample {

	public static void main(String[] args) {
		try {
			Writer writer = new FileWriter("/Users/dahee/Desktop/temp/test7.txt");
			
			char a = 'A';
			char b = 'B';
			char c = 'C';
			
			// 한 문자씩 출력 
			writer.write(a);
			writer.write(b);
			writer.write(c);
			
			writer.flush();
			writer.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

▷ write( char[ ] cbuf ) 메서드

- 매개값으로 주어지는 char[ ] 배열의 모든 문자를 출력 스트림으로 보냄

 

( 예제 ) 'A', 'B', 'C'가 저장된 배열을 파일 temp/test8.txt로 출력해서 test8.txt의 내용으로 저장해보자

package stream.output;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterExample2 {

	public static void main(String[] args) {
		try {
			Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text8.txt");
			
			char[] array = { 'A', 'B', 'C' };
            
			// 배열 전체 출력
			writer.write(array);
			
			writer.flush();
			writer.close();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

▷ write( char[ ] cbuf, int off, int len ) 메서드

- c[off]부터 len개의 문자를 출력 스트림으로 보냄

 

( 예제 ) 'A', 'B', 'C', 'D', 'E'가 저장된 배열에서 'B', 'C', 'D'을 추려서 파일 temp/test9.txt로 출력해서 test9.txt의 내용으로 저장해보자.

package stream.output;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterExample3 {

	public static void main(String[] args) {
		try {
			Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text9.txt");
			
			char[] array = {'A', 'B', 'C', 'D', 'E'};
			
			// 배열의 일부만 출력 
			writer.write(array, 1, 3);
			
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

▷ write ( String str ) 메서드, write ( String str, int off, int len ) 메서드

- 문자열을 좀 더 쉽게 보내기 위해서 

   write(String str) 메서드의 경우, 전체 문자열을 출력 스트림으로 보내고,

   write(String str, int off, int len) 메서드의 경우, 주어진 문자열의 off 순번부터 len개까지의 문자를 보냄

 

( 예제 ) 문자열 전체를 temp/test10.txt로 출력해서 test10.txt의 내용으로 저장해보자.

            문자열 일부를 temp/test11.txt로 출력해서 test11.txt의 내용으로 저장해보자.

package stream.output;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class WriterExample4 {

	public static void main(String[] args) {
		try {
			Writer writer = new FileWriter("/Users/dahee/Desktop/temp/text11.txt");
			
			String str = "안녕하세요 여러분😆";
			// ① 문자열 전체 출력 - text10.txt 
			// writer.write(str);
			// ② 문자열 일부 출력 (여러분) - test11.txt 
			//   공백도 문자열에 포함됨 
			writer.write(str, 6, 3);
			
			writer.flush();
			writer.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

 

 

 


문자 입력 스트림 : Reader

- Reader : 문자 기반 출력 스트림의 최상위 클래스로 추상클래스

   즉, 모든 문자 기반 출력 스트림 클래스는 Reader 클래스를 상속받아 생성됨

 

 

- Reader 클래스에는 모든 문자 기반 출력 스트림이 기본적으로 가져야 할 메서드가 정의되어 있음

리턴타입 메서드 설명
int read ( )   1개의 문자를 읽고 리턴함
int read ( char [ ] cbuf )   읽은 문자들을 매개값으로 주어진 문자 배열에 저장하고 읽은 문자 수를 리턴함
int read ( char [ ] cbuf, int off, int len )   len개의 문자를 읽고 매개값으로 주어진 문자 배열에서 cbuf[off]부터 len개까지      저장함 그리고 읽은 문자의 수를 리턴함
void close ( )   입력 스트림을 닫음

 

▷ read ( ) 메서드

- 입력 스트림으로부터 1개의 문자(2 byte)를 읽고 int(4 byte) 타입으로 리턴함

  리턴된 4byte 중 끝에 있는 2byte에 문자 데이터가 들어있음

- read( ) 메서드가 리턴한 int값을 char타입으로 변환하면 읽은 문자를 얻을 수 있음

char charData = (char) read();

 

 

'백엔드 > JAVA' 카테고리의 다른 글

게시판 구현 (2)  (0) 2023.06.07
게시판 구현 (1)  (0) 2023.06.02
데이터 입출력 (2)  (0) 2023.05.31
데이터 입출력(1)  (0) 2023.05.30
JDBC 드라이버 다운로드 및 등록  (0) 2023.05.23