데코레이터 패턴
- 객체의 추가적인 요건을 동적으로 첨가
- 서브클래스를 만드는 방식으로 기능을 유연하게 확장할 수 있는 방법을 제공
- 장식할 대상과 장식을 동일시하는 패턴
바이트 기반 보조 스트림 / 음성 , 이미지, 프로그램
FilterInputStream과 FilterOutputStream
- 모든 바이트 기반 보조스트림의 최고조상
- 보조스트림은 자체적으로 입출력을 수행할 수 없다
- 상속을 통해 FilterInputStream/FilterOutputStream의 read()와 write()를 오버라이딩 해야 한다
BufferedInputStream과 BufferedOutputStream
- 입출력 효율을 높이기 위해 버퍼(byte[])를 사용하는 보조 스트림
- 보조스트림을 닫으면 기반스트림도 닫힌다.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class BufferedStreamEx {
static final String rootPath = System.getProperty("user.dir") + "\\files\\";
static String source = rootPath + "img.jpg";
static String target = rootPath + "img_copy_buffered.jpg";
public static void main(String[] args) {
InputStream fis = null; // 주스트림
OutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
fis = new FileInputStream(source); // 주스트림
fos = new FileOutputStream(target); // 주스트림
// 버퍼 기반보조스트림
bis = new BufferedInputStream(fis); // 보조스티림
bos = new BufferedOutputStream(fos); // 출력용 보조스트림
byte[] data = new byte[10240];
int size = 0;
while ((size = bis.read(data)) != -1) {
bos.write(data,0,size);// 버퍼내용 출력
System.out.println(size + "바이트복사!");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
bos.close(); // 연결된 주소 스트림도 닫힌다.
bis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
문자 기반 보조 스트림
BufferedReader와 BufferedWriter
- 입출력 효율을 높이기 위해 버퍼(char[])를 사용
- 라인(line) 단위의 입출력에 편리
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;
public class BufferedCharStreamEx {
static final String rootPath = System.getProperty("user.dir") + "\\files\\";
static String source = rootPath + "last-leaf.txt";
static String target = rootPath + "last-leat-filterd.txt";
public static void main(String[] args) {
// 주스트림
Reader fr = null;
Writer fw = null;
// 보조스트림
BufferedReader br = null;
BufferedWriter bw = null;
try {
// 주스트림
fr = new FileReader(source);
fw = new FileWriter(target);
// 메인스트림
br = new BufferedReader(fr);
bw = new BufferedWriter(fw);
String line = "";
while ((line = br.readLine()) != null) {
// 해당 라인에 leaf 혹은 leaves가 포함된 라인만 따로 저장
if (line.toLowerCase().contains("leaf") || line.toLowerCase().contains("leaves")) {
// leaf, leaves 들어있는 문장만 출력
System.out.println(line);
bw.write(line);
bw.write("\r\n");
}
}
System.out.println("필더링 완료!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
기본 타입 입출력 보조스트림
DataInputStream과 DataOutputStream
- 바이트 기반 스트림은 기본 데이터 타입(Primitive Types)을 입출력할 수 없다
- DataInputStream과 DataOutputStream을 이용하면 기본 타입 입출력이 가능하다
- 주의: DataInputStream으로 읽을 때는 DataOutputStream에서 출력한 순서대로 읽어와야 한다.
각 데이터 타입의 크기가 모두 다르기 때문
예) 출력 순서 : String -> int -> double
입력 순서 : String -> int -> double
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class DataStreamEx {
static final String rootPath = System.getProperty("user.dir") + "\\files\\";
static final String filename = rootPath + "primives.txt";
// DataStrea ; 기본 데이터 타입을 저장
public static void main(String[] args) {
// Saveprimitives();
loadprimitives();
}
private static void loadprimitives() {
InputStream fis = null; // 주스트림
DataInputStream dis = null; // 주스트림
try {
fis = new FileInputStream(filename);
dis = new DataInputStream(fis);
for (int i = 0; i < 2; i++) {
// 주의 : 출력한 순서대로 읽어온다.
// String -> Boolean -> int -> Float
String s = dis.readUTF();
boolean b = dis.readBoolean();
int val = dis.readInt();
float f = dis.readFloat();
System.out.printf("%s:%b:%d:%f%n", s, b, val, f);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
dis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private static void Saveprimitives() {
OutputStream fos = null;
DataOutputStream dos = null;
try {
fos = new FileOutputStream(filename); // 주스트림
dos = new DataOutputStream(fos); // 보조스트림
// 출력 : String -> Boolean -> int -> Float
dos.writeUTF("홍길동");
dos.writeBoolean(true);
dos.writeInt(25);
dos.writeFloat(25.5f);
dos.writeUTF("김길동");
dos.writeBoolean(false);
dos.writeInt(385);
dos.writeFloat(99.9f);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
dos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
표준입출력
- 콘솔을 통한 데이터의 입출력을 ‘표준입출력'이라 한다
- JVM이 시작되면서 자동적으로 생성되는 스트림
파일 닫기
- 정상적으로 수행되었을 경우, Java가 알아서 파일을 close 해줌
close() 메서드를 호출하는 이유
- 비정상적으로 프로그램이 끝났을 경우 파일이 손상되는 것을 막아줌
- 파일에 출력한 이후 close 해주어야 읽을 수 있음
- RandomAccessFile 클래스 객체를 이용, 파일에서 출력과 읽어들이는 것을 동시에 할 수 있으나 일반적으로 Transaction 관점에서 바람직하지 않음
StringTokenizer
java.util.StringTokenizer
- 문자열을 특정 구분자(Delimeter)로 분리해내는 기능 수행
StringTokenizer의 Constructor
- StringTokenizer(String str)
- Default 생성자는 구분자로 “\t\n\r”을 가정 (공백 / 탭/ 개행)
- StringTokenizer(String str, String delim)
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.StringTokenizer;
public class StringTokenizerEx {
static final String rootPath = System.getProperty("user.dir") + "\\files\\";
static final String filename = rootPath + "thieves.txt";
public static void main(String[] args) {
Reader fr = null;
BufferedReader br = null;
try {
fr = new FileReader(filename);
br = new BufferedReader(fr);
String thief;
while ((thief = br.readLine()) != null) {
StringTokenizer st = new StringTokenizer(thief, " ");
while (st.hasMoreTokens()) {
String token = st.nextToken()+"\t";
System.out.print(token);
}
System.out.println();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Scanner
- Java 5부터 java.util.Scanner 제공
- BufferedReader와 FileReader, StringTokenizer의 조합 대신 사용
- 키보드 입력 사용의 예
Scanner vs BufferedReader
Scanner 클래스가 있는데도, BufferedReader 클래스를 InputStream, InputStreamReader, FileReader, StringTokenizer 등과 조합해서 사용하는 이유
하나의 업무를 하나의 클래스에서 수행하여 클래스의 변경 없이 다양한 경우에 조합해서 사용 가능
Scanner 클래스로 처리 가능한 경우는 Scanner 클래스 사용을 추천
import java.io.File;
import java.io.IOException;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class ScannerEx {
static final String rootPath = System.getProperty("user.dir") + "\\files\\";
static final String filename = rootPath + "thieves.txt";
public static void main(String[] args) {
File file = new File(filename);
try {
Scanner scanner = new Scanner(file);
String name;
float height;
float weight;
while (scanner.hasNextLine()) {
name = scanner.next();
height = scanner.nextFloat();
weight = scanner.nextFloat();
System.out.printf("%s : %f , %f %n", name, height, weight);
scanner.nextLine();
}
scanner.close();
} catch (NoSuchElementException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
'JAVA' 카테고리의 다른 글
Java Network and Thread (0) | 2021.08.11 |
---|---|
JDBC Programming - DAO (Data Access Object) (0) | 2021.08.11 |
JAVA Hash / Java I/O Programming (0) | 2021.08.11 |
Java Utility API / Geniric / Collection Framework (0) | 2021.08.11 |
JAVA API, Stirng, StringBuffer, Arra (0) | 2021.08.11 |