2022.08.23 [TUE]
- Day 17-
수업 주요 목차
- java.io.File
- IO (InputStream, OutputStream)
- File(Reader, Writer) -> 객체 직렬화
🤖Review
Java SE 면접예상 내용 한줄요약해보기
- polymorphism : 하나의 소통방식으로 다양한 객체가 각자의 기능에 따라 동작하는 성질
- interface : 다양한 계층구조를 형성하여 다형성을 지원
- abstract : 추상적 클래스/method로 직접 객체화 되지 않고 부모의 역할에 집중하여 자식에게 멤버를 물려주고 구현을 강제한다.
- 소프트웨어 개발방법론 : waterfall/agile(사용자의 요구에 신속/기민하게 반응; TDD,pair programming, kanban;반복/점증)
- UML: 프로그램 분석/설계 기초 언어로 class diagram 사용
- (5와 이어지는) class diagram에서 사용되는 relation은 association(use a), aggregation(has a), composition(consist of a), generalization, realization이 있다.
- String : 문자열 담당 클래스 / 불변 / 여러곳에서 하나의 문자열을 사용할 때
- StringBuilder : 문자열 담당 클래스 / 가변 / 문자열 자체가 자주 변경될 때
- Set : 중복을 허용하지 않게 데이터 관리
- List : index로 데이터를 관리
- Map : key와 value로 데이터를 관리
IO : 입출력
Stream : 입출력을 위한 장치
: 사전적 의미 : 줄기, 시냇물
4가지 IO abstract class | ||
ByteStream(1byte) | CharacterStream(2byte) | |
입력 | InputStream | Reader |
출력 | OutputStream | Writer |
NodeStream 계열 : 직접 장치에 연결되는 스트림 계열
ex) FileReader, FileOutputStream ...
ProcessingStream 계열 : 기존 스트림에 연결되어 다양한 기능을 지원하는 스트림 계열
ex) BufferedReader, BufferedOutputStream ...
🔎 Eclipse 실습 내용
1. File.separator / exists() / mkdirs() / getPath() / createNewFile()
package step1;
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) {
String path="hasense"+File.separator+"kosta250"+File.separator+"iotest1";
File dir1=new File(path);
System.out.println("존재유무: "+dir1.exists()); // 존재유무 : false
System.out.println("디렉토리생성: "+dir1.mkdirs());
System.out.println("존재유무: "+dir1.exists());// 존재유무 : true
//dir1 파일객체의 경로 (iotest1) 디렉토리 아래에 memo1.txt 파일을 생성해본다.
System.out.println("dir1의 경로: "+dir1.getPath());
File file1=new File(dir1.getPath()+File.separator+"memo1.txt"); //정상흐름
//File file1=new File("h/"+File.separator+"memo1.txt"); 예외흐름 (존재하지 않는 경로를 입력해 예외를 발생시
try {
boolean result=file1.createNewFile();
System.out.println(file1.getPath()+" 파일생성:"+result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
↓
존재유무: false
디렉토리생성: true
존재유무: true
dir1의 경로: hasense/kosta250/iotest1
hasense/kosta250/iotest1/memo1.txt 파일생성:true
2. isDirectory() / isFile() /
package step1;
import java.io.File;
import java.io.IOException;
public class TestFile2 {
public static void main(String[] args) {
File dir=new File("hasense/"+File.separator+"kosta250"+File.separator+"iotest1");
System.out.println("디렉토리여부: "+dir.isDirectory());
System.out.println("파일여부: "+dir.isFile());
// dir 내부에 memo2.txt~memo5.txt까지 생성
for(int i=2;i<=5;i++) {
File f=new File(dir.getPath()+File.separator+"memo"+i+".txt");
try {
f.createNewFile();
} catch(IOException e) {
e.printStackTrace();
} //catch
} //for
System.out.println("생성완료");
} //method
} //class
↓
디렉토리여부: true
파일여부: false
생성완료
3. 파일 삭제 테스트(강사님이랑 같이 풀이)
package step2;
import java.io.File;
public class FileService {
private String path;
public FileService(String path) {
super();
this.path = path;
}
//path 경로 디렉토리에 있는 fileName에 해당하는 파일을 삭제, 삭제 여부를 boolean으로 리턴
public boolean deleteFile(String fileName) {
File f1= new File(path+File.separator+fileName);
return f1.delete();
}
}
package step2;
import java.io.File;
public class TestFileService {
public static void main(String[] args) {
String path="hasense/"+File.separator+"kosta250"+File.separator+"iotest1";
FileService service=new FileService(path);
String fileName="memo3.txt";
boolean result=service.deleteFile(fileName);
System.out.println(fileName+" 삭제: "+result); // 삭제되면 true 아니면 false
}
}
↓
memo3.txt 삭제: true
4) 파일 이동 테스트(성공!)
* 이동시킬 디렉토리를 생성(mkdirs method 사용)
* 원본파일객체 생성, 이동시킬파일객체 생성
* renameTo method 적용해서 이동시킴
package step2;
import java.io.File;
public class TestFileService2 {
public static void main(String[] args) {
String path="hasense/"+File.separator+"kosta250"+File.separator+"iotest1"; // 원본파일 경로
FileService service=new FileService(path);
String fileName="memo1.txt";
String destDir="hasense/"+File.separator+"kosta250"+File.separator+"iotest2"; // 이동시킬 디렉토리
boolean result=service.moveFile(fileName,destDir);
System.out.println(fileName+" 이동:"+result);
}
}
public boolean moveFile(String fileName, String destDir) {
new File(destDir).mkdirs();
File f1=new File(path+File.separator+fileName);
File f2=new File(destDir+File.separator+fileName); // f1.getName() -> fileName대신 추후 사용해야 할 경우가 있다.
return f1.renameTo(f2);
}
↓
memo1.txt 이동:true
폴더에서도 확인해보면 옮겨져있었다.(짱재밌어...짜릿해)
아래처럼 객체 생성을 해줬었는데 생각해보니 디렉토리 만들어주고 역할이 끝인 객체라서 그냥 일회용으로 바꿔서 해보니 결과가 같았다!
File f2=new File(destDir);
f2.mkdirs();
5. 디렉토리 내의 파일 및 폴더의 리스트 정보
package step2;
import java.io.File;
public class TestFileService3 {
public static void main(String[] args) {
String path="hasense/"+File.separator+"kosta250"+File.separator+"iotest1"; // 원본파일 경로
FileService service=new FileService(path);
//폴더&파일명만 출력
service.printDirectoryAndFileInfo();
System.out.println("**************");
//폴더&파일명 출력시
//directory: food
// file: memo2.txt ...
service.printDirectoryAndFileInfo2();
}
}
public void printDirectoryAndFileInfo() {
File f1=new File(path);
String[] info=f1.list(); // 이게 빠졌었
for(int i=0;i<info.length;i++) {
System.out.println(info[i]);
}
}
public void printDirectoryAndFileInfo2() {
File f1=new File(path);
File[] info=f1.listFiles();
for(int i=0;i<info.length;i++) {
if(info[i].isFile()) {
System.out.println("file: "+info[i].getName());
} else if(info[i].isDirectory()) {
System.out.println("directory: "+info[i].getName());
}
↓
.DS_Store
memo4.txt
memo5.txt
memo2.txt
food
**************
file: .DS_Store
file: memo4.txt
file: memo5.txt
file: memo2.txt
directory: food
(.DS_Store 파일은 맥에서 자동으로 생성해주는 파일이라 나중에 설정으로 꺼줄 수도 있다는데 일단은 내가 만든거 아니고 맥북이 이놈이가 만든거)
6. FileWriter&PrintWriter
package step3;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class TestOutput {
public static void main(String[] args) {
String path="hasense"+File.separator+"kosta250"+File.separator+"iotest"+File.separator+"song.txt";
File f1=new File(path);
System.out.println(f1.exists());
System.out.println(f1.isFile());
System.out.println(f1.getPath());
System.out.println(f1.getParent());
//song.txt의 상위 디렉토리 정보를 파일객체로 반환받아 디렉토리를 생성한다.
f1.getParentFile().mkdirs();
PrintWriter pw=null;
FileWriter fw=null;
try {
//NodeStream : 직접 장치에 연결
fw=new FileWriter(f1,true); //true : append
//ProcessingStream : 기존 스트림에 연결되어 기능을 지원
pw=new PrintWriter(fw);
pw.println("즐거운 화요일 오후");
System.out.println("출력완료");
} catch (IOException e) {
e.printStackTrace();
} finally {
if(pw!=null)
pw.close();
}
}
}
↓
true
true
hasense/kosta250/iotest/song.txt
hasense/kosta250/iotest
🧚♂️입출력 스트림은 사용 후 반드시 닫아줘야 한다.(buffer에 있는 데이터를 모두 출력 -> flush)
안닫아주면 아래처럼 아무런 변화도 없지만
↓
닫아주면 이렇게 적용이 된다.
7. FileWriter
- NodeStream 계열인 FileWriter 생성 filepath를 인자값으로 전달하고 append 기능을 위해 true를 할당한다.
- ProcessingStream 계열인 PrintWriter를 생성 println(message)를 이용헤 파일에 정보를 출력
- 사용한 스트림을 반드시 닫아주기 위해 close()를 실행한다.
- close() : 자원을 다 사용했을음 시스템에게 알리고 버퍼의 데이터를 모두 출력한다. => try ~ finally
package step4;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class OutputService {
FileWriter fw = null;
PrintWriter pw = null;
public void createFileAndWriteMessage(String filePath, String message) throws IOException {
try {
fw = new FileWriter(filePath, true); //append true
pw = new PrintWriter(fw);
pw.println(message);
} finally {
if(pw!=null)
pw.close();
}
}
}
-main
package step4;
import java.io.File;
import java.io.IOException;
import common.DirInfo;
public class TestOutputService {
public static void main(String[] args) {
OutputService service=new OutputService();
String filePath=DirInfo.OUTPUT_TEST_PATH+File.separator+"friends.txt";
String message="손흥민";
try {
service.createFileAndWriteMessage(filePath,message);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("출력완료");
}
}
↓
출력완료
8. PrintWriter
선수명을 입력하세요: 손흥민 -> 엔터키 누르면 player.txt.에 출력 선수명을 입력하세요: 서정우 -> 엔터키 누르면 player.txt.에 출력 선수명을 입력하세요: 김민석 -> 엔터키 누르면 player.txt.에 출력 선수명을 입력하세요: exit -> 엔터키 누르면 "선수명단 출력을 완료했습니다." |
- 콘솔에서 입력스트릠 생성 Scanner(System.in)
- 파일에 출력하는 스트림 생성 new PrintWriter(new FileWriter(filePath,true))
- while(true){
- sc.nextLine(); => pw.println()
- exit가 입력되면 while loop 종료
- finally
- pw.close(); => 스트림 닫아주고 flush(buffer에 있는 데이터 출력)
package step5;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class OutputService2 {
private String filePath;
public OutputService2(String filePath) {
super();
this.filePath = filePath;
}
PrintWriter pw=null;
public void writePlayer() throws IOException {
Scanner sc=new Scanner(System.in);
pw=new PrintWriter(new FileWriter(filePath,true));
try {
while(true) {
System.out.println("선수명을 입력하세요: ");
String info=sc.nextLine();
if(info.equals("exit")) {
System.out.println("선수명단 출력을 완료했습니다.");
break;
}
pw.println(info);
}
} finally {
if(pw!=null)
pw.close();
}
sc.close();
}
}
-main
package step5;
import java.io.File;
import java.io.IOException;
import common.DirInfo;
public class TestOutputService2 {
public static void main(String[] args) {
String filePath=DirInfo.OUTPUT_TEST_PATH+File.separator+"player.txt";
OutputService2 service=new OutputService2(filePath);
try {
service.writePlayer();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
↓
선수명을 입력하세요:
기성용
선수명을 입력하세요:
손흥민
선수명을 입력하세요:
구자철
선수명을 입력하세요:
exit
선수명단 출력을 완료했습니다.
🤮ERROR🤮
1. Test클래스에 main method 안씀...^^(이게 오류의 원흉이 되었지...뭘 쳐도 다 에러가 뜨니 멀어도 너무 멀리까지 갔다 옴)
2. FileWriter은 따로 null로 초기화 해주지 않아도 된다!(파일생성은 한번만 하면 되니까)
3. pw.close()를 위해 try{} finally{}를 만들어두고 시작하면 편했을텐데 역시나 중괄호때문에 꽤나 애먹음
4. 스캐너 입력값을 참조변수에 따로 넣어주고(위치 헷갈렸는데 while문 안에 넣으면 됐었음) exit만 조건으로 만들어준 뒤 조건 끝나면 파일에 작성해주도록 쓰면 되는 거였음!
5. 아, 맨 처음에 PrintWriter 선언해줄 때 pw=빼먹었다가 다시 떴다 떴다 에러 ㅎ
6. try,catch는 메인에서, Service에서는 throws!!
-강사님 ver.
package step5;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Scanner;
public class OutputService3 {
private String filePath;
public OutputService3(String filePath) {
super();
this.filePath = filePath;
}
/*
* 강사님 풀이
*/
public void writePlayer() throws IOException {
Scanner sc=null;
PrintWriter pw=null;
try {
sc=new Scanner(System.in); //입력 스트림
pw=new PrintWriter(new FileWriter(filePath,true)); // 출력 스트림
while(true) {
System.out.println("선수명을 입력하세요: ");
String info=sc.nextLine();
if(info.equalsIgnoreCase("exit")) { //대소문자 상관없이 비교
System.out.println("선수명단 출력완료");
break; // while문을 종료한다.
}
pw.println(info); //파일에 출력
}
} finally {
if(pw!=null)
pw.close();
if(sc!=null)
sc.close();
}
}
}
-다른점-
1) Scanner도 null로 초기화 하신 것
2) 변수 두개 다 method 안에 넣으신 것(지금 당장 method에서만 사용할 거니까)
3)pw랑 sc모두 finally에 조건달아 넣으신 것(이래서 초기화를 시키셨었군...!)
9.BufferedReadeer
package step6;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import common.DirInfo;
public class TestInput {
public static void main(String[] args) {
//입력을 위한 NodeStream
BufferedReader br=null;
try {
FileReader fr=new FileReader(DirInfo.OUTPUT_TEST_PATH+File.separator+"friends.txt"); // 입력 NodeStream
br=new BufferedReader(fr); // 입력 ProcessingStream
System.out.println("입력스트림생성");
System.out.println(br.readLine()); // 더 이상 입력할 라인이 없으면 null을 반환
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if(br!=null)
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
↓
입력스트림생성
손흥민
// 오늘의 단축키
X
//오늘의 질문
예제 8번에서 자꾸 에러가 뜨는데 틀린 부분은 없어서 결국 질문하니 main method missing^^ 환장...
//오늘의 숙제
복습!!