고래씌

[JAVA] 13-1. 입출력(IO) (File 클래스 ①) 본문

JAVA/JAVA 기초

[JAVA] 13-1. 입출력(IO) (File 클래스 ①)

고래씌 2023. 10. 20. 17:02

1. File 클래스

java.io.File 클래스를 가지고 파일 만드는 과정 실습
 
file 클래스는 꼭 IOException 입출력 예외처리를 해줘야한다.
 

1) 별도의 저장경로를 지정하지 않고 생성하고자하는 파일의 이름만 제시해서 생성해보기

package com.kh.chap01_file.run;

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

public class FileRun {

	public static void main(String[] args) {
		
		// java.io.File 클래스를 가지고 파일 만드는 과정 실습
		

		try {
			// 1. 별도의 저장경로를 지정하지 않고 생성하고자하는 파일의 이름만 제시해서 생성해보기
			File file1 = new File("test.txt");
			file1.createNewFile();
			
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
test.txt 파일 생성됨

 

2) 경로지정을 한 파일명을 제시해서 생성하기 --> 존재하는 경로를 제시해줘야한다.

package com.kh.chap01_file.run;

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

public class FileRun {

	public static void main(String[] args) {
		
		// java.io.File 클래스를 가지고 파일 만드는 과정 실습
		

		try {
			
			// 2. 경로지정을 한 파일명을 제시해서 생성하기 --> 존재하는 경로를 제시해줘야한다.
			File file2 = new File("C:\\dev\\test.txt");
			file2.createNewFile();
//			file2.mkdir();

		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
C드라이브 안 text.txt 파일 생성

 

3) 폴더를 생성하고나서 그 안에 파일을 생성하는 방법

package com.kh.chap01_file.run;

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

public class FileRun {

	public static void main(String[] args) {
		
		// java.io.File 클래스를 가지고 파일 만드는 과정 실습
		

		try {
			
			// 3. 폴더를 생성하고나서 그 안에 파일을 생성하는 방법
			String dir = "C:\\b\\c\\d\\e";    //파일을 저장할 경로 지정
			File bFolder = new File(dir);
//			if(bFolder.isDirectory()) // bFolder가 디렉토리(폴더)인지 확인
//				bFolder.mkdir(); // makeDirectory  => 1개 폴더만 만들어지는 함수
				bFolder.mkdirs(); // => 여러개의 디렉토리를 만들어줄때 사용
			
			File file3 = new File(dir + "\\test.txt");    // 폴더를 생성하고 나서 파일 생성
			file3.createNewFile();

		} catch (IOException e) {
			e.printStackTrace();
		}


	}

}

 

4) 별도의 경로 지정 없이 폴더 생성

- .isFile()  => file 이냐 아니냐 ? true / false 반환
- .isDirectory()  =>  Directory 이냐? true / false 반환
- .getName()  => 파일 이름.확장자 출력
- .getParent() =>  상위폴더 반환
- .length()  =>  파일 용량 반환
- .getAbsolutePath()   => 파일의 절대경로를 가져옴
 

package com.kh.chap01_file.run;

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

public class FileRun {

	public static void main(String[] args) {
		
		// java.io.File 클래스를 가지고 파일 만드는 과정 실습
		

		try {	
			
			// 4. 별도의 경로 지정 없이 폴더 생성
			File folder = new File("test");   // 경로 지정을 안하면 현재 java 프로젝트 기본경로에 저장됨
			folder.mkdir();
			
			File file = new File("test\\person.txt");
			file.createNewFile();
			
			// File에서 제공하는 메소드들
			System.out.println(folder.isFile());  // file이냐?  // false
			System.out.println(file.isDirectory()); // Directory 냐?
			
			System.out.println("파일명 : " + file.getName()); // 이름만 나오게 하는 것
			System.out.println("상위폴더 : " + file.getParent());   // 상위폴더 반환 // test
			System.out.println("파일 용량 : " +file.length());
			System.out.println("절대경로 : " + file.getAbsolutePath());  // 파일의 절대경로 가져옴
			
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}

 
 
▶ 프로그램 상의 데이터를 외부매체(모니터, 스피커, 자바프로그램, 파일 등등)로 출력하거나 입력장치(키보드, 마우스)로 입력받는 과정을 진행하고자 한다면 반드시 외부매체와의 연결통로를 만들어야한다.
(통로 == 스트림)
 

▶ 스트림의 특징
- 단방향 : 입력이면 입력, 출력이면 출력 즉, 입력용 출력용 스트림이 별도로 존재함.
                동시에 입출력하고자 한다면 하나의 스트림으로는 불가능함
           
- 선입선출(FIFO) : 먼저 전달한 값이 먼저 나오게 됨
- 시간지연문제가 발생할 수 있다.
 

▶ 스트림의 구분
- 통로의 사이즈 : 
         ① 바이트 스트림 : 1byte짜리가 이동할 수 있을정도의 사이즈(좁은 통로)   => 문자 하나 사용할 때
         ② 문자 스트림 : 2byte짜리가 이동할 수 있을정도의 사이즈(넓은 통로)     => 여러줄의 문자 String 사용할때
            

- 외부매체와의 직접적인 연결여부 :
         ① 기반스트림 : 외부매체와 직접적으로 연결되는 통로(스트림)이다
         ② 보조스트림 : 기반스트림만으로 부족한 성능을 향상시켜주는 용도의 스트림.
                                 직접적으로 외부매체와 연결할 수 없음. 즉, 단독사용이 불가능
                                 기반스트림을 보조해주는 역할을 한다.
                              =>  보조기능 : 속도향상, 자료형 변환, 객체단위 입출력 등
     
 ☞ 보조스트림 사용시 단독적으로는 사용이 불가능하므로, 따라서 반드시 기반스트림과 함께 사용해야 한다.
 

 


2. DAO(Data Access Object) 

: 데이터가 보관되어 있는 공간과 직접 접근해서 데이터를 입,출력할 수 있는 클래스
 
 
현재 프로그램 → 외부매체(파일)
출력 : 프로그램 내의 데이터를 파일로 내보내기(즉, 파일에 저장)
 
FileOutputStream : "파일"로 데이터를 1byte단위로 출력하는 스트림
 
 
 
 

3. 파일 출력

1) FileOutputStream 객체 생성  => 매개변수로 지정한 파일과 직접적으로 연결되는 통로 만듦

- 해당 파일이 존재하지 않으면 해당 파일이 생성되면서 통로가 연결됨 
- 이미 존재하는 파일이라면 즉시 통로가 연결됨
 
▶ FileOutputStream 객체 생성
- 두번째 매개변수로 true 추가시 → 기존에 해당파일이 있을 경우 "이어쓰기" 가능
- 두번째 매개변수로 미작성시     → 기존에 해당파일이 있더라도 "덮어씌우기"
 
변수명 = new FileOutputStream("파일.확장자");    => 객체 생성 후 덮어씌우기
변수명 = new FileOutputStream("파일.확장자", true);    => 이어쓰기
 

package com.kh.chap02_byte.model.dao;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileByteDao {
	
	public void fileSave() {
		
		
		FileOutputStream fos = null;   // try 바깥쪽에 변수 생성. 
		

		try {
			// 1. FileOutputStream 객체 생성 
			
			fos = new FileOutputStream("a_byte.txt"); // 객체 생성 후 덮어씌우기
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

 
 
 

2) 연결통로로 데이터를 내보내기(출력) : write()메소드 이용

1byte의 범위 : -128 ~ 127 까지의 범위(파일에 기록이 될때 해당 숫자의 고유한 문자가 기록됨)
 
▶ 변수명.write(97);  => char로 자동형변환이 돼서   'a' 출력됨
▶ byte[] arr = {99, 100, 101};    
    변수명.write(arr);   =>  c d e 출력
▶ 변수명.write(arr, 1, 2)     => 1번 인덱스에서부터 2개만 기록해라. 100, 101   => d  e 출력

package com.kh.chap02_byte.model.dao;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;


public class FileByteDao {
	

	public void fileSave() {
		
		
		FileOutputStream fos = null;   // try 바깥쪽에 변수 생성. 
		

		try {
			// 1. FileOutputStream 객체 생성 
		
			fos = new FileOutputStream("a_byte.txt");   // 객체 생성 후 덮어씌우기

			
			// 2. 연결통로로 데이터를 내보내기(출력) : write()메소드 이용
			// 1byte의 범위 : -128 ~ 127 까지의 범위(파일에 기록이 될때 해당 숫자의 고유한 문자가 기록됨)
			fos.write(97);  // char으로 자동형변환이 됨 // a 출력됨
			fos.write('b');
//			fos.write('고'); // 글자가 깨져서 출력됨
			
			byte[] arr = {99, 100, 101};  // c d e 출력
			fos.write(arr);
			
			fos.write(arr, 1, 2);   // 1번 인덱스에서부터 2개만 기록해라. 100, 101 // d e
	
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} 
		
	}

}
a_byte.txt 출력 내용

 

3) 스트림을 사용했으면 반드시 자원 반납하기(반드시!)

▶ 스트림을 사용했으면 반드시 자원 반납을 해주어야한다!  =>  변수명.close() 
▶ 자원을 반납할 때 try 내부에 작성을 하면안된다. 앞에 코드가 에러가 나면 빠져나오지 못할 수 있기 때문에 변수명.close() 실행될 수 있도록 finally에 추가하여야 함!!
 
finally   : 어떤 예외가 발생하든간에 반드시 실행하는 구문
▶ finally를 추가할 때 안에 try ~ catch 문도 다시 사용을 해주어야 함.
▶ finally : exception 발생 여부와 관계없이 꼭 처리해야 하는 로직 기술.
중간에 return문을 만나도 finally구문은 실행되지만 System.exit();를 만나면 무조건 프로그램 종료.
주로 java.io나 java.sql 패키지의 메소드 처리 시 이용
 
 
~
} finally {
     try {
          변수명.close();
    }catch(IOException e) {
           e.printStackTrace();
    }
}
   

package com.kh.chap02_byte.model.dao;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.FileInputStream;

public class FileByteDao {
	
	public void fileSave() {
		
		
		FileOutputStream fos = null;   // try 바깥쪽에 변수 생성. 
		

		try {
			// 1. FileOutputStream 객체 생성  => 매개변수로 지정한 파일과 직접적으로 연결되는 통로 만듦
		
			fos = new FileOutputStream("a_byte.txt", true); // 이어쓰기
			
			
			// 2. 연결통로로 데이터를 내보내기(출력) : write()메소드 이용
			
			fos.write(97);  
			fos.write('b');

			
			byte[] arr = {99, 100, 101};
			fos.write(arr);
			
			fos.write(arr, 1, 2);  
			
			
			// 3. 스트림을 사용했으면 반드시 자원 반납하기(반드시!)
			// fos.close();  위코드에서 에러 발생하는 경우 실행이 안될 수 있으므로 finally에 추가
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {

			e.printStackTrace();
		} finally { // 어떤 예외가 발생하든간에 반드시 실행하는 구문
			// try 내부에 작성하면 X . 
			// 앞에 코드가 에러가 났든 안났던 반드시 실행될 수 있도록 finally에 추가하여야한다.
			try {
				fos.close();
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		
	}

}
a_byte.txt 파일에 이어쓰기

 

4. 파일의 내용 읽어들이기

외부매체(파일)  ----> 프로그램
입력 : 파일로부터 데이터를 읽어들이겠다
 
FileInputStream : 파일로부터 데이터를 1바이트씩 입력받는 스트림
 

1) FileInputStream 객체로 입력 스트림 생성

	public void fileRead() {
		
		
		// FileInputStream : 파일로부터 데이터를 1바이트씩 입력받는 스트림
		FileInputStream fis = null;
		
		try {
			
			// 1. FileInputStream 객체로 입력 스트림 생성
			fis = new FileInputStream("a_byte.txt");  // 존재하는 파일의 경로 제시

	}

 

2) 통로로 데이터를 입력받기

- System.out.println((char)fis.read());  // 1byte단위로 하나씩 데이터를 읽어들이는 함수
☞ 형변환까지 해주어야 아스키코드 값으로 출력이 안되고 문자로 출력됨
 
- 파일에서 더이상 읽어올 데이터가 없는 경우 -1을 반환
 

	public void fileRead() {
		
		
		// FileInputStream : 파일로부터 데이터를 1바이트씩 입력받는 스트림
		FileInputStream fis = null;
		
		try {
			
			// 1. FileInputStream 객체로 입력 스트림 생성
			fis = new FileInputStream("a_byte.txt");  // 존재하는 파일의 경로 제시
			
			
			// 2. 통로로 데이터를 입력받기
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read()); 
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println((char)fis.read());  
			System.out.println(fis.read());   // 파일에서 더이상 읽어올 데이터가 없는 경우 -1을 반환

	}

 

3) 반복문을 활용하여 파일내부의 모든 데이터 읽어들이기

- 방법 ①
while(true) {
      int value = 0;
     value = fis.read();
if(value == -1) break;
     System.out.print((char)value);
}

	public void fileRead() {
		
		
		// FileInputStream : 파일로부터 데이터를 1바이트씩 입력받는 스트림
		FileInputStream fis = null;
		
		try {
			
			// 1. FileInputStream 객체로 입력 스트림 생성
			fis = new FileInputStream("a_byte.txt");  // 존재하는 파일의 경로 제시
			
			
			// 반복문을 활용하여 파일내부의 모든 데이터 읽어들이기
			
			// 방법 ①
			while(true) {
				int value = 0;
				value = fis.read();
				if(value == -1) break;
				System.out.print((char)value);
			}
					
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
        
			// 3. 다쓴 자원 반납
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
	}

 
 
- 방법 ②
int value = 0;               X
while(fis.read()) != -1) { 
       System.out.print((char)value);
}
 
☞ 이 방법은 while(fis.read())에서 문자를 하나 불려들이고 그다음 문자가 System.out.print((char)value); 에서 실행이 되기 때문에 해당 파일의 내용이 모두 출력되지 않는다!
 
 
 
int value = 0;              O
while((value = fis.read()) != -1) {   
     System.out.print((char)value);
}
 
변수에 저장을 안하면 fis.read()가 호출되면서 그다음 문자가 출력되기 때문에 이 방법을 해주어야 모든 문자가 출력됨

	public void fileRead() {
		
		
		// FileInputStream : 파일로부터 데이터를 1바이트씩 입력받는 스트림
		FileInputStream fis = null;
		
		try {
			
			// 1. FileInputStream 객체로 입력 스트림 생성
			fis = new FileInputStream("a_byte.txt");  // 존재하는 파일의 경로 제시
			
			
			// 반복문을 활용하여 파일내부의 모든 데이터 읽어들이기
			
			// 방법 ②
			int value = 0;
			while((value = fis.read()) != -1) {   // 변수에 저장을 안하면 fis.read()가 호출되면서 그다음 문자가 출력되기 때문에
				System.out.print((char)value);
			}
			
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			// 3. 다쓴 자원 반납
			try {
				fis.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
	}