JAVA_12_입출력(IO)

송지윤·2024년 2월 22일

Java

목록 보기
20/22

입출력(IO)

Input(입력 : 외부에서 내부로 값이 들어오는 것)과 Output(출력 : 내부에서 외부로 값이 나가는 것)의 약자, 컴퓨터 내부 또는 외부 장치와 프로그램 간의 데이터를 주고 받는 것
장치와 입출력을 위해서는 하드웨어 장치에 직접 접근이 필요한데 다양한 매체에 존재하는 데이터들을 사용하기 위해 입출력 데이터를 처리할 공통적인 방법으로 스트림(시냇물) 이용 (일방통행)
Scanner 로 input
print 구문 이용 console 출력 output

File 클래스

파일 시스템의 파일을 표현하는 클래스
파일 크기, 파일 속성, 파일 이름 등의 정보와 파일 생성 및 삭제 기능 제공

java.io 패키지

파일/디렉토리(폴더)를 관리하는 클래스
(파일/디렉토리 존재 유무 관계 없음)

파일 생성, 제거, 이름, 크기, 마지막 수정일, 존재여부 등의 기능 제공

File 객체 생성

File file = new File("파일 경로");
File file = new File("C:/dev/test.txt");
	 * + 폴더가 존재하지 않으면 폴더 생성
	 */
	public void method1() {
		
		// 제일 앞 "/" : 최상위 폴더 (== root, 절대 경로의 기준점 C드라이브)
		
		// C:/io_test/20240222 폴더를 지정
		File directory = new File("/io_test/20240222");
		// -> 처음 : 존재하지 않는 폴더를 관리하는 File 객체 생성
		
		System.out.println("존재 여부 확인 : " + directory.exists());
//		존재 여부 확인 : false
		
		if(!directory.exists()) { // 폴더가 존재하지 않으면
			
			// 폴더 모두 생성 (폴더 2개 생성해야해서 s 붙은 거 씀)
			directory.mkdirs();
			
			// 폴더 이름
			System.out.println(directory.getName());
//			20240222
			// 전체 경로 반환
			System.out.println(directory.getPath());
//			\io_test\20240222
		}
		
	}

File 객체를 이용해서 지정된 위치에 파일 생성하기

	public void method2() {
		// 백슬래쉬 한개는 이스케이프 문자
		// \\ 문자열에서 "\" 표기하는 방법 : "\\"
		// 확장자까지 써줘야함
		File file = new File("\\io_test\\20240222\\파일생성.txt");
		
		try {
			
			if(!file.exists()) { // 파일이 존재하지 않으면
				
				if(file.createNewFile()) { // 파일 생성이 성공한 경우
					// createNewFile 이 boolean 값 반환
					System.out.println(file.getName() + " 파일이 생성 되었습니다.");
//					파일생성.txt 파일이 생성 되었습니다.
				}
				
			}
			
			
		} catch (IOException e) {
			e.printStackTrace(); // 예외 정보 + 예외가 발생한 위치까지의 메서드 추적
		}
	}

File 클래스 제공 메서드 활용하기

	public void method3() {
		
		// File 객체 생성
		File directory = new File("\\workspace\\02_Java\\12_io");
		
		// 지정된 디렉토리에 있는 모든 파일/디렉토리를 File[] 형태로 얻어오기
		File[] files = directory.listFiles();
		
		// 향상된 for 문 -> for( 요소 저장 변수  :   배열|컬렉션) {}
		for(File f : files) {
			
			// String File.toString() : 지정된 파일/디렉토리의 절대경로
//			System.out.println( f.toString() );
//			\workspace\02_Java\12_io\.classpath
//			\workspace\02_Java\12_io\.gitignore
//			\workspace\02_Java\12_io\.project
//			\workspace\02_Java\12_io\.settings
//			\workspace\02_Java\12_io\bin
//			\workspace\02_Java\12_io\src
			
			// 파일명
			String fileName = f.getName();
			
			// 마지막으로 수정한 날짜
			long lastModified = f.lastModified();
//			System.out.println(lastModified);
//			1708571652475
//			1708571652611
//			1708571652461
//			1708571652469
//			1708571684955
//			1708571684828
			
			// java.text.SimpleDateFormat : 간단히 날짜 형식을 지정할 수 있는 객체
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd a h:mm");
								// 2024-02-22 오후 2:14
			
			// String SimpleDateFormat.format(long) : 
			// 매개변수 long 값을 지정된 패턴 형식으로 변화하여
			// 문자열 형태로 반환
			String date = sdf.format(lastModified);
		
//			System.out.println(date);
//			2024-02-22 오후 12:14
//			2024-02-22 오후 12:14
//			2024-02-22 오후 12:14
//			2024-02-22 오후 12:14
//			2024-02-22 오후 12:14
//			2024-02-22 오후 12:14
			
			// 파일 유형 (파일이냐 폴더냐)
			String type= null;
			if(f.isFile()) type = "파일";
			else		   type = "폴더"; // isDirectory
			
			// 파일 크기(byte)
			String size = f.length() + "B";
			
			if(f.isDirectory()) { // 폴더라면 파일 크기 안 나옴
				size = "";
			}
			
			String result
				= String.format("%-20s %-20s %-5s %10s",
						fileName, date, type, size);
			
			System.out.println(result);
			
//			.classpath           2024-02-22 오후 12:14  파일          396B
//			.gitignore           2024-02-22 오후 12:14  파일            6B
//			.project             2024-02-22 오후 12:14  파일          381B
//			.settings            2024-02-22 오후 12:14  폴더              
//			bin                  2024-02-22 오후 12:14  폴더              
//			src                  2024-02-22 오후 12:14  폴더   
			
		}
		
	}

파일/디렉토리 생성 및 삭제 메소드

File 클래스 메서드

boolean  mkdir()          : 디렉토리 생성
boolean  mkdirs()         : 경로상의 모든 디렉토리 생성
boolean  createNewFile()  : 파일 생성
boolean  delete()         : 파일/디렉토리 삭제
String   getName()        : 파일 이름 반환
String   parent()         : 파일이 저장된 디렉토리 반환
String   getPath()        : 전체 경로 반환
boolean  isFile()         : 현재 File 객체가 관리하는게 파일이면 true
boolean  isDirectory()    : 현재 File 객체가 관리하는게 디렉토리 true
boolean  exists()         : 파일/디렉토리가 존재하면 true, 아님 false
long     length()         : 파일 크기 반환
long     lastModified()   : 파일 마지막 수정일 (1970.01.01 09:00 부터 현재까지 지난 시간을 ms 단위로 반환)
String[] list()          : 디렉토리 내 파일 목록을 String[] 배열로 반환
File[]   listFiles()     : 디렉토리 내 파일 목록을 File[] 배열로 반환

개발자 상식

OS : 운영 체제

(Windows)     /    (Linux, Mac)
  폴더       /      디렉토리
  
- 경로 표기 방법(하위 폴더, 파일 표시)   

백슬래시(\, Windows)    -> C:\workspace\02_Java
슬래시  (/, Linux, Mac) -> Users:/workspace/02_Java

- Java 언어의 특징 : 플랫폼(OS)에 독립적
-> OS 관계 없이 똑같은 코드 작성이 가능

-> 이 특징을 유지하기 위해 /, \ 둘 다 호환 가능
   (런타임 시 실행되는 OS에 맞게 자동으로 변경)

---------------------------------------------------

- 경로 표기 방법

1) 절대 경로 : 하나의 (절대적인) 기준으로 부터
			목표까지의 경로를 모두 표기하는 방법
C:\workspace\02_Java

- 기준
[Windows] : C:/ , D:/
[Linux, Mac] : /Users , /

2) 상대 경로 : 현재 위치를 기준으로 목표까지의 경로를 표기하는 방법
<script src = "../js/01_js">

파일/디렉토리 정보 리턴 메소드

스트림(Stream) 클래스

입출력 장치에서 데이터를 읽고 쓰기 위해서 자바에서 제공하는 클래스
모든 스트림은 단방향이며 각각의 장치마다 연결할 수 있는 스트림 존재
하나의 스트림으로 입출력을 동시에 수행할 수 없으므로 동시에 수행하려면 2개의 스트림 필요

스트림(Stream) : 데이터가 이동하는 통로
기본적으로 한 방향으로 흐름

Byte 기반 스트림

1byte 단위로 데이터를 입/출력하는 스트림

최상위 인터페이스 : InputStream, OutputStream

문자열, 이미지, 영상, 오디오, pdf 등
모든 것을 입/출력 할 수 있음
(단, 통로가 좁다보니 속도가 조금 느림)

IO 관련된 코드는 IOException이 발생될 가능성이 높다

-> 거의 모든 메서드가 throws IOException
-> IOException 예외 처리 구문을 작성하는 것이 필수

분류

스트림 클래스 종류

바이트 기반 파일 출력

	public void fileByteOutput() {
		
		// FileOutputStream 참조 변수 선언
		FileOutputStream fos = null;
		
		try {
			// new FileOutputStream("경로") :
			// -> 경로에 작성된 파일과 연결된 파일 출력 스트림 객체 생성
			// -> 출력 스트림에 연결된 파일이 존재하지 않으면 자동 생성
			// (단, 폴더는 생성되지 않음)
			// -> 기존 파일이 존재하면 내용을 덮어쓰기함
			
			// new FileOutputStream("경로", true)
			// -> 기존 파일이 존재하면 내용을 이어쓰기함
			
			fos = new FileOutputStream("/io_test/20240222/바이트기반_테스트.txt");
			
			// String 불변성 문제를 해결한 객체(가변성)
			StringBuilder sb = new StringBuilder();
			sb.append("Hello World!!\n");
			sb.append("1234567890\n");
			sb.append("~!@#$%^&*()_+\n");
			sb.append("가나다라마바사아\n");
			sb.append("와 자바 너무 재밌다\n");
			sb.append("선생님 저 공부 열심히 할게요");
			sb.append("진짜로");
			sb.append("정말로");
			sb.append("화이팅");
			
			// StringBuilder -> String 변환
			String content = sb.toString();
			
			// 출력 방법 1 : 한 글자(2byte) 씩 파일로 출력
			// -> 2byte 범주의 문자(영어, 숫자, 기본 특수문자 제외)는
			//    1byte 기반 스트림 통과 시
			//    데이터 손실이 발생해서 글자가 깨지는 문제가 발생
			
//			for(int i = 0 ; i < content.length() ; i++) {
//				char ch = content.charAt(i); // i 번째 글자 반환
//				fos.write(ch); // 1byte 출력 스트림이 연결된 파일에 ch 쓰기
//			}
			
			// System.nanoTime() : 1970.01.01 09:00:00 부터
			// 현재 시간까지의 차이를 ns(nano second 단위)로 반환
			// 1ms(밀리)     == 1/1000초
			// 1us(마이크로) == 1/1000ms
			// 1ns(나노)     == 1/1000us (1/10억 초)
			
			long startTime = System.nanoTime();
			
			// 출력 방법 2 : String 을 byte[] 변환 후 출력
			fos.write(content.getBytes());
			
			long endTime = System.nanoTime();
			
			System.out.println("[수행 시간] : " + (endTime - startTime) + "ns");
			
//			[수행 시간] : 59600ns
			
			fos.flush(); // 스트림 안에 남아있는 모든 데이터를 모두 밀어냄
			
			System.out.println("출력 완료");
			
		} catch(IOException e) {
			e.printStackTrace(); // 예외가 발생한 메서드까지 추적해 출력
			
		} finally { // try 예외 발생 여부 관계 없이 무조건 수행
			
			// 사용 완료한 스트림을 제거(닫기, 메모리 반환)하는 코드 작성
			
			try {
				
				// 스트림이 정상 생성된 경우
				if(fos != null) fos.close();
				
			} catch(IOException e) {
				e.printStackTrace();
			}
			
		}
		
	}

버퍼를 이용한 파일 출력

BufferedOutputStream 보조 스트림 이용

버퍼(Buffer)란?
데이터를 모아두는 박스, 장바구니 같은 메모리 공간

버퍼링
인터넷 속도 낮음 + 스트리밍 코드가 효율이 안 좋음
-> 동영상 재생 중에 미리
앞에 재생될 부분을 다운 받아놔서
영상을 끊김없이 볼 수 있게 함
-> 다운 받아서 저장해놓는 공간 == 버퍼

BufferedOutputStream / BufferedInputStream

FileOutputStream 은 1바이트씩 데이터를 입출력
-> 버퍼에 입출력할 내용을 모아서 한 번에 입출력
--> 스트림을 이용하는 횟수가 적어짐
-> 성능, 시간 효율 up


	public void bufferedFileByteOutput() {
		
		FileOutputStream fos = null;
		
		BufferedOutputStream bos = null; // 보조 스트림 선언
		
		try {
			
			fos = new FileOutputStream("/io_test/20240222/바이트기반_테스트_Buffered.txt");

			// 기반 스트림 fos 를 이용해
			// 보조 스트림 bos 를 생성
			bos = new BufferedOutputStream(fos);
			
			StringBuilder sb = new StringBuilder();
			sb.append("Hello World!!\n");
			sb.append("1234567890\n");
			sb.append("~!@#$%^&*()_+\n");
			sb.append("가나다라마바사아\n");
			sb.append("와 자바 너무 재밌다\n");
			sb.append("선생님 저 공부 열심히 할게요");
			sb.append("진짜로");
			sb.append("정말로");
			sb.append("화이팅");
			
			String content = sb.toString();
			
			long startTime = System.nanoTime();
			
			bos.write(content.getBytes());
			
			long endTime = System.nanoTime();
			
			System.out.println("[수행 시간] : " + (endTime - startTime) + "ns");
			
//			[수행 시간] : 25300ns
			
			bos.flush(); // 스트림에 남아있는 데이터 밀어내기(쏟아내기)
			
			System.out.println("출력 완료");
			
		} catch(IOException e) {
			
			e.printStackTrace();
			
		} finally {

			try {

				if(bos != null) bos.close();
				// 보조스트림 close()시
				// 보조스트림 생성에 사용된 기반 스트림 같이 close() 됨
				
			} catch(IOException e) {
				
				e.printStackTrace();
			}
			
		}
		
	}

0개의 댓글