국비교육(22-23)

21일차(3)/java(30) : Input, Output(2)

서리/Seori 2022. 11. 4. 01:25

21일차(3)/java(30) : Input, Output(2)

 

MainClass07

- 파일시스템 접근하기

package test.main;

import java.io.File;

public class MainClass07 {
	public static void main(String[] args) {
		// c:/를 Access 할 수 있는 파일 객체 생성
		File f=new File("c:/");
		String[] names=f.list();
		//배열에 들어있는 문자열 모두 출력하기
		for(int i=0; i<names.length; i++) {
			String tmp=names[i];
			System.out.println(tmp);
		}
		
		System.out.println("---------------");
		
		for(String tmp:names) {			
			System.out.println(tmp);
		}
	}
}

 

 

- File. 으로 사용할 수 있는 파일에 관련된 객체들이 매우 많다!

 

.list();

- C:/ 에 들어있는 파일, 폴더 등의 이름을 배열에 넣어서 하나씩 다 출력하기!

 

- for문으로 계속 돌면서 총 파일/폴더 갯수만큼 반복한다.

- 확장 for문으로도 작성

- file객체의 list라는 메소드는 파일시스템 안에 들어있는 내용을 배열에 넣어 출력하는 기능

 

 


 

MainClass08

- 파일시스템 접근해서 목록 읽어오기

package test.main;

import java.io.File;

public class MainClass08 {
	public static void main(String[] args) {
		File f=new File("c:/");
		//파일객체 목록(file[])을 얻어내기
		File[] files=f.listFiles();
		
		for(File tmp:files) {
			if(tmp.isDirectory()) {
				//대괄호를 디렉토리명 양쪽에 출력하기
				System.out.println("[ "+tmp.getName()+" ]");
			}else {
				//파일이면 파일명만 출력
				System.out.println(tmp.getName());
			}
		}
	}
}

 

 

.listFiles();

- access할 수 있는 파일객체를 생성해서 배열에 담아서 리턴한다.

 단순히 이름만 리턴하는것이 아니라!

 

.isDirectory() : 호출하면 이게 디렉토리인지 파일인지 알 수 있다.(boolean 값 리턴)

.getName() : 파일의 이름을 얻어낼 수 있다.

 

- 아까와는 다른 모양으로 출력되는데, 디렉토리와 파일이 구분된다.

 


 

MainClass09

- 파일시스템 접근해서 파일 생성/삭제

package test.main;

import java.io.File;
import java.io.IOException;

public class MainClass09 {
	public static void main(String[] args) {
		//이미 존재하거나 혹은 만들 예정인 파일을 제어할 수 있는 File 객체 생성
		File f1=new File("C:/acorn202210/myFolder/sy.txt");
			try {
				//만약 해당 파일이 존재하지 않으면
				if(!f1.exists()) {
					f1.createNewFile();
					System.out.println("sy.txt파일을 만들었습니다.");
				}else {
					f1.delete();
					System.out.println("sy.txt파일을 삭제했습니다.");
				}
			}catch(IOException ie) {
				ie.printStackTrace();
			}
	}	
}

 

.createNewFile(); : 신규파일생성

.delete(); : 파일 삭제

 

- if문을 사용해 파일이 있으면 삭제하고, 없으면 생성한다.

- 예외처리 try문 안에 넣어 예외발생시에 대처!

 


 

MainClass10

- 파일시스템 접근해서 폴더 생성/삭제

package test.main;

import java.io.File;

public class MainClass10 {
	public static void main(String[] args) {
		File f1=new File("C:/acorn202210/myFolder/folder1");
		//폴더 만들기
		f1.mkdir();
		
		for(int i=0; i<20; i++) {
			File tmp=new File("C:/acorn202210/myFolder/folder"+i);
			//tmp.mkdir(); //폴더 만들기
			tmp.delete(); //폴더 삭제하기
		}
	}
}

 

.mkdir(); : 폴더 생성하기. make directory

 

- 폴더를 1,000개 만들고싶다면... for 문 안에 넣으면 된다.

- 삭제도 동일하게 할 수 있다.

 

- 주의 : 파일 객체로 아무거나 삭제하면 안 된다! 파일 객체로 삭제하면 복구가 안 된다.

- 파일 객체는 특정 파일에 access할 수 있는 객체

 


 

MainClass11

- 파일시스템 접근해서 파일에 문자 출력하기

package test.main;

import java.io.File;
import java.io.FileWriter;

public class MainClass11 {
	public static void main(String[] args) {
		//문자열을 저장할 파일을 만들기 위한 File 객체
		File memoFile=new File("C:/acorn202210/myFolder/memo.txt");
		try {
			//만일 파일이 존재하지 않으면
			if(!memoFile.exists()) {
				//파일을 만들고
				memoFile.createNewFile();
			}
			//파일에 문자열을 출력할 수 있는 객체의 참조값 얻어내기
			FileWriter pw=new FileWriter(memoFile, true);			
			pw.write("안녕");
			pw.write("\r\n");
			pw.write("하세요");
			pw.write("\r\n");
			pw.write("\t"); // \t는 tab 들여쓰기이다.
			pw.write("반가워요\r\n");
			pw.flush();
			pw.close();			
			System.out.println("파일에 문자를 저장했습니다.");
		} catch (Exception e) {
			e.printStackTrace();
		}		
	}
}

 

if(!memoFile.exists()) {}

- 만일 메모파일이 존재하지 않으면, 이라고 읽는다.( ! 연산자에 익숙해지기)

 

- if문을 try{} 안에넣고 catch(Exception e) 로 모든 예외를 처리해버림

 

- 파일객체에는 문자열을 출력할 수 있는 기능이 없다.

FileWriter : 파일에 문자열을 기록하고 싶을 때 사용

 

- FileWriter에 String타입을 받아 기록하는 메소드가 있다.

 

 

- 생성자 중 파일객체를 인자로 사용하는 생성자 사용!

 

- memo.txt파일에 텍스트를 전달하여 출력한다.

- run 하고 파일 안에서 값이 들어가있는 것을 확인할 수 있다.

 

 

참고)

- 인자 하나짜리 FileWriter 생성자를 사용하면 기본값이 덮어쓰기 상태이다. 여러번 run 해도 문자열이 누적되지 않는다.

- file, boolean 타입 2가지를 인자로 갖는 생성자를 사용해 append모드로 하면(true),

 기본 덮어쓰기 상태(false)인 것을 바꾸어, 기존의 문자열을 유지하면서 덧붙일 수도 있다.

 

- 개행기호, 탭을 사용해서 위와 같이 출력할 수 있다. 개행기호, 탭을 모두 인식한다.

- \t 는 tab을 가리킨다.

 

 


 

MainClass12

- 파일시스템 접근해서 파일에서 문자 읽어오기

package test.main;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

/*
 * C:/acorn202210/myFolder/memo.txt 파일에 기록된 문자열을 읽어서
 * 콘솔창에 출력해 보세요.
 * 
 * -hint
 * FileReader객체를 잘 활용해 보세요.
 */
public class MainClass12 {
	public static void main(String[] args) {
		//File객체
		File memofile=new File("C:/acorn202210/myFolder/memo.txt");

		try {
			//파일에서 문자열을 읽어들일수 있는 객체 생성
			FileReader fr=new FileReader(memofile);
			//반복문 돌면서
			while(true) {
				//한글자씩 읽어들인다.
				int code=fr.read();
				//만일 더이상 읽을 문자가 없으면
				if(code==-1) {
					break; //반복문 탈출!
				}
				//코드값을 문자로 변환해서
				char ch=(char)code;
				//개행기호 없이 읽은 내용만 출력
				System.out.print(ch);
			}
		} catch (Exception e) {			
			e.printStackTrace();
		}		
	}
}

 

 

 

- 파일에서 메모리로 읽어들여서 콘솔로 출력하기!

 

- 파일에서 읽어들일 때는 new하는 것이고, 출력할 때는 system.out만 활용하면 된다.

 

- String type을 리턴하고 싶은데 String타입이 없다...

 

read(); 메소드의 설명을 보면(좌측 노란색 창) 아래와 같다.

 Returns: The character read, or -1 if the end of the stream has been reached

 (한글자씩 읽어내고 전부 다 읽었을 때 더이상 읽을것이 없으면 -1을 리턴한다.)

 

- 몇 번이나 돌아야 되는지 모르므로 while문 사용!

- 읽어온 코드값이 -1이 되면 while문을 중단하도록 작성한다.

 

- 읽어서 콘솔에 출력한 모습. 개행기호도 전부 하나하나 읽어서 콘솔창으로 가져온 것이다.

 

 

- 디버그모드에서 하나씩 돌려보면 while → if → char → syso 행을 순서대로 읽어내는 것을 볼 수 있다.

- 코드가 -1이 되면 break; 에서 정지하고 밖으로 빠져나온다.

 


 

MainClass13

- 파일시스템에서 읽어오는 FileReader를 BufferedReader로 포장하기

package test.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

/*
 * C:/acorn202210/myFolder/memo.txt 파일에 기록된 문자열을 읽어서
 * 콘솔창에 출력해 보세요.
 * 
 * -hint
 * FileReader객체를 잘 활용해 보세요.
 */
public class MainClass13 {
	public static void main(String[] args) {
		//File객체
		File memofile=new File("C:/acorn202210/myFolder/memo.txt");

		try {
			//파일에서 문자열을 읽어들일수 있는 객체 생성
			FileReader fr=new FileReader(memofile);
			BufferedReader br=new BufferedReader(fr);
			//반복문 돌면서
			while(true) {
				//개행기호를 기준으로 한줄씩 읽어오기 때문에 개행기호는 읽어오지 않는다.
				String line=br.readLine();				
				if(line==null) {
					break;
				}			
				//읽어낸 문자열 콘솔에 출력하기
				System.out.println(line);
			}	
		} catch (Exception e) {			
			e.printStackTrace();
		}		
	}
}

 

- BufferedReader는 글자 단위가 아니라 줄 단위로 읽어온다.

- FileReader를 인자로 받는 BufferedReader 타입 변수 생성

 

.readLine : 데이터를 읽어내주는 메소드인데 String 타입!

- 참조값을 리턴해주는 메소드는 보통 더이상 읽을 문자열이 없을 때 null을 리턴한다.

- 개행기호를 기준으로 한줄씩 읽어오기 때문에 따로 개행기호는 읽어오지 않는다.

 

if(line==null) { break; }

- while안에 탈출조건이 null인 if문 작성!

 


 

MainClass14

- 입/출력 작업의 마무리작업 close 사용

package test.main;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;

/*
 * C:/acorn202210/myFolder/memo.txt 파일에 기록된 문자열을 읽어서
 * 콘솔창에 출력해 보세요.
 * 
 * -hint
 * FileReader객체를 잘 활용해 보세요.
 */
public class MainClass14 {
	public static void main(String[] args) {
		//File객체
		File memofile=new File("C:/acorn202210/myFolder/memo.txt");

		//필요한 객체를 담을 지역변수를 미리 만들어준다.
		FileReader fr=null;
		BufferedReader br=null;
		try {
			//미리 만들어둔 지역변수에 참조값 대입하기
			fr=new FileReader(memofile);
			br=new BufferedReader(fr);
			//반복문 돌면서
			while(true) {
				//개행기호를 기준으로 한줄씩 읽어오기 때문에 개행기호는 읽어오지 않는다.
				String line=br.readLine();				
				if(line==null) {
					break;
				}			
				//읽어낸 문자열 콘솔에 출력하기
				System.out.println(line);
			}			
		} catch (Exception e) {			
			e.printStackTrace();
		}finally {
			//마무리작업을 해주어야 되는데...
			try {
				//닫는 작업은 열린 순서의 역순으로 하면 좋다.
				if(br!=null)br.close();
				if(fr!=null)fr.close();
			}catch(Exception e){}
		}		
	}
}

 

- 프로세스가 아주 잠깐 만들어졌다가 데이터를 읽어오고 사라진다.

- 하지만 만약 어플리케이션이 쭉 실행중이라면, 이런 입출력을 하는 기능들이 자리를 차지할 수 있다.

- fr, br 과 같은 작업은 사실 어떤 마무리(종료작업)를 해주어야 한다. (지금은 크게 상관없지만..)

 

.close : 객체를 종료하는 메소드

- 다 사용한 입출력하는 객체들은 사용하고 나서 닫아주어야 한다!

- 지속적으로 사용되는 어플리케이션이라면 남은 입출력 객체가 꾸준히 메모리를 점유해 문제를 발생시킬 수 있다.

 

 

- 마무리 작업을 해주어야 되는데... 어떤 이유때문에 마무리를 못할 가능성이 있다면 try~catch문으로.

- close는 보통 열린 순서의 역순으로 닫아준다.

 

- 저 위치에 close가 위치해 있으면, catch문으로 들어가버릴 경우에는 close 할 수 없다.

→ 무조건 실행이 보장되는 블럭에 들어있어야 한다.

 

- finally절로 위치를 옮겨주었더니 br, fr 지역변수가 참조되지 않는다...

 

- br,fr 객체 생성시 exception 발생 가능성이 있으므로 try문 바깥으로 뺄 수 없는데,

 try문 안에서는 finally절에서 참조가 안 된다...

 

 

- try문 바깥에서 변수를 미리 만들고, 참조값은 나중에 넣는 방식으로 해결한다.(try문 안에서)

 

 

- finally블럭 안에 close를 넣었는데, 위에서 예외가 생긴 경우 br,fr이 null일 수도 있다.

 그런 경우 br, fr를 제대로 close 할 수 없으므로 nullpointException이 발생하고,

 finally절로 오더라도 FileReader(br,fr)를 close 하지 못할 상황이 생길 수 있다.

- finally절 안에 if문을 넣어 안전하게 마무리한다.

 

- nullPointException : 참조값이 없다는 뜻!

 

 

 

- java 코드가 이런 순서로 진행되는 경우가 많으니 기억하기!

 

1. try문에서 지역변수 만들기

2. 참조값은 try블럭 안에서 들어가고

3. 객체는 어떤 작업을 하고

4. 어떤 예외가 발생했건 관계없이 finally블럭에서 마무리 작업