코딩 기록들

[Java Programming] 12.1 File I/O 본문

Java

[Java Programming] 12.1 File I/O

코딩펭귄 2024. 2. 1. 11:25

File클래스는 파일의 데이터를 읽고쓰는 기능은 지원하지 않음 : 파일의 입출력은 스트림을 사용해야됨

1. 파일을 객체로 생성

File file = new File("C:\\Temp\\file.txt");

2. 해당 경로에 File / Directory 가 실제로 있는지 확인

booldean is Exist = file.exists();

3. exist() 리턴값이 false : createNewFile(), mkdirs() 메소드로 파일 / 디렉토리 생성

exist() 리턴값이 true : canExecute(), canRead(), canWrite(). getParent(), getName()등 통해 정보 얻어내기

 

 

File Input 

파일 읽기 (File System -> Java)

- 자바로 파일을 가져오는것

File output

파일 쓰기 (Java -> File System)

 

1. File Input

파일의 기본적인 정보를 얻어오는 방법

- File 클래스를 사용 -> File 객체 만들어서 사용

- Java의 File객체를 통해 파일의 기본적인 정보(파일의 절대경로, 파일의 크기 등등) 얻어올 수 있음

ex) File file = new File("C:\\Java Exam", "Java Exam.txt");  // Java.Exam폴더에서 Java Exam.txt.를 가져와서 file 이라는 인스턴스에 넣어라   // 첫번째 파라미터 :  파일의 위치 , 두번째파라미터 : 파일 이름(확장자까지 적기)

File file = new File("C:\\Java Exam", "Java Exam.txt");
System.out.println(file.exists()); 파일이 존재하는지 여부 확인
(
없으면 file not found exception 발생 (존재한다면 true) )
System.out.println(file.isFile()); 파일 객체인지 확인  : 파일이면 true, 폴더라면 false
System.out.println(file.isDirectory()); 폴더 객체인지 확인  : 맞다면 true
System.out.println(file.getAbsolutePath()); 파일의 절대경로 확인 :  모든위치를 문자열로 받음
System.out.println(file.getName()); 파일의 이름 확인
System.out.println(file.length()); 파일의 크기(byte) 확인  : 전부 long타입으로 반환됨
System.out.println(file.lastModified());  파일이 마지막으로 수정된 시간
Date date = new Date(file.lastModified());  
System.out.println(file.getParent());  파일이 존재하는 경로 // C:\\Java Exam
System.out.println(file.listFiles());    객체가 폴더일 경우, 폴더내에 존재하는 모든 항목의 목록
 : 만약 폴더라면, 폴더내부의 모든 폴더목록과 파일목록 출력

 

Input - 입력(ReadandPrint) 예제
public class FileInfo {

	public static void main(String[] args) {

		File file = new File("C:\\Java Exam", "Java Exam.txt");
//		File file = new File("C:\\Java Exam");
//		File file = new File("C:\\"); // ->.listFiles() : nullpointer발생 (자바가 C드라이브에 접근할수없게 막아놓음) 

		//파일이 존재하면 true, 아니면 false
		boolean isFileExists = file.exists();
		System.out.println("isFileExists >" + isFileExists); 
		
		//읽어온 File 인스턴스가 파일이라면 true, 폴더라면 false
		boolean isFile = file.isFile();
		System.out.println("isFile >" + isFile); 

		//읽어온 File 인스턴스가 폴더(디렉토리)라면 true, 파일이라면 false
		boolean isDirectory = file.isDirectory();
		System.out.println("isDirectory >" + isDirectory);

		//File인스턴스가 가리키고있는 폴더 또는 파일의 '전체경로'
		String fileAbsolutePath = file.getAbsolutePath();
		System.out.println("fileAbsolutePath >" + fileAbsolutePath);

		//File 인스턴스가 가리키고 있는 것이 폴더라면 폴더이름, 
		// 파일이라면 확장자 포함한 타입의 이름
		String fileName = file.getName();
		System.out.println("fileName >" + fileName);

		// file 인스턴스가 가리키고 있는 파일의 크기(byte로 가져옴)
		// 1byte = 1, 
		// 1kb = 1024(windows기준 1024, windows 아닐경우 1000) 
		// 1 mb = 1024*1024, 
		// 1gb = 1024*1024*1024
		// 1tb = 1024*1024*1024*1024
		// 1pb = 1024*1024*10241024*1024
		long length = file.length();
		System.out.println("length >" + length);

		//파일이 마지막으로 수정된 날짜와 시간
		// 컴퓨터의 시간기준 : 1970년 1월 1일 00:00:00 이때부터 흘러간 초 를 보여줌
		// (KST 코리안타임)-> 1970년 1월 1일 09:00:00  
		// 이 초 * 1000해서 돌려줌 -> 숫자가 나옴
		long lastModifiedTime = file.lastModified(); //long은 날짜와 시간 반환시킴
		System.out.println("lastModifiedTime >" + lastModifiedTime);
		// long 타입의 날짜와 시간을 -> 문자로 된 날짜와 시간으로 변환
		Date date = new Date(lastModifiedTime);
		System.out.println("lastModifiedTime(Date) >" + date);
		
		/*getParent 2가지
		getParent() : 부모파일의 경로가 '문자열'로 나옴
		getParentFile(); -> 부모폴더의 다른 파일들이 '파일인스턴스'로 나옴
		*/
		//현재파일이 존재하는 '부모(상위)폴더의 경로'가 '문자열' 로 나옴
		String parentPath = file.getParent();	
		System.out.println("parentPath >" + parentPath);

		//현재파일이 존재하는 부모(상위)폴더의 새로운 File 인스턴스
		File parentFile = file.getParentFile();
		System.out.println("parentFile >" + parentFile);
		System.out.println("parentFileAbsolutePath >" + parentFile.getAbsolutePath());

		
		// File 인스턴스가 폴더일때, 폴더내부에 존재하는 모든 폴더와 파일목록 반환
		File[] listFileArray = file.listFiles(); //listFiles() : 배열로 반환해줌
		// 폴더가 아닌 파일안에 다른 폴더나 파일이 없으면, 
		// listFileArray는 null값임 -> NullPointerException 발생
		for(File item : listFileArray) {
			System.out.println("listFileArray >" + item.getAbsolutePath());
		}		
	}
}

 

UTF - 8 

- 영어, 숫자 빼면 전부 3바이트

- 전세계의 언어를 인코딩 할 수 있음

ex) FileReader(file, Charset.forName("UTF-8")); - 파일을 바이트단위로 읽어온다

-> 발전 : bufferedReader = new BufferedReader(reader); - 파일을 줄(라인)단위로 읽어온다

UTF - 16

-중국 한자들 전부 표현 가능

 

 

** flush() 메소드 : 내부 버퍼에 잔류된 바이트 모두 출력


2. File Output

파일을 쓸 때엔 확인 해야 할 항목들이 많다 
< C:\java\outputs 라는 폴더에 java_output.txt 라는 파일을 쓰려 할 때 >
1. C:\java\outputs 라는 파일이 존재하는지 확인
2. 없다면 폴더를 생성
3. java_output.txt 파일이 존재하는지 확인
4. 이미 있다면 새로 생성할 파일의 이름을 java_output (2).txt 로 생성
5. 이 마저도 있다면 java_output (3).txt로 생성.
6. 파일이 없을 때 까지 순번을 증가시키며 찾는다
7. 존재하지 않는 파일 순번을 찾았다면 파일 내용을 씀

 

Output- write (출력) 예제
/**
 * Java를 이용해 폴더를 만들고 파일을 생성/쓰기 하는 코드
 */
public class WriteExam {

	/**
	 * 파일을 쓴다.
	 * @param parent 파일을 쓸 경로
	 * @param fileName 쓸 파일의 이름
	 * @param append 이어서 쓸 것인지 여부
	 */
	public static void writeFile(String parent, String fileName, boolean append) {

		
		File file = new File(parent, fileName);
		if( ! file.getParentFile().exists()) { //file.getParentFile() = C:\\java\\outputs 
			file.getParentFile().mkdirs(); // mkdirs : make directories
			// mkdir => java만 만들어주고, mkdirs => java, outputs 둘다 만들어줌(이걸사용)
		}	
		
		
		// 이어서 쓰게되면 원본파일이 originalFileDescription에 들어감
		/*
		 * 기존의 파일 내용 써주는 용도
		 */
		List<String> originalFileDescription = new ArrayList<>();
		if( ! append ) {//이어서 쓰는게 아니라면 : 새로운 파일 만들어줌
		//기존의 파일 내용을 보호하기 위해 파일의 이름을 다르게 해줌(덮어쓰기 방지용)
		// -> 코드 실행 할 때 마다java.output(1), java.output(2), java.output(3).. 이런식으로 생성됨
		
		// 그렇다면, 파일을 이어서 쓸 수는 없나? -> 파일을 이어서 쓸수있는 메소드는 없음. 
		// -> java 1.8 미만 : 기존의 파일내용 다 읽어와서 새롭게 파일을 쓰는 방법을 사용할수밖에없다.
		// -> java1.8 되어서야 도입됨 (= 이어쓰기 가능하게됨)
			int index = 2; //이어서 쓰지 않을것이라면.. 영역
			while( file.exists()) {
				file = new File("C:\\java\\outputs", // C:\\java\\outputs = file.getParent()
						"java_output (" + (index++) + ").txt"); // index++ = 2, 해당 반복문 실행 후 그 다음 3이 됨
			}
		}
		else {
			//이어서 쓸 것이라면..영역
			//기존의 파일내용 읽어와서 List<String>으로 반환받고
			originalFileDescription.addAll(ReadAndPrintExam.getAllLines(file));
			//반환받은 내용은 originalFileDesvription에 addAll한다
		}
		
		FileWriter fw = null; //byte 단위로 쓰는것
		BufferedWriter bw = null;// 한줄씩 쓰는것
		
		try { //new 하면서 2개의 파이프가 열림 -> 이후 try에서 나중에 열린(new)거부터 close 해줘야됨
			fw = new FileWriter(file, Charset.forName("UTF-8"));
			bw = new BufferedWriter(fw);
			
			//이어서 쓸것이라면 아래코드 실행
			if(append) {
				for(String originalFileLine : originalFileDescription) {
					bw.write(originalFileLine);
				}
			}
			
			bw.write("파일을 씁니다1. \n");
			bw.write("파일을 씁니다2. \n");
			bw.write("파일을 씁니다3. \n");
			bw.flush();  //bw(=bufferedwriter) : 일단 쓰고, flush 해줄때 한번에 파일에 값이 들어감
		}
		catch(IOException ioe) {
			System.out.println(ioe.getMessage());
		}
		
		finally {
			if (bw != null) {
				try {
					bw.close();
				}
				catch(IOException ioe) {}
			}
			if (fw != null) {
				try {
					fw.close();
				}
				catch(IOException ioe) {}
			}
		}
		System.out.println(file.getAbsolutePath());
	
		
	}
	
	public static void main(String[] args) {
		//처음실행되면 : 파일을 씁니다123. 이 나옴
		writeFile("C:\\java\\outputs", "java_output.txt", false); //false = 이어붙이지말아라
		//두번째 실행되면 : 파일을 씁니다123. 이 2번 나옴
		writeFile("C:\\java\\outputs", "java_output.txt", true); //true = 이어붙여라
		
		// 덮어쓰지 말라는것이므로 ~~~(2) 파일이 생김
		writeFile("C:\\java\\outputs", "java_output.txt", false); 

	}
	
}