본문 바로가기
☁︎KOSTA/☂︎KOSTA-JAVA

[KOSTA] Spring 기반 Cloud 서비스 구현 개발자 양성 (Day 17) - File(Reader, Writer), IO(Stream)

by 하_센세 2022. 8. 23.

2022.08.23 [TUE]

- Day 17- 

 

수업 주요 목차

  •  java.io.File
  •  IO (InputStream, OutputStream)
  • File(Reader, Writer) -> 객체 직렬화

🤖Review

Java SE 면접예상 내용 한줄요약해보기

  1. polymorphism : 하나의 소통방식으로 다양한 객체가 각자의 기능에 따라 동작하는 성질
  2. interface : 다양한 계층구조를 형성하여 다형성을 지원
  3. abstract : 추상적 클래스/method로 직접 객체화 되지 않고 부모의 역할에 집중하여 자식에게 멤버를 물려주고 구현을 강제한다.
  4. 소프트웨어 개발방법론 : waterfall/agile(사용자의 요구에 신속/기민하게 반응; TDD,pair programming, kanban;반복/점증)
  5. UML: 프로그램 분석/설계 기초 언어로 class diagram 사용 
  6. (5와 이어지는) class diagram에서 사용되는 relation은 association(use a), aggregation(has a), composition(consist of a), generalization, realization이 있다.
  7. String : 문자열 담당 클래스 / 불변 / 여러곳에서 하나의 문자열을 사용할 때
  8. StringBuilder : 문자열 담당 클래스 / 가변 / 문자열 자체가 자주 변경될 때
  9. Set : 중복을 허용하지 않게 데이터 관리
  10. List : index로 데이터를 관리
  11. 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^^ 환장...

 

//오늘의 숙제

복습!!