728x90
2023.01.30 - [JAVA/Java 기초] - 입출력 스트림-2.java
입출력 스트림-2.java
2023.01.30 - [JAVA/Java 기초] - 입출력 스트림.java 입출력 스트림.java 입력 스트림과 출력 스트림 프로그램을 기준으로 데이터가 들어오면 입력 스트림, 데이터가 나가면 출력 스트림 프로그램이 다른
less-go.tistory.com
이전글에서부터 계속됩니다
기본 타입 스트림
보조스트림
DataInputStream
DataOutputStream
프로그램에서 사용한 데이터 타입 그대로 저장하고 불러올때 사용합니다.
로컬 프로그램에서 로컬파일을 데이터베이스 처럼 이용할때 사용합니다.
- 바이트 스트림에 보조스트림인 DataInputStream과 DataOutputStream 을 연결하면 기본타입(boolean, char, short, int, long, float, double) 값을 입출력 할수 있습니다.

import java.io.*;
public class DataInputOutputStreamExam {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("c:/Temp/privitive.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("c:/Temp/privitive.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();
}
}
결과 :
c:/Temp/privitive.db 에
홍길동 : 95.5 : 1
감자바 : 90.3 : 2
의 값을 갖게 한후 파일을 생성후
디버그 창에
홍길동 : 95.5 : 1
감자바 : 90.3 : 2
을 출력
DataOutputStream으로 출력한 데이터를 다시 DataInputStream으로 읽어 올때에는 출력한 순서와 동일한 순서로 읽어야 합니다.
예를 들어 출력시의 순서가 int → Boolean → double 이라면, 읽을 때의 순서도 int → Boolean → double 이어야 합니다.
PrintStream와 PrintWriter
- 프린터와 유사하게 출력하는 print(), println(), printf() 메소드를 가진 보조 스트림

- PrintStream은 바이트 출력 스트림과 연결되고, PrintWriter는 문자 출력 스트림과 연결합니다.

package IO4;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStreamExam {
public static void main(String[] args) throws Exception{
FileOutputStream fos = new FileOutputStream("c:/Temp/printstream.txt");
PrintStream ps = new PrintStream(fos);
ps.print("마치 ");
ps.println("프린터가 출력하는것 처럼");
ps.println("데이터를 출력합니다.");
ps.printf("| %6d | %-10s | %10s | \n", 1, "홍길동", "도적");
// %6d = 6칸 차지
// %-10s = 10칸짜리 왼쪽정렬/ %10s = 10칸짜리 오른쪽정렬
ps.printf("| %6d | %-10s | %10s | \n", 2, "감자바", "학생");
ps.flush();
ps.close();
}
}
결과 :
Temp에 printstream.txt 파일 생성
내용 :
마치 프린터가 출력하는것 처럼
데이터를 출력합니다.
| 1 | 홍길동 | 도적 |
| 2 | 감자바 | 학생 |
객체 스트림 :
- 직렬화 : 자바는 메모리에 생성된 객체를 파일 또는 네트워크로 출력하는데, 객체를 출력하려면 필드값을 일렬로 늘어선 바이트로 변경해야 합니다. (객체 : 필드 → 바이트)
- 역직렬화 : 직렬화 된 바이트를 객체의 필드값으로 복원하는 것 입니다. (객체 : 필드 ← 바이트)
- ObjectOutputStream은 바이트 출력 스트림과 연결되어 객체를 직렬화하고, ObjectInputStream은 바이트 입력 스트림과 연결되어 객체로 복원하는 역직렬화.

import java.io.*;
import java.util.Arrays;
public class ObjectInputStreamExam {
public static void main(String[] args) throws Exception{
// fos에 oos 보조 스트림 연결
FileOutputStream fos = new FileOutputStream("c:/Temp/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을 ObjectInputStream 보조 스트림 연결
FileInputStream fis = new FileInputStream("c:/Temp/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));
}
}
결과 :
fall: 단풍이
노트북: 1500000
[1, 2, 3]
Serializable 인터페이스
- 멤버가 없는 빈 인터페이스이지만, 객체를 직렬화 할수 있다고 표시하는 역할입니다.
- 인스턴스 필드값은 직렬화 대상입니다.
- 정적 필드값과 transient로 선언된 필드값은 직렬화에서 제외되므로 출력되지 않습니다.

serialVersionUID 필드
직렬화 할때 사용된 클래스와 역직렬화할 때 사용된 클래스는 동일한 클래스여야 합니다.
클래스 내용이 다르더라도 두 클래스가 동일한 serialVersionUID 상수값을 가지면 역직렬화가 가능합니다.

File 클래스
- File 클래스로부터 File 객체를 생성 합니다.

- exists() 메소드가 false를 리턴할 경우, 다음 메소드로 파일 또는 폴더를 생성합니다.

- exists() 메소드의 리턴값이 true 라면 다음 메소드를 사용합니다.

package IO6;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class FileExam {
public static void main(String[] args) throws Exception{
//File 객체 생성
File dir = new File("c:/Temp/images");// 디렉토리 지정
File file1 = new File("c:/Temp/file1.txt"); // file1.txt 파일 지정
File file2 = new File("c:/Temp/file2.txt"); // file2.txt 파일 지정
File file3 = new File("c:/Temp/file3.txt"); // file3.txt 파일 지정
// 존재유무 exists() : 존재 : T / 존재X : F
if(dir.exists() == false) { dir.mkdir();}// 중간 경로가 없는 경우에도 중간 경로를 생성
if(file1.exists() == false) {file1.createNewFile();}
if(file2.exists() == false) {file2.createNewFile();}
if(file3.exists() == false) {file3.createNewFile();}
//Temp 폴더의 내용을 출력
File temp = new File("C:/Temp"); //경로 지정
File[] contents = temp.listFiles(); //경로 안의 파일과 디렉토리 목록을 File 형태로 저장
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a HH:mm"); //날짜출력
for(File file : contents) { //contents에 있는 파일과 디렉토리 목록을 하나씩 file에 대입
System.out.printf("%-25s", sdf.format(new Date(file.lastModified())));
//file 마지막 수정 날짜 출력
if(file.isDirectory()) { // 파일의 내용이 디렉토리인지 확인
System.out.printf("%-10s%-20s", "<DIR>", file.getName());
//디렉토리일 경우 <DIR>을 출력,
//<DIR>에 좌측정렬로 10칸의 String형 자리 할당 : %-10s -- 첫번째
//파일의 이름을 좌측정렬로 20칸의 String형 자리 할당 : %-20s -- 두번째
} else {
System.out.printf("%-10s%-20s", file.length(), file.getName());
//디렉토리가 아닐경우 파일의 길이를 출력합니다.
//파일의 길이를 좌측정렬로 String형 10자리를 할당하여 출력: %-10s -- 첫번째
//파일의 이름을 좌측정렬로 String형 20자리를 할당하여 출력 : %-20s -- 두번째
}
System.out.println();
}
}
}
결과 :
2023-01-31 오후 14:24 0 file1.txt
2023-01-31 오후 14:24 0 file2.txt
2023-01-31 오후 14:24 0 file3.txt
2022-12-05 오후 12:29 628 hello2022.class
2022-12-05 오후 12:28 147 hello2022.java
2023-01-31 오후 14:24 <DIR> images
2022-12-20 오전 08:44 <DIR> NEO
2022-12-30 오후 13:55 <DIR> NEO2
2023-01-31 오후 12:35 187 object.dat
2023-01-31 오후 12:10 171 printstream.txt
2023-01-31 오전 11:32 46 privitive.db
2023-01-31 오전 10:35 664489 targetFile1.jpg
2023-01-31 오전 10:35 664489 targetFile2.jpg
2022-12-20 오후 15:23 567654 test.jpg
2023-01-31 오전 09:49 19 test.txt
2023-01-30 오후 16:24 3 test1.db
2023-01-30 오후 16:39 3 test2.db
2023-01-30 오후 17:26 567654 test2.jpg
Files 클래스
- Files 클래스는 정적 메소드로 구성되어 있기 때문에 File 클래스처럼 객체로 만들 필요가 없습니다.
- Files의 정적 메소드는 운영체제의 파일 시스템에게 파일 작업을 수행하도록 위임합니다.

files.createDirectory = 부모 디렉토리가 없을 경우 디렉토리 생성 실패
files.createDirectories = 부모 디렉토리가 없을 경우 부모 디렉토리까지 생성
- 위 메소드들은 매개값으로 Path 객체를 받습니다.
- Path 객체는 파일이나 디렉토리를 찾기 위한 경로 정보를 가지고 있는데, 정적 메소드인 get() 메소드로 다음과 같이 얻을수 있습니다.
Path path = Paths.get(String first, String... more)
- get()메소드의 매개값은 파일 경로인데, 전체 경로를 한번에 지정할수도 있고, 상위 디렉토리와 하위 디렉토리를 나열해서 지정해도 좋습니다.
- 다음은 특정 경로를 이용해서 Path 객체를 얻는 방법입니다.
Path path = Paths.get("C:/Temp/dir/file.txt");
Path path = Paths.get("C:/Temp/dir/", "file.txt");
Path path = Paths.get("C:", "Temp", "dir", "file.txt");
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FilesExam {
public static void main(String[] args) {
try {
String data =
"" +
"id: winder\n" +
"email : winter@mycompany.com\n" +
"tel: 010-123-1234";
Path path = Paths.get("C:/Temp/user.txt");
Files.writeString(Paths.get("C:/Temp/user.txt"), data, Charset.forName("UTF-8"));
System.out.println("파일 유형: " + Files.probeContentType(path));
System.out.println("파일 크기: " + Files.size(path) + " bytes");
String content = Files.readString(path, Charset.forName("UTF-8"));
System.out.println(content);
// 한글에 대한 캐릭터 셋 : UTF-8(4byte), EUC-KR(3Byte)
}catch(IOException e) {
e.printStackTrace();
}
}
}
728x90
'JAVA > Java 기초' 카테고리의 다른 글
| 서버의 동시 요청 처리.java (0) | 2023.02.01 |
|---|---|
| 네트워크 기초(IP, TCP, UDP).java (0) | 2023.01.31 |
| 요소 커스텀 집계.java (0) | 2023.01.30 |
| 입출력 스트림-2.java (0) | 2023.01.30 |
| 입출력 스트림.java (0) | 2023.01.30 |