-
입출력 스트림(5) / File프로그래밍/JAVA 자바 2021. 8. 24.반응형
package ioEx3; import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class Ex001_File { public static void main(String[] args) { // TODO Auto-generated method stub String appDir = System.getProperty("user.dir"); //System.out.println("현 작업 경로 : " + appDir); String pathname = appDir + File.separator + "user.txt"; //System.out.println(pathname); // File.separator = 윈도우는 역슬래시\, 맥이나 리눅스는 슬래시/ File f = new File(pathname); // exists() : 폴더 또는 파일이 존재하면 true, 없으면 false if(!f.exists()) { System.out.println(pathname + "파일이 존재 안함"); System.exit(0); } try { System.out.println("파일 정보"); System.out.println("파일명 : "+ f.getName()); // 파일명.확장자 System.out.println("경로명 : "+ f.getPath()); // 파일 경로 System.out.println("절대 경로명 : "+ f.getAbsolutePath()); // 절대 파일 경로 System.out.println("표준 경로명 : "+ f.getCanonicalPath()); // 표준 파일 경로 System.out.println("부모 경로 : "+ f.getParent()); // 부모 경로 폴더 까지만 가져 옴. System.out.println("파일길이(long형, byte단위) : "+ f.length()); System.out.println("파일 생성일자 : "+ new Date(f.lastModified())); // f.lastModified() : 1970.1.1 일 부터 파일 생성일까지를 ms 단위로 환산하여 변환 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); //SimpleDateFormat 원하는 서식으로 날짜를 보고 싶을때(한국식으로 바꾼것) String s = sdf.format(new Date(f.lastModified())); System.out.println("파일 생성일 : " + s); System.out.println("읽기 속성 : " + f.canRead()); System.out.println("쓰기 속성 : " + f.canWrite()); } catch (Exception e) { e.printStackTrace(); } } }
코드 분석
- System.getProperty("user.dir"); => 작업 경로를 보여준다. user.dir의 현재 위치를 보여줌
(폴더 까지만 보여준다.)
- appDir + File.separator + "user.txt"; => 폴더 까지 보여주는 경로에 File.separator가 +가 되는데
이건 / 의 의미이다. 윈도우에서 파일 경로 나눌때 / 로 구분을 짓는데 이게 그걸 나타낸다.
즉 위 소스들을 전부 합쳐보면
user.txt 파일의 현재 위치 + / + "user.txt" 라는 그냥 문자열
단순하게 현재 경로에다가 파일명까지 보여주고 싶어서 붙인것이다.
- File f = new File(pathname); => pathname이라는 폴더나 파일이 존재하면 true 아니면 false
나머지는 소스안 주석을 참고
FileDelete
package ioEx3; import java.io.File; public class Ex002_FileDelete { public static void main(String[] args) { String appDir = System.getProperty("user.dir"); // 현재 작업 경로 String pathname = appDir + File.separator + "test.txt"; File f = new File(pathname); if(! f.exists()) { System.out.println(pathname + "파일이 존재 안함"); System.exit(0); } boolean b = f.delete(); /* * 파일 또는 디렉토리 삭제 * 한번에 하나의 파일 또는 디렉토리만 삭제 가능 * 디렉토리는 비어 있어야 삭제 가능 */ if(b) { System.out.println("파일이 삭제 되었습니다"); }else { System.out.println("파일 삭제 실패"); } } }
- 특정 파일을 삭제하기 위해서 경로를 지정해 주어야 한다.
- 현재 경로 먼저 구해주고
- 현재 경로 + 파일 세퍼레이터 + 삭제할 파일명 문자열
- 파일 객체 f 만들어 준다.
- 파일 존재 유무 확인하고
- .delete() 명령어로 파일 삭제 한다. => 파일이 삭제가 됐으면 true 아니면 false
package ioEx3; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; public class Ex003_Cat { public static void main(String[] args) { // 텍스트 파일 내용 읽기 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String pathname; String s; BufferedReader fbr = null; try { System.out.print("파일명?"); pathname = br.readLine(); File f = new File(pathname); /* if(! f.exists()) { System.out.println("파일이 존재하지 않습니다."); System.exit(0); } *///이 방법 말고 다른 방법도 있음. // 바이트 스트림이 InputStreamReader를 거치면 문자 스트림이 된다. //fbr = new BufferedReader(new InputStreamReader(new FileInputStream(f))); //fbr = new BufferedReader(new InputStreamReader(new FileInputStream(pathname))); // 이렇게 파일명을 바로 줄수도있음 이러면 위에서 File 객체 안만들어도 돼 fbr = new BufferedReader(new FileReader(f)); // 더 간단한 방법이다. // 파일 리더는 전부 텍스트 파일에서만 사용 가능하다. while( (s = fbr.readLine()) != null ) { System.out.println(s); } } catch (FileNotFoundException e) { System.out.println("파일이 존재하지 않습니다."); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { if(fbr != null) { try { fbr.close(); } catch (Exception e2) { // TODO: handle exception } } } } }
경로 지정해서 텍스트 파일 내용 읽기
Cat
* 같은 폴더안에 존재하면 경로를 안쓰고 파일명과 확장자만 써도 됨 ex) user.txt
- BufferedReader br 객체를 만든다 (바이트 스트림을 문자 스트림으로 읽기 위해서 InputStreamReader(System.in) 사용 )
- BufferedReader fbr 객체 하나 더 만들어서 null을 준다 (바이트 스트림 읽기)
- 아까 만든 br로 파일 읽어 온다.
- 그리고 파일 객체에 저장
- FileReader를 이용하여 fbr에 저장
- fbr을 readLine()으로 읽어서 출력
FileList
폴더(경로 포함) 안에 들어있는 폴더와 파일의 목록(리스트) 출력하기.
package ioEx3; import java.io.BufferedReader; import java.io.File; import java.io.InputStreamReader; import java.text.SimpleDateFormat; import java.util.Date; public class Ex004_FileList { public static void main(String[] args) { // 폴더 알려주면 안에 들어있는 파일의 목록 출력하기 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String s; try { System.out.println("경로 ? "); s = br.readLine(); dirList(s); } catch (Exception e) { e.printStackTrace(); } } public static void dirList(String pathname) { // 폴더 알려주면 안에 들어있는 파일의 목록 출력하기 File file = new File(pathname); if (! file.exists()) { System.out.println("디렉토리가 존재하지 않음"); return; } if(! file.isDirectory()) { System.out.println("디렉토리가 아닙니다."); return; } File [] ff = file.listFiles(); // 폴더에 존재하는 자식 폴더 또는 파일에 대한 File 객체를 반환 try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String s; for(File f : ff) { s = sdf.format(new Date(f.lastModified())); if(f.isFile()) { System.out.print(f.getName() + "\t"); System.out.print(s + "\t"); System.out.println(f.length() + "bytes"); } else if(file.isDirectory()) { System.out.println("["+f.getName()+"]"); } } } catch (Exception e) { e.printStackTrace(); } } }
- 함수 하나를 만들어 준다. dirList(String pathname)
* 이 함수의 기능이 주요 기능 구현이다.
* 파일 객체를 (객체명 : file) 생성하고 폴더 이름 및 경로을 담는다.
* 폴더 경로가 존재 하는지 안하는지 검사를 한다. (exists() / isDirectory() 활용)
* 경로가 존재하는게 확인이 됐으면 배열을 만든다.
* file.listFiles();은 폴더에 존재하는 자식 폴더 및 모든 파일을 반환한다.
* 마지막 수정 날짜를 알기 위해서 SimpleDateFormat을 사용한다.
(SimpleDateFormat을 사용하면 내가 원하는 포멧(형식)으로 날짜를 정할 수 있음)
* 만들어둔 배열을 출력하기 위해 for문을 돌린다.
* 파일이 존재하면 파일이름, 수정날짜, 파일크기를 출력하고 / 폴더가 있으면 폴더 이름을 출력한다.
FileMakeDir
폴더 생성 클래스
package ioEx3; import java.io.File; public class Ex005_FileMakeDir { public static void main(String[] args) { // TODO Auto-generated method stub String pathname = "c:"+File.separator+"user"+File.separator+"test"; try { File f = new File(pathname); if(! f.exists()) { f.mkdirs(); // 상위 폴더가 존재하지않으면 상위 폴더도 생성함 //f.mkdir(); // 상위 폴더가 존재하지 않으면 폴더를 생성하지 않음 System.out.println("디렉토리를 생성 했습니다."); } else { System.out.println("이미 존재하는 디렉토리 입니다."); } } catch (Exception e) { e.printStackTrace(); } } }
- pathname에 폴더 만들 경로를 지정 해준다.
- 파일 객체 생성하고
- mkdirs / mkdir 둘 중 하나를 이용한다.
(mkdirs = 상위 폴더가 존재 하지 않으면 상위 폴더도 생성한다.)
(mkdir = 상위 폴더가 존재하지 않으면 폴더를 생성 하지 않는다.)
주로 mkdirs를 사용할것이다.
FileRename
파일 이름을 변경한다.
package ioEx3; import java.io.File; import java.util.Calendar; public class Ex006_FileRename { public static void main(String[] args) { // TODO Auto-generated method stub String appDir = System.getProperty("user.dir"); String pathname = appDir + File.separator + "ex.txt"; File f = new File(pathname); if(! f.exists()) { System.out.println(pathname + "파일이 존재하지않음"); System.exit(0); } // 확장자(.txt) String fileExt = pathname.substring(pathname.lastIndexOf(".")); Calendar cal = Calendar.getInstance(); String newName = String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$ts", cal); newName += System.nanoTime() + fileExt; //System.out.println(newName); try { String newFilename = appDir + File.separator+newName; File dest = new File(newFilename); // 파일 또는 디렉토리 이름 변경 f.renameTo(dest); System.out.println("파일 이름 변경 완료"); } catch (Exception e) { e.printStackTrace(); } } }
- 현재 작업 경로 구하고 파일 세퍼레이터를 이용해서 이름 바꿀 파일 경로까지 찾아준다.
- 파일 객체 생성해서 파일이 존재하는지 확인한다.
- 확장자와 파일을 분리해야하니 substring을 이용한다.
- Calendar.getInstance(); = 현재 시간 정보를 담는다
- String.format을 이용해서 시간 정보를 담는다.
- renameTo로 파일또는 디렉토리의 이름을 변경한다.
디렉토리 폴더 또는 파일 전부 삭제
package ioEx3; import java.io.File; public class Ex007_FileRemove { // C드라이브에 ex 폴더와 내용물 전부 삭제하기 public static void main(String[] args) { String pathname = "c:" + File.separator + "ex"; FileManager fm = new FileManager(); fm.removeDir(pathname); System.out.println("디렉토리 또는 파일 삭제 완료"); } } class FileManager { /** * 파일 또는 폴더 삭제(하위 폴더 및 모든 파일도 제거 됨으로 조심) * @param pathname 삭제할 폴더 또는 파일 * @return 폴더 또는 파일 삭제 여부 * */ public boolean removeDir(String pathname) { boolean b = false; try { File f = new File(pathname); if(f.isDirectory()) { removeSubDir(pathname); } b = f.delete(); } catch (Exception e) { // TODO: handle exception } return b; } private void removeSubDir(String pathname) { File[] ff = new File(pathname).listFiles(); try { if(ff.length == 0) { // 자식이 없으면 return; } for(File f : ff) { if(f.isDirectory()) { removeSubDir(f.getPath()); // 재귀 호출 } f. delete(); } } catch (Exception e) { // TODO: handle exception } } }
- 파일 삭제를 위해 클래스를 새로 만든다.
- FileManager클래스에서는 경로를 입력 받아 파일 또는 디렉토리 폴더를 삭제 할 것이다.
- 파일 객체를 생성하고
- 디렉토리가 존재하는지 확인한다.
- 존재하면 삭제하는 함수를 호출 한다.
- 삭제하는 함수 만들기
- 배열을 만들어서 경로에 있는 모든 디렉토리와 파일들을 객체로 담는다.
- 만약 배열의 길이가 0이라면 아무것도 없다는 뜻이니까 탈출한다.
- 배열을 향상된 for문으로 돌려줘서 내용물 삭제를 진행한다.
- 만약 디렉토리 폴더가 존재 한다면 재귀 호출(자기 자신 호출)을 이용해서 (어차피 폴더 안에는 또 다시 폴더나 파일이 존재 할 수있으니까 ) 삭제 한다.
- 파일이 존재 한다면 그냥 .delete();로 지워주자.
MS949 데이터를 UTF-8 형식의 파일로 저장하기
package ioEx3; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; public class Ex008_Encoding { public static void main(String[] args) { // MS949 데이터를 UTF-8 형식의 파일로 저장하기 int data; String pathname = "test.txt"; try(Writer wt = new OutputStreamWriter(new FileOutputStream(pathname), "UTF-8") ) { Reader rd = new InputStreamReader(System.in,"MS949"); System.out.print("입력 : /종료는 ctrl + z"); while((data=rd.read()) != -1){ wt.write(data); } wt.flush(); } catch (Exception e) { // TODO: handle exception } } }
UTF-8 파일을 MS949 파일로 복사하기
package ioEx3; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; public class Ex009_Encoding { public static void main(String[] args) { // UTF-8 파일을 MS949 파일로 복사하기 String source = "test.txt"; String dest = "ex.txt"; int data; try(Reader rd = new InputStreamReader(new FileInputStream(source)); Writer wt = new OutputStreamWriter(new FileOutputStream(dest))) { while((data = rd.read()) != -1) { wt.write(data); } wt.flush(); System.out.println("변환 저장 완료"); } catch (Exception e) { e.printStackTrace(); } } }
예제)
package ioEx3; import java.io.BufferedReader; import java.io.FileReader; import java.io.PrintStream; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; /* * user1.txt 파일과 user2.txt 파일을 이용하여 user3.txt 파일을 작성한다. * * user1.txt 파일에 없는 학번이 user2.txt 파일에 존재하는 경우 user3.txt 파일에 저장하지 않는다. * * user2.txt에는 학번과 과목별 점수가 무작위로 존재한다. * * user2.txt 파일에 과목 점수가 없는 것은 공백(탭)으로 처리한다. * * user3.txt 파일 출력은 다음과 같은 형식으로 한다. * 학번 이름 국어 영어 수학 */ public class Ex011_userEx { public static void main(String[] args) { // TODO Auto-generated method stub User ob = new User(); ob.loadFile1(); ob.loadFile2(); ob.saveFile(); System.out.println("파일 저장 완료"); } } class UserVO { private String name; private Integer kor; private Integer eng; private Integer mat; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getKor() { return kor; } public void setKor(Integer kor) { this.kor = kor; } public Integer getEng() { return eng; } public void setEng(Integer eng) { this.eng = eng; } public Integer getMat() { return mat; } public void setMat(Integer mat) { this.mat = mat; } @Override public String toString() { // TODO Auto-generated method stub String s = name+"\t"; s+= kor == null ? "\t" : kor+"\t"; s+= eng == null ? "\t" : eng+"\t"; s+= mat == null ? "\t" : mat+"\t"; return s; } } class User{ /* * TreeMap = 키로 정렬하여 저장 * private Map<String, UserVO> map = new TreeMap<>(); * * LinkedHashMap = 등록된 순서로 저장 * private Map<String, UserVO> map = new LinkedHashMap<String, UserVO>(); * * HashMap = 등록 순서는 랜덤 * private Map<String, UserVO> map = new HashMap<String, UserVO>(); */ private Map<String, UserVO> map = new TreeMap<>(); private String pathname1 = "user1.txt"; private String pathname2 = "user2.txt"; private String pathname3 = "user3.txt"; public void loadFile1() { try(BufferedReader br = new BufferedReader(new FileReader(pathname1))) { String s; while((s = br.readLine()) != null) { String[] ss = s.split(","); if(ss.length != 2) { //유저1 텍본 파일에서 콤마로 나누고 나면 2개여야 하는데 혹시 아니면 처리 안한다. continue; } UserVO vo = new UserVO(); vo.setName(ss[1]); // 국영수는 null map.put(ss[0], vo); } } catch (Exception e) { e.printStackTrace(); } } public void loadFile2() { try(BufferedReader br = new BufferedReader(new FileReader(pathname2))) { String s; while((s = br.readLine()) != null) { String [] ss = s.split(","); if(ss.length<2) { continue; } UserVO vo = map.get(ss[0]); // 학번의 데이터를 Map에서 가져오기 if(vo == null) { continue; // 데이터가 없으면 } int n; for(int i=1; i<ss.length; i++) { String[] c = ss[i].split(":"); n = Integer.parseInt(c[1]); if(c[0].equals("kor")) { vo.setKor(n); } else if(c[0].equals("eng")) { vo.setEng(n); } else if(c[0].equals("mat")) { vo.setMat(n); } } } } catch (Exception e) { e.printStackTrace(); } } public void saveFile() { try(PrintStream ps = new PrintStream(pathname3)) { Iterator<String> it = map.keySet().iterator(); while(it.hasNext()) { String hak = it.next(); UserVO vo = map.get(hak); ps.println(hak + "\t" + vo); } } catch (Exception e) { e.printStackTrace(); } } }
반응형'프로그래밍 > JAVA 자바' 카테고리의 다른 글
자바로 오라클 DB 간섭하기 / Statement / ResultSet (0) 2021.08.26 입출력 스트림(6) / PrintStream (0) 2021.08.24 입출력 스트림(4) / FileCopy / FileWriter / FileReader (0) 2021.08.24 입출력 스트림(2) / Reader / 예제 소스 분석 (0) 2021.08.24 입출력 스트림(1) / InputStream, OutputStream (0) 2021.08.24