📚 이것이 자바다 [개정판]
- 데이터 입출력 : 데이터가 키보드, 파일, 프로그램으로부터 입출력, 저장 또는 전송되는 모든 것의 총칭
- 스트림 : 단방향으로 데이터가 흐르는 것
- 그림, 멀티미디어, 문자 등 모든 종류의 데이터 출력 시 사용
- 최상위 클래스
OutputStream
- 하위 클래스
FileOutputStream
PrintStream
BufferedOutputStream
DataOutputStream
public class WriteEx {
public static void main(String[] args) {
try {
OutputStream os = new FileOutputStream("test1.db");
// 1. 1byte씩 출력하는 경우
byte a= 10, b=20, c=30;
os.write(a); // 1byte씩 출력
os.write(b);
os.write(c);
// 2. 바이트 배열로 출력하는 경우
byte[] array = {10,20,30};
os.write(array); // 배열의 모든 바이트 출력
// 특정 인덱스까지 출력하는 경우 os.write(array, 0, 1);
// 공통부분
os.flush(); // 내부 버퍼에 잔류하는 바이트를 출력 후 비움
os.close(); // 출력 스트림을 닫고 사용 메모리 해제
} catch (Exception e) {
e.printStackTrace();
}
}
}
// OutputStream은 내부에 작언 buffer를 가지고 있다
// write()는 버퍼에 바이트를 저장하고, 끝 1byte를 순서대로 출력한다
// flush()는 내부 버터에 잔류하는 모든 바이트 출력 후 버퍼를 비운다
// close()로 더이상 출력 스트림을 사용하지 않을 경우 메모리를 해제한다
- 최상위 클래스
InputStream
- 하위 클래스
FileInputStream
BufferedInputStream
DataInputStream
public class ReadEx {
public static void main(String[] args) {
try {
InputStream is = new FileInputStream("test1.db");
// 1. 1byte씩 입력하는 경우
while(true) {
int data = is.read(); // 1byte씩 읽기
if(data == -1) break;
// 더이상 읽을 수 없는 경우(끝) -1 반환하기 때문
System.out.println(data);
}
// 2. 바이트 배열로 출력하는 경우
byte[] data = new byte[100];
while(true) {
int num = is.read(data);
if(num == -1) break; // 파일 끝에 도달한 경우
for(int i=0; i<num; i++) {
System.out.println(data[i]); // 읽은 데이터 출력
}
}
// 공통 부분
is.close(); // 입력 스트림을 닫고 사용 메모리 해제
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
}
}
// FileInputStream에서 읽은 바이트를 바로 FileOutputStream으로 출력
public class CopyEx {
public static void main(String[] args) throws Exception {
String originalFileName = "k.jpg";
String targetFileName = "k_copy.jpg";
InputStream is = new FileInputStream(originalFileName);
OutputStream os = new FileOutputStream(targetFileName);
byte[] data = new byte[1024]; // 읽은 파일을 저장할 배열
while (true) {
int num = is.read(data);
if (num == -1)break;
os.write(data, 0, num); // 읽은 바이트 수만큼 출력
}
os.flush(); // 내부 버퍼 잔류 바이트 출력 후 비움
os.close();
is.close();
System.out.println("복사 성공");
}
}
문자 입출력 시 사용
- 최상위 클래스
Write
(출력) /Reader
(입력)- 하위 클래스
FileWriter
/FileReader
PrintWriter
BufferedWriter
/bufferedReader
OutputStreamWriter
/InputStreamReader
<문자 출력>
public class WriteEx {
public static void main(String[] args) {
try {
// 문자 기반 출력 스트림 생성
Writer writer = new FileWriter("test.txt");
// 1. 1문자씩 출력
char a = 'A';
writer.write(a);
char b = 'B';
writer.write(b);
// 2. char 배열 출력
char[] arr = {'C','D','E'};
writer.write(arr);
// 3. 문자열 출력
writer.write("FGH");
// 버퍼 잔류 문자 출력, 비움
writer.flush();
// 출력 스트림 닫고 메모리 해제
writer.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 파일 생성 결과 : ABCDEFGH
<문자 읽기>
public class ReadEx {
public static void main(String[] args) {
try {
Reader reader = null;
// 1. 1문자씩 읽기
reader = new FileReader("test.txt");
while (true) {
int data = reader.read(); // 문자 읽음
if (data == -1)
break; // 파일을 다 읽으면 while문 종료
System.out.println((char) data); // 읽은 문자 출력
}
reader.close();
System.out.println();
// 2. 문자 배열로 읽기
reader = new FileReader("test.txt");
char[] data = new char[100]; // 문자를 저장할 배열 생성
while (true) {
int num = reader.read(data);
if (num == -1) break;
for (int i = 0; i < num; i++) { // 읽은 문자 수만큼 출력
System.out.println(data[i]);
}
}
reader.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
다른 스트림과 연결되어 여러 가지 편리한 기능을 제공해주는 스트림
자체적으로 입출력을 수행할 수 없음
-> 직접 생성된 입출력 스트림에 연결하여 사용
보조스트림 변수 = new 보조스트림(입출력스트림);
BufferedInputStream
BufferedOutputStream
InputStreamReader
바이트 스트림을 문자 스트림으로 변환
문자를 바로 입출력하는 편리함 제공, 문자셋의 종류 지정 가능
// InputStream을 Reader로 변환
InputStream is = new FileInputStream("test.txt");
Reader reader = new InputStreamReader(is);
// OutputStream을 Writer로 변환
OutputStream os = new FileOutputStream("test.txt");
Writer writer = new OutputStreamReader(os);
// 예제
public class CharacterConvertStreamEx {
public static void main(String[] args) throws Exception{
write("문자 변환 스트림을 사용합니다.");
String data = read();
System.out.println(data);
}
public static void write(String str) throws Exception {
//FileOutputStream에 OutputStreamWriter 보조스트림 연결
OutputStream os = new FileOutputStream("test.txt");
Writer writer = new OutputStreamWriter(os, "UTF-8");
writer.write(str); // 보조스트림을 이용하여 문자 출력
writer.flush();
writer.close();
}
public static String read() throws Exception {
//InputStream에 InputStreamReader 보조스트림을 연결
InputStream is = new FileInputStream("test.txt");
Reader reader = new InputStreamReader(is, "UTF-8");
char[] data = new char[100];
int num = reader.read(data); // 보조스트림을 이용하여 문자 입력
reader.close();
String str = new String(data, 0, num); // 배열에서 읽은 문자 수만큼 반환
return str;
}
}
Buffered~
성능 향상을 위해 프로그램이 중간에 메모리 버퍼와 작업하도록 설정
데이터가 쌓이기를 기다렸다가 꽉 차는 순간 데이터를 한번에 보냄
public class BufferEx {
public static void main(String[] args) throws Exception{
// FileReader에 BufferedReader 보조스트림 연결
BufferedReader br = new BufferedReader(new FileReader("test.txt"));
int lineNo = 1;
while(true) {
String str = br.readLine(); // 한 행을 읽음
if(str == null) break; // 더이상 읽을 내용이 없으면 while문 종료
System.out.println(lineNo + "\t" + str);
lineNo++;
}
br.close();
}
}
Data~Stream
기본 타입인 boolean, char, short, int, long, float, double 값 입출력 가능
public class DataInputOutputStreamEx {
public static void main(String[] args) throws Exception{
// DateOutputStream 생성
FileOutputStream fos = new FileOutputStream("test.db");
DataOutputStream dos = new DataOutputStream(fos);
// 기본 타입 출력
dos.writeUTF("홍길동");
dos.writeDouble(95.5);
dos.writeInt(1);
dos.writeUTF("차길동");
dos.writeDouble(90.3);
dos.writeInt(2);
dos.flush();
dos.close();
fos.close();
// DataInputStream 생성
FileInputStream fis = new FileInputStream("test.db");
DataInputStream dis = new DataInputStream(fis);
// 기본 타입 출력
for(int i=0; i<2; i++) {
String name = dis.readUTF();
double score = dis.readDouble();
int order = dis.readInt();
System.out.println(name + ":" + score + ":" + order);
}
dis.close();
fis.close();
}
}
Object~Stream
메모리에 생성된 객체를 파일 또는 네트워크로 출력
객체 출력시 필드값을 일렬로 늘어선 바이트로 변경하는 과정 -> 직렬화
직렬화된 바이트를 객체의 필드값으로 복원하는 과정 -> 역직렬화
class Member implements Serializable {
private static final long serialVersionUID = -622284561026719240L;
private String id;
private String name;
public Member(String id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return id + ": " + name;
}
}
class Product implements Serializable {
private static final long serialVersionUID = -621812868470078544L;
private String name;
private int price;
public Product(String name, int price) {
this.name = name;
this.price = price;
}
@Override
public String toString() {
return name + ": " + price;
}
}
public class ObjectInputOutputStream {
public static void main(String[] args) throws Exception{
//FileOutputStream에 ObjectOutputStream 보조스트림 연결
FileOutputStream fos = new FileOutputStream("object.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 객체 생성
Member m1 = new Member("fall", "단풍이");
Product p1 = new Product("노트북", 1500000);
int[] arr1 = {1,2,3};
// 객체 역직렬화하여 파일에 저장
oos.writeObject(m1);
oos.writeObject(p1);
oos.writeObject(arr1);
oos.flush();
oos.close();
fos.close();
FileInputStream fis = new FileInputStream("object.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
// 파일을 읽고 역직렬화하여 객체로 복원
Member m2 = (Member) ois.readObject();
Product p2 = (Product) ois.readObject();
int[] arr2 = (int[]) ois.readObject();
ois.close();
fis.close();
// 복원된 객체 내용 확인
System.out.println(m2);
System.out.println(p2);
System.out.println(Arrays.toString(arr2));
}
}
파일과 디렉토리 정보를 가지고 있는 클래스
File file = new File("경로")
boolean isExist = file.exists();
존재한다면 true 리턴
<File 클래스>
public class FileEx {
public static void main(String[] args) throws Exception{
// File 객체 생성
File dir = new File("images");
File file1 = new File("file1.txt");
File file2 = new File("file2.txt");
File file3 = new File("file3.txt");
// 존재하지 않으면 디렉토리 또는 파일 생성
if(dir.exists() == false) {dir.mkdirs();} // 폴더 생성
if(file1.exists() == false) {file1.createNewFile();} // 파일 생성
if(file2.exists() == false) {file2.createNewFile();}
if(file3.exists() == false) {file3.createNewFile();}
// 폴더 내용 출력
File temp = new File("D:\\seonjin\\javaStudy\\javaStudy\\ThisIsJava");
File[] contents = temp.listFiles();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm");
for(File file : contents) {
System.out.printf("%-25s", sdf.format(new Date(file.lastModified())));
if(file.isDirectory()) {
System.out.printf("%-10s%-20s", "<DIR>", file.getName());
} else {
System.out.printf("%-10s%-20s", file.length(), file.getName());
}
System.out.println();
}
}
}
<Files 클래스>
public class FilesEx {
public static void main(String[] args) {
try {
String data = ""
+ "id: winter\n"
+ "email: winter@w.com\n"
+ "tel: 010-0000-0000";
// Path 객체 생성
Path path = Paths.get("user.txt");
// 파일 생성 및 데이터 저장
Files.writeString(Paths.get("user.txt"), data, Charset.forName("UTF-8"));
// 파일 정보 얻기
System.out.println("파일 유형: " + Files.probeContentType(path));
System.out.println("파일 크기: " + Files.size(path) + "byte");
// 파일 읽기
String content = Files.readString(path, Charset.forName("UTF-8"));
System.out.println(content); // 파일 내용
} catch (IOException e) {
e.printStackTrace();
}
}
}