I/O 스트림 : 데이터 이동 통로, 단방향(입력, 출력), 지연(버퍼가 존재) 

바이트기반 스트림 (1바이트 단위) - InputStream, OutputStream 

 - 기반스트림 : FileInputStream&FileOutputStream

 - 보조스트림 : in -> DataInputStream, BufferedInputStream, ObjectInputStream

                    out -> DataOutputStream, BufferedOutputStream, ObjectOutputStream, PrintStream

 - 모든 스트림의 조상은 InputStream, OutputStream

 - 모든 보조스트림의 조상은 FilterInputStream, FilterOutputStream

 - 그림, 멀티미디어, 문자 등 모든 종류

FileInputStream fis = new FileInputStream("src/ch15/InputStreamEx1.java");
		// int read() - 1byte씩, 읽어온 바이트를 int로 리턴
		int data = 0;
		while ((data = fis.read()) != -1) {
			System.out.print((char) data);
		}

		// int read(byte[] buf) - 배열 크기씩, 읽은 바이트들을 buf로 바이트수를 int로 리턴
		fis = new FileInputStream("src/ch15/FileInputStreamEx1.java");
		byte[] buf = new byte[fis.available()];		// 글자수만큼 배열 생성
		while ((data = fis.read(buf)) != -1) {		// read(buf)로 읽어온 글자수를 data에 넣음
			System.out.println(new String(buf, 0, data));
		}
		
		// int read(byte[] buf, int offset, int len)
		fis = new FileInputStream("src/ch15/FileInputStreamEx1.java");
		buf = new byte[fis.available()];
		while ((data = fis.read(buf, 0, buf.length)) != -1) {
			System.out.println(new String(buf, 0, data));
		}
FileOutputStream fos = new FileOutputStream(new File("src/ch15/out.txt"));
		fos.write('1');	fos.write('2');	fos.write('3');	// void write(int)
		= fos.write(49)            50             51
		fos.write('a');	fos.write('b');	fos.write('c');
		= fos.write(97)            98             99
		fos.write('가'); fos.write('나'); fos.write('다');
		
		byte[] buf = "\n반갑습니다. 이것은 예제입니다.\n".getBytes();
		fos.write(buf);		// void write(byte[])
		fos.write(buf, 13, 2);	// void write(byte[], int offset, int len)
		fos.flush();

문자기반 스트림 (2바이트 단위 = 1 char) - Reader, Writer 

 - 기반스트림 :FileReader&FileWriter

 - 보조스트림 : in -> InputStreamReader, BufferedReader

                    out ->InputStreamWriter, BufferedWriter, PrintWriter

 - 조상은 Reader, Writer

 - 문자 특화

○ 바이트 스트림 -> 문자 스트림 변환 : InputStreamReader, OutputStreamWriter

FileReader fis = new FileReader("src/ch15/fileReaderEx1.java");
		// int read() - 2byte(1char)씩, 읽어온 문자를 int로 리턴
		int data = 0;
		while ((data = fis.read()) != -1) {
			System.out.print((char) data);
		}

		// int read(char[] buf) - 배열 크기씩, 읽은 문자들을 buf로 문자수를 int로 리턴
		fis = new FileReader("src/ch15/fileReaderEx1.java");
		char[] buf = new char[1024];
		while ((data = fis.read(buf)) != -1) {
			System.out.print(new String(buf, 0, data));
		}
		
		// int read(char[] buf, int offset, int len)        
		fis = new FileReader("src/ch15/fileReaderEx1.java");
		buf = new char[1024];
		while ((data = fis.read(buf, 0, buf.length)) != -1) {
			System.out.print(new String(buf, 0, data));
		}
FileWriter fos = new FileWriter(new File("src/ch15/out2.txt"));
		fos.write('1');	fos.write('2');	fos.write('3');	// void write(int)
		= fos.write(49)            50             51
		fos.write('a');	fos.write('b');	fos.write('c');
		= fos.write(97)            98             99
		fos.write('가'); fos.write('나'); fos.write('다');
		
		char[] buf = "\n반갑습니다. 이것은 예제입니다.\n".toCharArray();
		fos.write(buf);		// void write(char[])
		fos.write(buf, 13, 2);	// void write(char[], int offset, int len)
		System.out.println((int)'\n');
		fos.write('\n'); 	fos.write("안녕.");	// void write(String)
		fos.flush();

 - BufferedReader : 버퍼를 내부적으로 추가해 IO 성능을 향상시킨 스트림, 보조스트림 생성자 매개변수로 기반스트림을 넣어줘야함.

FileReader fr = new FileReader(System.in);
BufferedReader br = new BufferedReader(fr);

● RandomAccessFile : 입출력이 모두 가능

 - 파일 포인터가 존재하여 파일의 임의의 위치에 있는 내용을 작업할 수 있음

 - getFilePointer() : 현재 포인터 위치

 - seek(long pos) : 포인터 위치 변경

● 직렬화 : 객체를 외부로 전송하는 기능

 - ObjectOutputStream : 객체를 외부로 전송하는 스트림, 전송되는 객체는 반드시 Serializable를 구현해야함

 - transient : 직렬화 대상에서 제외

 - 상속 관계 속 직렬화 : 자손클래스만 Serializable를 구현 한 경우 부모클래스의 자료는 전송 X, 부모 클래스의 자료도 전송시키기 위해서는 자손클래스에 WriteObject, readObject 메소드를 구현해야 함.

private void writeObject(ObjectOutputStream out) throws IOException {
    out.writeUTF(name);
    out.writeUTF(password);
    out.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    name = in.readUTF();
    password = in.readUTF();
    in.defaultReadObject();
}

◆자바의 표준 입출력 객체

 - 입력 : InputStream System.in : 키보드에서 입력

 - 출력 : PrintStream System.out : 콘솔에 출력

 - 오류 : PrintStream System.err : 콘솔에 출력