반응형
12. 자바의 입출력을 위한 I/O 스트림
입출력 스트림
- 네트워크에서 자료의 흐름이 물의 흐름과 같다는 비유에서 유래됨
- 자바는 다양한 입출력 장치에 독립적으로 일관성있는 입출력 스트림을 통해 제공
- 입출력이 구형되는 곳 - 파일디스크, 키보드, 마우스, 네트웍, 메모리 등 모든 자료가 입력되고 출력되는 곳
입출력 스트림의 구분
- 대상 기준 : 입력 스트림 / 출력 스트림
- 자료의 종류 : 바이트 스트림 / 문자 스트림
- 기능 : 기반 스트림 / 보조 스트림
스트림의 종류
- 종류 예
입력 스트림 | FileInputStream, FileReader, BufferedInputStream, BufferedReader 등 |
출력 스트림 | FileOutputStream, FileWriter, BufferedOutputStream, BufferedWriter 등 |
바이트 단위 스트림과 문자 단위 스트림
- 바이트 단위 스트림 : 동영상, 음악, 파일, 실행 파일 등 자료를 읽고 쓸 때 사용
- 문자 단위 스트림 : 바이트 단위로 자료를 처리하면 문자는 깨짐,
인코딩에 맞게 2바이트 이상으로 처리하도록 구현된 스트림
스트림의 종류
종류 예
바이트 스트림 | FileInputStream, FileOutputStream, BufferedInputStream, BufferedOutputStream 등 |
문자 스트림 | FileReader, FileWriter, BufferedReader, BufferedWriter 등 |
기반 스트림과 보조 스트림
- 기반 스트림 : 대상에 직접 자료를 읽고 쓰는 기능의 스트림
- 보조 스트림 : 직접 읽고 쓰는 기능은 없이 추가적인 기능을 더해주는 스트림
- 보조 스트림은 직접 읽고 쓰는 기능은 없으므로 항상 기반 스트림이나
또 다른 보조 스트림을 생성자의 매개 변수로 포함함
스트림의 종류
- 종류 예
기반 스트림 | FileInputStream, FileOutputStream, FileReader, FileWriter 등 |
보조 스트림 | InputStreamReader, OutputStreamWriter, BufferedInputStream, BufferedOutputStream 등 |
13. 표준 입출력 스트림
System 클래스의 표준 입출력 멤버
public class System{
public static PrintStream out;
public static InputStream in;
public static PrintStream err;
}
- System.out
표준 출력(모니터) 스트림
System.out.println("출력 메세지");
- System.in
표준 입력(키보드) 스트림
int d = System.in.read() // 한 바이트 읽기
- System.err
표준 에러 출력(모니터) 스트림
System.err.println("에러 메세지");
import java.io.IOException;
import java.io.InputStreamReader;
public class SystemInTest1 {
public static void main(String[] args) {
System.out.println("알파벳을 여러개 쓰고 [Enter]를 누르세요");
int i;
try {
InputStreamReader irs = new InputStreamReader(System.in);
while ((i = irs.read()) != '\n') {
//System.out.println(i);
System.out.print((char)i);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
14. 바이트 단위 입출력 스트림
InputStream
- 바이트 단위 입력 스트림 최상위 추상 클래스
- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함
- 주요 하위 클래스
스트림 클래스 설명
FileInputStream | 파일에서 바이트 단위로 자료를 읽습니다. |
ByteArrayInputStream | byte 배열 메모리에서 바이트 단위로 자료를 읽습니다. |
FilterInputStream | 기반 스트림에서 자료를 읽을 때 추가 기능을 제공하는 보조 스트림의 상위 클래스 |
- 주요 메서드
메서드 설명
int read() | 입력 스트림으로부터 한 바이트의 자료를 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
int read(byte b[]) | 입력 스트림으로 부터 b[] 크기의 자료를 b[]에 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
int read(byte b[], int off, int len) | 입력 스트림으로 부터 b[] 크기의 자료를 b[]의 off변수 위치부터 저장하며 len 만큼 읽습니다. 읽은 자료의 바이트 수를 반환합니다. |
void close() | 입력 스트림과 연결된 대상 리소스를 닫습니다. |
FileInputStream 예제
- 파일에서 한 바이트씩 자료 읽기
public class FileInputStreamTest1 {
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("input.txt");
System.out.println((char)fis.read());
System.out.println((char)fis.read());
System.out.println((char)fis.read());
} catch (IOException e) {
System.out.println(e);
} finally{
try {
fis.close();
} catch (IOException e) {
System.out.println(e);
} catch (NullPointerException e){
System.out.println(e);
}
}
System.out.println("end");
}
}
- 파일의 끝까지 한 바이트씩 자료 읽기
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest2 {
public static void main(String[] args) {
int i;
try (FileInputStream fis = new FileInputStream("input.txt")) {
while( (i = fis.read()) != -1) {
System.out.print((char)i);
}
} catch(IOException e) {
System.out.println(e);
}
}
}
- 파일에서 바이트 배열로 자료 읽기 ( 배열에 남아 있는 자료가 있을 수 있음에 유의 )
public class FileInputStreamTest3 {
public static void main(String[] args) {
try (FileInputStream fis = new FileInputStream("input2.txt")){
byte[] bs = new byte[10];
int i;
while ( (i = fis.read(bs)) != -1){
/*for(byte b : bs){
System.out.print((char)b);
}*/
for(int k= 0; k<i; k++){
System.out.print((char)bs[k]);
}
System.out.println(": " +i + "바이트 읽음" );
}
/*while ( (i = fis.read(bs, 1, 9)) != -1){
for(int k= 0; k<i; k++){
System.out.print((char)bs[k]);
}
System.out.println(": " +i + "바이트 읽음" );
}*/
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("end");
}
}
OutputStream
- 바이트 단위 출력 스트림 최상위 클래스
- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함
주요 하위 클래스
FileOutputStream | 파일에서 바이트 단위로 자료를 씁니다. |
ByteArrayOutputStream | byte 배열 메모리에서 바이트 단위로 자료를 씁니다. |
FilterOutputStream | 기반 스트림에서 자료를 쓸 때 추가 기능을 제공하는 보조 스트림의 상위 클래스 |
주요 메서드
int write() | 한 바이트를 출력합니다. |
int write(byte b[]) | b[] 크기의 자료를 출력합니다. |
int write(byte b[], int off, int len) | b[] 배열에 있는 자료의 off 위치부터 len 개수만큼 자료를 출력합니다. |
void flush() | 출력을 위해 잠시 자료가 머무르는 출력 버퍼를 강제로 비워 자료를 출력합니다. |
void close() | 출력 스트림과 연결된 대상 리소스를 닫습니다. 출력 버퍼가 비워집니다. |
FileOutputStream 예제
파일에 한 바이트씩 쓰기
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest1 {
public static void main(String[] args) {
try(FileOutputStream fos = new FileOutputStream("output.txt")) {
fos.write(65);
fos.write(66);
fos.write(67);
} catch (IOException e) {
System.out.println(e);
}
System.out.println("end");
}
}
byte[] 배열에 A-Z 까지 넣고 한꺼번에 파일 쓰기
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
public class FileOutputStreamTest2 {
public static void main(String[] args) throws FileNotFoundException {
FileOutputStream fos = new FileOutputStream("output2.txt");
try(fos){
byte[] bs = new byte[26];
byte data = 65;
for(int i=0; i<bs.length; i++) {
bs[i] = data++;
}
fos.write(bs);
} catch (Exception e) {
System.out.println(e);
}
System.out.println("end");
}
}
byte[] 배열의 특정 위치에서 부터 정해진 길이 만큼 쓰기
public class FileOutputStreamTest3 {
public static void main(String[] args) {
try(FileOutputStream fos = new FileOutputStream("output3.txt"))
{
byte[] bs = new byte[26];
byte data = 65; //'A' 의 아스키 값
for(int i = 0; i < bs.length; i++){ // A-Z 까지 배열에 넣기
bs[i] = data;
data++;
}
fos.write(bs, 2, 10); // 배열의 2 번째 위치부터 10 개 바이트 출력하기
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다.");
}
}
flush() 와 close() 메서드
- 출력 버퍼를 비울때 flush() 메서드를 사용
- close() 메서드 내부에서 flush()가 호출되므로 close()메서드가 호출되면 출력 버퍼가 비워짐
15. 문자단위 입력 스트림
Reader
- 문자 단위 입력 스트림 최상위 추상 클래스
- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함
주요 하위 클래스
FileReader | 파일에서 문자 단위로 읽는 스트림 클래스입니다. |
InputStreamReader | 바이트 단위로 읽은 자료를 문자로 변환해주는 보조 스트림 클래스 입니다. |
BufferedReader | 문자로 읽을 때 배열을 제공하여 한꺼번에 읽을 수 있는 기능을 제공하는 보조 스트림입니다. |
주요 메서드
int read() | 파일로부터 한 문자를 읽습니다. 읽은 문자를 반환합니다. |
int read(char[] buf) | 파일로부터 buf 배열에 문자를 읽습니다. |
int read(char[] buf, int off, int len) | 파일로부터 buf 배열의 off 위치로부터 len 개수만큼의 문자를 읽습니다. |
void close() | 입력 스트림과 연결된 대상 리소스를 닫습니다. |
FileReader
파일에서 문자 읽기
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
public static void main(String[] args) {
try(FileReader fr = new FileReader("reader.txt")) {
int i;
while ((i=fr.read()) != -1) {
System.out.print((char)i);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Writer
- 문자 단위 출력 스트림 최상위 추상 클래스
- 많은 추상 메서드가 선언되어 있고 이를 하위 스트림이 상속받아 구현함
- 주요 하위 클래스
클래스 설명
FileWriter | 파일에서 문자 단위로 출력하는 스트림 클래스입니다. |
OutputStreamWriter | 바이트 단위의 자료를 문자로 변환해 출력해주는 보조 스트림 클래스 입니다. |
BufferedWriter | 문자로 쓸 때 배열을 제공하여 한꺼번에 쓸 수 있는 기능을 제공하는 보조 스트림입니다. |
주요 메서드
int write(int c) | 한 문자를 파일에 합니다. |
int write(char[] buf) | 문자 배열 buf의 내용을 출력합니다. |
int write(char[] buf, int off, int len) | 문자 배열 buf의 off위치에서부터 len 개수의 문자를 출력합니다. |
int write(String str) | 문자열 str을 출력합니다. |
int write(String str, int off, int len) | 문자열 str의 off번째 문자로부터 len 개수만큼 출력합니다. |
int flush() | 출력하기 전에 자료가 있는 공간(출력 버퍼)을 비워 출력하도록 합니다 |
void close() | 스트림과 연결된 리소스를 닫습니다. 출력 버퍼도 비워집니다. |
FileWriter
파일에 문자 쓰기
public class FileWriterTest {
public static void main(String[] args) {
try(FileWriter fw = new FileWriter("writer.txt")){
fw.write('A'); // 문자 하나 출력
char buf[] = {'B','C','D','E','F','G'};
fw.write(buf); //문자 배열 출력
fw.write("안녕하세요. 잘 써지네요"); //String 출력
fw.write(buf, 1, 2); //문자 배열의 일부 출력
fw.write("65"); //숫자를 그대로 출력
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("출력이 완료되었습니다.");
}
}
16. 여러가지 보조 스트림 클래스들
보조 스트림
- 실제 읽고 쓰는 스트림이 아닌 보조 기능을 제공하느 스트림
- FileInputStream과 FileOutputStream이 보조 스트림의 상위 클래스들
생성자의 매개변수로 또 다른 스트림( 기반스트림이나 다른 보조 스트림)을 가짐 - Decorator Pattern으로 구현됨
상위 클래스 생성자
protected FilterInputStream과(InputStream in) | 생성자의 매개변수로 InputStream을 받습니다. |
public FilterOutputStream(OutputStream out) | 생성자의 매개변수로 OutputStream을 받습니다. |
InputStreamReader와 OutputStreamWriter
- 바이트 단위로 읽거나 쓰는 자료를 문자로 변환해주는 보조 스트림
FileInputStream으로 읽은 자료를 문자로 변환해주는 예
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderTest {
public static void main(String[] args) {
try(InputStreamReader isr = new InputStreamReader(new FileInputStream("reader.txt"))) {
int i;
while((i=isr.read()) != -1) {
System.out.print((char)i);
}
} catch(IOException e) {
}
}
}
BufferedInputStream과 BufferedOutputStream
- 약 8k의 배열이 제공되어 입출력이 빠르게 하는 기능이 제공되는 보조 스트림
- BufferedReader와 BufferedWriter는 문자용 입출력 보조 스트림
BufferedInputStream과 BufferedOutputStream을 이용하여 파일 복사하는 예
public class BufferedStreamTest {
public static void main(String[] args) {
long millisecond = 0;
try(FileInputStream fis = new FileInputStream("a.zip");
FileOutputStream fos = new FileOutputStream("copy.zip");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)){
millisecond = System.currentTimeMillis();
int i;
while( ( i = bis.read()) != -1){
bos.write(i);
}
millisecond = System.currentTimeMillis() - millisecond;
}catch(IOException e) {
e.printStackTrace();
}
System.out.println("파일 복사 하는 데 " + millisecond + " milliseconds 소요되었습니다.");
}
}
DataInputStream과 DataOutputStream
- 자료가 메모리에 저장된 상태 그대로 읽거나 쓰는 스트림
DataInputStream 메서드
DataOutputStream 메서드
public class DataStreamTest {
public static void main(String[] args) {
try(FileOutputStream fos = new FileOutputStream("data.txt");
DataOutputStream dos = new DataOutputStream(fos))
{
dos.writeByte(100);
dos.writeChar('A');
dos.writeInt(10);
dos.writeFloat(3.14f);
dos.writeUTF("Test");
}catch(IOException e) {
e.printStackTrace();
}
try(FileInputStream fis = new FileInputStream("data.txt");
DataInputStream dis = new DataInputStream(fis))
{
System.out.println(dis.readByte());
System.out.println(dis.readChar());
System.out.println(dis.readInt());
System.out.println(dis.readFloat());
System.out.println(dis.readUTF());
}catch (IOException e) {
e.printStackTrace();
}
}
}
17. 직렬화 ( serialization )
직렬화란?
- 인스턴스의 상태를 그대로 파일 저장하거나 네트웍으로 전송하고 ( serialization )
이를 다시 복원 ( deserialization )하는 방식 - 자바에서는 보조 스트림을 활용하여 직렬화를 제공함
- ObjectInputStream과 ObjectOutputStream
생성자 | 설명 |
ObjectInputStream(InputStream in) | InputStream을 생성자의 매개변수로 받아 ObjectInputStream을 생성합니다. |
ObjectOutputStream(OutputStream out) | OutputStream을 생성자의 매개변수로 받아 ObjectOutputStream을 생성합니다. |
Serializable 인터페이스
- 직렬화는 인스턴스의 내용이 외부로 유출되는 것이므로 프로그래머가 해당 객체에 대한 직렬화 의도를 표시해야 함
- 구현 코드가 없는 marker interface
- transient : 직렬화 하지 않으려는 멤버 변수에 사용함 (Socket등 직렬화 할 수 없는 객체)
class Person implements Serializable{
private static final long serialVersionUID = -1503252402544036183L;
String name;
String job;
public Person() {}
public Person(String name, String job) {
this.name = name;
this.job = job;
}
public String toString()
{
return name + "," + job;
}
}
public class SerializationTest {
public static void main(String[] args) throws ClassNotFoundException {
Person personAhn = new Person("이순신", "대표이사");
Person personKim = new Person("김유신", "상무이사");
try(FileOutputStream fos = new FileOutputStream("serial.out");
ObjectOutputStream oos = new ObjectOutputStream(fos)){
oos.writeObject(personAhn);
oos.writeObject(personKim);
}catch(IOException e) {
e.printStackTrace();
}
try(FileInputStream fis = new FileInputStream("serial.out");
ObjectInputStream ois = new ObjectInputStream(fis)){
Person p1 = (Person)ois.readObject();
Person p2 = (Person)ois.readObject();
System.out.println(p1);
System.out.println(p2);
}catch (IOException e) {
e.printStackTrace();
}
}
}
Externalizable 인터페이스
- writerExternal()과 readExternal()메서드를 구현해야 함
- 프로그래머가 직접 객체를 읽고 쓰는 코드를 구현 할 수 있음
class Person implements Externalizable{
String name;
String job;
public Person() {}
public Person(String name, String job) {
this.name = name;
this.job = job;
}
public String toString()
{
return name + "," + job;
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(name);
//out.writeUTF(job);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
name = in.readUTF();
//job = in.readUTF();
}
}
18. 입출력 클래스
File 클래스
- 파일 개념을 추상화한 클래스
- 입출력 기능은 없고, 파일의 이름, 경로, 읽기 전용 등의 속성을 알 수 있음
- 이를 지원하는 여러 메서드들이 제공됨
import java.io.File;
import java.io.IOException;
public class FileTest {
public static void main(String[] args) throws IOException {
File file = new File("E:\\develop\\fast campus\\Java\\Chapter6\\newFile.txt");
file.createNewFile();
System.out.println(file.isFile());
System.out.println(file.isDirectory());
System.out.println(file.getName());
System.out.println(file.getAbsolutePath());
System.out.println(file.getPath());
System.out.println(file.canRead());
System.out.println(file.canWrite());
file.delete();
}
}
RandomAccessFile 클래스
- 입출력 클래스 중 유일하게 파일에 대한 입력과 출력을 동시에 할 수 있는 클래스
- 파일 포인터가 있어서 읽고 쓰는 위치 이동이 가능함
- 다양한 메서드가 제공됨
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) throws IOException {
RandomAccessFile rf = new RandomAccessFile("random.txt", "rw");
rf.writeInt(100);
System.out.println("파일 포인터 위치:" + rf.getFilePointer());
rf.writeDouble(3.14);
System.out.println("파일 포인터 위치:" + rf.getFilePointer());
rf.writeUTF("안녕하세요");
System.out.println("파일 포인터 위치:" + rf.getFilePointer());
rf.seek(0);
System.out.println("파일 포인터 위치:" + rf.getFilePointer());
int i = rf.readInt();
double d = rf.readDouble();
String str = rf.readUTF();
System.out.println("파일 포인터 위치:" + rf.getFilePointer());
System.out.println(i);
System.out.println(d);
System.out.println(str);
}
}
반응형
'Java' 카테고리의 다른 글
MVC Framework 만들어보기 / 객체지향 패러다임, 간단한 테스트 코드 (0) | 2023.04.06 |
---|---|
자바의 다양한 기능 / 데코레이터 패턴, Thread (0) | 2022.12.09 |
자바의 다양한 기능 / 스트림, 예외처리 (0) | 2022.12.07 |
자바의 다양한 기능 / 내부 클래스 정의, 람다식 (0) | 2022.12.02 |
자바와 자료구조 / Generic, T extends, 컬렉션 프레임워크 (0) | 2022.11.30 |