
경로에 대하여
🔹 dir구분 기호
절대 경로 : root로 부터의 위치
|
🔹 java.io.File - method
| exists() - 업데이트 lastModified - 날짜를 확인. (ex) 다르면 업데이트 진행) length - 크기 비교하여 다르면 업데이트 진행. renameTo - 파일이 이미 있는 경우 덮어쓰기 안하고 이름을 test(1)이런식으로 바꾸기 |
Stream
- 입출력 할 때의 스트림이 있고
- 입출력에서의 스트림 = 데이터를 운반하는데 사용하는 연결 통로이다.
- 여러개의 데이터를 순차적으로 처리하기 위한 스트림이 있다.(람다와 스트림에서 처럼)
🔹 분류
- 입력 Stream / 출력 Stream
- 바이트 Stream / 문자 Stream
- 일반적인 파일 처리는 바이트 Stream을 사용한다. (문자 이외의 것들도 전부 처리가 가능하기 때문)
- 문자를 읽고 쓰는 경우에만 문자 Stream을 사용한다. 문자 Stream을 사용할 때는 인코딩에 주의해야 한다. ❗인코딩 주의❗

➰ File에 대해서
package com.eb.fileinformation;
import java.io.File;
import java.util.Date;
public class Main {
public static void main(String[] args) {
//파일에 대한 정보 확인
try {
//file 인스턴스 생성 - windows에서는 dir구분 기호가 \이다.
// 프로그래밍 언어에서는 \가 오고 하나의 문자가 오면 제어문자로 인식하기 때문에 \\로 사용한다.
File f = new File("C:\\Users\\user\\Desktop\\Test.txt");
//파일의 존재 여부 확인
System.out.println(f.exists());
//마지막 수정 날짜
System.out.println(f.lastModified());
System.out.println(new Date(f.lastModified()));
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
ByteStream
InputStream 과 OutputStream
- 바이트 스트림의 최상위 클래스로 추상 클래스(인스턴스 생성 못하)
- 다른 바이트 스트림들이 가져야 하는 메서드 원형을 소유
🔹 InputStream - method
| int available() : 읽을 수 있는 바이트 수 리턴 void clise() : 닫기 int read() : 한 바이트를 읽어서 정수로 리턴하고 읽지 못하면 음수(-1)을 리턴 int read(byte[] b) : b배열 만큼 읽어서 b에 저장하고 읽은 개수를 리턴 -0이나 음스가 리턴되면 읽기 실패 int read(byte[] b, int offset, int length) : offset 부터 length만큼 읽어서 b에 저장하고 읽은 갯수를 리턴 long skip(long n) : n만큼 넘기기 |
🔹 OutputStream - method
| void close() : 닫기 void write(int n) : n을 기록 void write(byte[] b) : b배열을 기록 void write(byte[] b, int offset, int length) : b배열에서 offset에서 length만큼 기록 void flush() : 버퍼의 내용을 출력 |
❗ Stream은 열면 반드시 닫아야 한다.
package com.eb.bytefilterprocessing;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class ByteBufferStream {
public static void main(String[] args) {
try {
//버퍼를 이용해서 출력하는 Stream을 만들기
PrintStream ps = new PrintStream(new FileOutputStream("./buffer.txt"));
ps.print("문자열을 버퍼를 이용해서 출력");
ps.flush();
ps.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
🔹 바이트 단위 파일 입출력 - FileInputStream 과 FileOutputStream 사용
- 바이트 단위로 파일에 기록을 하는 class : FileOutputStream
- FileOutputStream(File file) - 매번 새로 만들어진다.
- FileOutputStream(File file, true) - 기존의 파일에 밑에 내용을 추가 하게된다.
package com.eb.bytefilterprocessing;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class Main {
public static void main(String[] args) {
//바이트 단위로 파일에 기록하기 - log 기록
try {
//오늘 날짜를 문자열로 만들기
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//기록할 파일 만들기
FileOutputStream fos = new FileOutputStream("./"+sdf.format(date)+".txt", true);
//기록할 메세지 생성 후 기록
String msg = "hello\n";
fos.write(msg.getBytes());
//파일 닫기
fos.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
//앞에서 작성한 파일 읽기
try {
FileInputStream fis = new FileInputStream("./2022-10-27.txt");
//읽어서 저장할 바이트 배열을 생성
byte[] b = new byte[fis.available()];
fis.read(b);
//출력
System.out.println(new String(b));
System.out.println(Arrays.toString(b ));
//닫기
fis.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
❓ Println 바로바로 출력하는것 print 버퍼 모아서 출력 하는 차이이다. (단순히 줄바꿈의 차이만 있는 것이 아니다) (print는 버퍼에 출력하는 method이다)
🔹 버퍼를 이용한 입출력

- java 코드를 입출력하는 작업을 작성하면 실제로는 JVM이 운영체제의 Native Method를 호출해서 처리한다. 자주 입출력을 하는 경우 작업을 할 때마다 Native Method를 호출하면 시스템의 성능이 저하될 수 있다. 이런 경우 버퍼를 이용해서 입출력 횟수를 줄이는 것이 좋다.
- 버퍼를 이용하는 바이트 단위 입출력은 BufferedInputStream(읽기)와 PrintStream(쓰기)를 이용한다. 버퍼에 기록을 할 때에는 write메서드 대신에 print method를 사용할 수 있으면 flush method를 이용해서 버퍼의 내용을 전부 출력할 수 있다.
- 표준 출력 스트림이 System.out인데 이 스트림의 자료형이 PrintStream
Character Stream (문자 스트림)
- ByteStream 을 이용하면 모든 종류의 IO장치와 데이터를 읽고 쓰기 작업이 가능 - 컴퓨터는 기본적으로 바이트 단위로 작업을 수행하기 때문입니다.
- 문자 단위로 데이터를 입출력하는 경우 ByteStream을 사용하게 되면 변환 작업이 필요.
Reader & Writer
- 문자 단위로 읽고 쓰기 위한 메서드를 제공하는 추상 클래스 - 문자 스트림의 최상위 클래스
🔹 Reader의 method
| void close() int read() 하나의 문자를 읽어오는 메서드로 문자의 코드를 리턴하는데 읽는데 실패하면 음수를 리턴 int read(char[] buf) 문자를 buf의 크기만큼 읽어서 buf에 저장하고 읽은 개수를 리턴 - 리턴값이 0보다 작거나 같으면 읽기 실패 int read(char[] buf, int offset, int length) 문자를 offset 부터 length만큼 읽어서 buf에 저장하고 읽은 개수를 리턴 int read(CahrBuffer target) boolean ready() long skip(long n) |
🔹 Writer Method
| void close() void flush() void write(String str) void write(String str, int offset, int length) |
package com.eb.charaterstream;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
//파일에 문자 단위로 기록하고 읽어오기
public class CharaterFileMain {
public static void main(String[] args) {
//파일에 문자열을 문자 단위로 기록하기
try {
//버퍼를 이용해서 파일에 문자열을 기록하는 클래스의 인스턴스를 생성.
//한번 기록하고 두번째 기록할 때 이어서 기록하는 인스턴스
//true를 생략하고 false를 설정하면 파일의 내용을 항상 새로 작성한다.
PrintWriter pw = new PrintWriter(new FileWriter("ch.txt", false));
//문자열을 기록
//문자열을 기록할 때 , 또는 공백, 탭 등으로 구분이 가능한데 이와 같이 만들어진 텍스트를 csv라고 한다.
//이 방식은 변하지 않는 고정적인 데이터를 기록할 떄 주로 이용
pw.print("민지, 뉴진스\n");
pw.print("도영, NCT\n");
pw.print("사쿠라, 르세라핌\n");
//버퍼의 내용 전부 출력
pw.flush();
pw.close(); //닫기
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
//파일에서 문자열을 문자 단위로 읽어오기 : FileReader 와 BufferedReader 이용
try {
//FileReader fr = new FileReader("ch.txt");
//BufferedReader br = new BufferedReader(fr);
BufferedReader br = new BufferedReader(new FileReader("ch.txt"));
while(true) {
String line = br.readLine();
if(line == null) {
break;
}
//읽은 데이터 출력
//System.out.println(line);
String[] ar = line.split(",");
System.out.println(ar[0]);
System.out.println(ar[1]);
}
br.close();
//fr.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
package com.eb.charaterstream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class WebTextDownload {
public static void main(String[] args) {
try {
//읽어올 URL 생성
URL url = new URL("https://www.naver.com");
//URL에 연결
HttpURLConnection con = (HttpURLConnection)url.openConnection();
//문자열을 읽기 위한 스트림 생성
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
while(true) {
String line = br.readLine();
if(line == null) {
break;
}
System.out.println(line);
}
br.close();
con.disconnect();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
// TODO: handle exception
}
}
}
InputStreamReader & OuputStreamReader (ByteStream)
- ByteStream을 CharacterStream으로 변환시켜주는 클래스
- 네트워크 프로그래밍에서 소켓은 ByteStream을 리턴하는데 주고 받는 데이터가 문자열이라면 ByteStream을 InputStreamReader 인스턴스로 변환해서 사용해야 한다.
new InputStreamReader(ByteStream instance)
FileReader / FileWriter (CharacterStream)
파일에 문자 단위로 읽고 쓰기 위한 클래스
BufferedReader / PrintWrite
- BufferedReader는 버퍼를 이용해서 문자를 읽어주는 클래스 (입출력 성능향상 스트림)
- 이 클래스에는 String readLine()이라는 method가 제공되어 줄 단위로 읽어낼 수 있다. but, 읽어 낸 내용이 없다면 null을 return.
- PrintWriter는 버퍼를 이용해서 문자 단위로 기록하는 클래스
etc
🔹파일에 문자 단위로 기록하고 읽어오기
- 문자열을 기록할 때 , 또는 공백, 탭 등으로 구분이 가능한데 이와 같이 만들어진 텍스트를 csv라고 한다.
<문자열을 분할하는 방법>
특수한 문자를 기준으로 분할
Stringp[ split(String 기분문자열) : 기준 문자열을 기준으로 문자열을 분할해서 문자열 배열로 리턴
String msg = "Hello, Java, World";
String[] splits = msg.split(",");
System.out.println(splits[0]); //Hello
System.out.println(splits[1]); //Java
System.out.println(splits[2]); // World
//마지막 데이터 출력 - 확장자 제거하기와 같은 작업을 할 때 필요
System.out.println(splits[splits.length-1]);
//위치를 기준으로 분할 - 주민번호로 나이 계산, 성별 확인, 생일 확인과 같은 일들 가능.
subString사용. Document 확인을 해야 한다. (숫자를 몇개줄지)
String msg = "Hello, Java, World";
String result = msg.substring(6); //Java, World
String result1 = msg.substring(6, 10); //Java
🔹 Serializable (직렬화)
- 인스턴스를 다른 곳에 전송할 수 있도록 해주는것
- 전송한다는 의미는 파일 단위로 읽고 쓰는 것도 전송으로 간주하고 컴퓨터와 컴퓨터 또는 component와 component 사이를 왔다갔다 하는 것도 전송한다고 합니다.
- 이럴 때 사용하는 값의 집합을 나타내기 위한 인스턴스를 DTO(Data Transfer Object)라고 합니다.
- java에서는 인스턴스 단위로 데이터를 전송하고자 하면 Serializable 인터페이스를 implements하면 된다. (Override를 하지 않아도 되는 인터페이스다!! 띠용)
- 별도의 method구현이 필요없다.
- 응용프로그램을 만들 때 자신만의 저장 형식을 갖고자 하는 경우 사용하고 안드로이드에서 Activity 사이에 데이터 전송을 하고자 하면 사용한다.
- DataInputStream과 DataOutputStream을 이용해서 사용한다.
- 데이터를 전송하고 전송받을 때 데이터는 항상 하나로 만들어두는 것이 좋다.
🔆 직렬화를 위한 DTO 클래스 생성
- 정수로 된 번호, 문자열로 된 이름, Data로 만들어진 생일을 저장.
package com.eb.serizlizable;
import java.io.Serializable;
import java.util.Date;
//인스턴스 단위로 읽고 쓰기가 가능한 클래스 - Serializable interface 때문
public class StudentDTO implements Serializable{
private int num;
private String name;
private Date birthday;
private String group;
public StudentDTO() {
super();
}
public StudentDTO(int num, String name, Date birthday, String group) {
super();
this.num = num;
this.name = name;
this.birthday = birthday;
this.group = group;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
@Override
public String toString() {
return "StudentDTO [num=" + num + ", name=" + name + ", birthday=" + birthday + ", group=" + group + "]";
}
}
🔆 Main
- 여러개의 객체를 write read하는 것은 전부 모아서 한번만 작업해주어야 한다 따라서 아래와 같이 list.add(인스턴스)를 여러줄 사용하는 것은 안된다.
package com.eb.serizlizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Date;
public class Main {
public static void main(String[] args) {
try {
//인스턴스 단위로 파일에 기록할 수 있는 객체를 생성
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("multiobject.txt"));
//기록할 인스턴스 생성
StudentDTO dto = new StudentDTO(1, "사쿠라", new Date(), "르세라핌");
StudentDTO dto1 = new StudentDTO(2, "민지", new Date(), "뉴진스");
//기록할 인스턴스가 여러개 이므로 하나의 List로 묶어줍니다. (write는 한번만 해주어야 한다.)
ArrayList<StudentDTO> list = new ArrayList<>();
list.add(dto);
list.add(dto1);
//기록
oos.writeObject(list);
oos.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
try {
//인스턴스 단위에 파일에 읽어낼 수 있는 객체를 생성
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("multiobject.txt"));
ArrayList list = (ArrayList)ois.readObject();
for(Object obj : list) {
System.out.println(obj);
}
//하나의 데이터 읽어오기
//StudentDTO dto = (StudentDTO) ois.readObject();
//System.out.println(dto);
ois.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
- ArrayList로 한번에 모아서 writeObject(ArrayList)한번만 해주었다. read해 올때에도 ArrayList로 readObject하여 List를 한개씩 출력해볼 수 있다.
package com.eb.serizlizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Date;
public class Main2 {
public static void main(String[] args) {
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("try&resource.txt"));
//기록할 인스턴스 생성
StudentDTO dto = new StudentDTO(1, "사쿠라", new Date(), "르세라핌");
StudentDTO dto1 = new StudentDTO(2, "민지", new Date(), "뉴진스");
//기록할 인스턴스가 여러개 이므로 하나의 List로 묶어줍니다. (write는 한번만 해주어야 한다.)
ArrayList<StudentDTO> list = new ArrayList<>();
list.add(dto);
list.add(dto1);
//기록
oos.writeObject(list);
oos.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
try {
//인스턴스 단위에 파일에 읽어낼 수 있는 객체를 생성
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("try&resource.txt"));
ArrayList list = (ArrayList)ois.readObject();
for(Object obj : list) {
System.out.println(obj);
}
//하나의 데이터 읽어오기
//StudentDTO dto = (StudentDTO) ois.readObject();
//System.out.println(dto);
ois.close();
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
🔹 데이터의 분류
1) scala data(하나의 데이터) : Byte, Short, Charater, Integer, Long, Float, Double, Boolean + 자바는 String도 하나의 데이터로 본다.
2) Vector data (여러개의 데이터)
* 배열과 List(Collection) : 동일한 종류의 비교 가능한 데이터 , 인덱스를 이용해서 데이터를 구분
* VO 클래스나 Map : 여러개의 데이터를 하나로 묶을 떄 사용, 이름을 이용해서 데이터를 구분
🔹 try - resource
- jdk 1.7에서부터 지원되는 문법
- Stream은 만들면 반드시 close를 해줘야 한다. 하지 않으면 메모리 누수가 발생한다.
- 아래와 같은 try-resource문법으로 자동으로 Stream을 close하도록 해줄 수 있다.
try(여기서 만든 객체가 AutoCloseable 인터페이스를 implements 하고 있다면 close 하지 않아도 try-catch 구문을 벗어나면 자동적으로 close를 호출합니다.){
}catch(Exception e){
}
- 위의 Serializable에서 사용한 코드를 재사용해서 예를 들면 try - chatch 안에서 만든 ObjectOutputStream을 try옆에()안으로 옮겨주고 close를 해주지 않아도 try()안에 넣어준것은 자동으로 close()된다.
package com.eb.serizlizable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Date;
public class Main2 {
public static void main(String[] args) {
//따로 close를 해주지 않아도 자동적으로 close하도록 하는 기능.
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("try&resource.txt"));){
//기록할 인스턴스 생성
StudentDTO dto = new StudentDTO(1, "사쿠라", new Date(), "르세라핌");
StudentDTO dto1 = new StudentDTO(2, "민지", new Date(), "뉴진스");
//기록할 인스턴스가 여러개 이므로 하나의 List로 묶어줍니다. (write는 한번만 해주어야 한다.)
ArrayList<StudentDTO> list = new ArrayList<>();
list.add(dto);
list.add(dto1);
//기록
oos.writeObject(list);
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("try&resource.txt"));){
//인스턴스 단위에 파일에 읽어낼 수 있는 객체를 생성
ArrayList list = (ArrayList)ois.readObject();
for(Object obj : list) {
System.out.println(obj);
}
//하나의 데이터 읽어오기
//StudentDTO dto = (StudentDTO) ois.readObject();
//System.out.println(dto);
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
}
}
}
'국비지원 > JAVA' 카테고리의 다른 글
| [JAVA] 24. Multi-Thread(multi-thread 사용시 고려할 점)와 정규표현식 (0) | 2022.10.31 |
|---|---|
| [JAVA] 23. Nested Class / Anonymous / Lambda / Stream API / Thread (0) | 2022.10.28 |
| [JAVA] 21. List(stack, queue, deque) / Set / Map (0) | 2022.10.26 |
| [JAVA] 21-2. API - java.util pkg (컬렉션 프레임워크) (0) | 2022.10.25 |
| [JAVA] 21-1. API - java.util pkg (Array, Date, Calendar, Random) (0) | 2022.10.25 |