본문 바로가기

STUDY/국비과정

[JAVA 웹 개발 공부] 국비지원 37일차 - File 클래스, 입출력스트림

File 객체

 

File 클래스는 파일을 조작하고 검사하는 코드를 쉽게 작성하게 해주는 클래스이다. File 객체는 파일이 아닌 파일 이름을 나타내는 객체이다. FileWriter와 같은 클래스의 생성자에 이 File 객체를 넘겨서 실제로 파일을 생성할 수 있다.

만약 File 객체가 나타내는 파일이 존재한다면 프로그램은 파일의 속성을 조사하고 파일에 대한 여러 가지 동작을 수행할 수 있다. 예를 들면 파일의 이름을 변경한다거나 삭제하거나 권한을 변경할 수 있다. 

 

*File 객체 생성

File file = new File("D:\\myfile.txt");

 

*File 클래스 메소드

반환형 메소드 설명
String getName() 파일의 이름을 반환
String getPath() 경로를 반환
String getAbsolutePath() 절대 경로를 반환
String getCanonicalPath() 정규 경로를 반환
boolean exists() 파일의 존재 여부
boolean isFile() 파일이면 참(true)
boolean isDirectory() 디렉터리이면 참(true)
boolean delete() 파일을 삭제
boolean mkdir() 디렉터리를 생성

 

ex) File 클래스 메소드 사용

File file = new File("D:\\myfile.txt");
System.out.println("파일명: " + file.getName()); // 파일명: myfile.txt
System.out.println("경로: " + file.getPath()); // 경로: D:\myfile.txt
System.out.println("파일인가요? " + file.isFile()); // 파일인가요? true

 

파일경로

 

*절대경로 : getAbsolutePath() 

*상대경로 : getCanonicalPath()

 

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

public class Main2 {
	public static void main(String[] args) {
		File file = new File("..\\.."); //.은 현재경로 //..은 현재경로의 상위경로
		System.out.println(file.getName());
		System.out.println(file.getPath());
		System.out.println(file.isFile());
		System.out.println(file.isDirectory());
		System.out.println(file.exists());
		
		// 절대적인 경로(모든경로가 표시)
		System.out.println(file.getAbsolutePath());
		
		// 상대적인 경로는 현재 작업하는 곳 기준에서의 경로(..)
		// 메소드에서 예외를 발생시킴
		// IOException은 부모가 Exception클래스로 반드시 try-catch 해줘야함
		try {
			System.out.println(file.getCanonicalPath()); 
		} catch (IOException e) {
			System.out.println("입출력 예외가 발생했습니다.");
		}
	}
}
..
..\..
false
true
true
D:\eunjin\workspace\221220\..\..
D:\eunjin

 

 

파일생성

 

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

public class Main4 {
	public static void main(String[] args) {
		File my = new File("d:\\myfolder\\new.txt");
		
		try {
			boolean result = my.createNewFile();
			if (result) {
				System.out.println("파일생성 : 성공");
			} else {
				System.out.println("파일이 이미 존재할 때 false");
			}
		} catch (IOException e) {
			System.out.println("입출력 예외가 발생하여 파일 생성에 실패했습니다.");
		}
	}
}
파일생성 : 성공

 

 

파일삭제

 

import java.io.File;

public class Main5 {
	public static void main(String[] args) {
		File my = new File("d:\\myfolder\\new.txt");
		
		boolean result = my.delete();
		System.out.println(result ? "삭제완료" : "삭제실패");
	}
}
삭제완료

 

 

폴더생성

 

import java.io.File;

public class Main6 {
	public static void main(String[] args) {
		File my = new File("d:\\myfolder\\newfolder");
		boolean result = my.mkdir();
		
		System.out.println(result? "폴더 생성 완료" : "폴더 생성 실패");
	}
}
폴더 생성 완료

 

 

폴더, 파일 생성 연습

 

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

public class Main7 {
	public static void main(String[] args) {
		// d드라이브
		// 하위폴더 myfolder에
		// memos 이름의 폴더를 생성하고
		// 해당경로에 todaymemo.txt 파일 생성하기
		
		File folder = new File("d:\\myfolder\\memos");
		if (!folder.exists()) {
			folder.mkdir();
		} 
		
		File file = new File("d:\\myfolder\\memos\\todaymemo.txt");
		try {
			if (file.createNewFile()) {
				System.out.println("파일 생성 완료");
			} else {
				System.out.println("파일이 이미 존재합니다.");
			}
		} catch (IOException e) {
			System.out.println("예외 발생");
		}
	}
}
파일이 이미 존재합니다.

 

 

입출력(I/O)

 

I/O란 Input과 Output의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 한다. 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고받는 것을 말한다.

 

 

스트림(stream)

 

자바에서 입출력을 수행하려면, 즉 어느 한쪽에서 다른 쪽으로 데이터를 전달하려면, 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림이라고 정의했다.

스트림이란 데이터를 운반하는데 사용되는 연결통로이다.

스트림은 단방향통신만 가능하기 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다.

그래서 입력과 출력을 동시에 수행하려면 입력을 위한 입력스트림(input stream)과 출력을 위한 출력스트림(output stream) 모두 2개의 스트림이 필요하다.

스트림은 먼저 보낸 데이터를 먼저 받게 되어 있으며 중간에 건너뜀 없이 연속적으로 데이터를 주고받는다.

 

 

바이트기반 스트림 -  InputStream, OutputStream

 

스트림은 바이트단위로 데이터를 전송하며 입출력 대상에 따라 다음과 같은 입출력스트림이 있다.

 

*입력스트림과 출력스트림의 종류

입력스트림 출력스트림 입출력 대상의 종류
FileInputStream FileOutputStream 파일
ByteArrayInputStream ByteArrayOutputStream 메모리(byte배열)
PipedInputStream PipedOutputStream 프로세스(프로세스간의 통신)
AudioIntputStream AudioOutputStream 오디오장치

 

*InputStream과 OutputStream에 정의된 읽기와 쓰기를 수행하는 메소드

InputStream OutputStream
abstract int read() abstract void write(int b)
int read(byte[] b) void write(byte[] b)
int read(byte[] b, int off, int len) void write(byte[] b, int off, int len)

 

*InputStream의 메소드

메소드명 설명
int available() 스트림으로부터 읽어 올 수 있는 데이터의 크기를 반환한다.
void close() 스트림을 닫음으로써 사용하고 있던 자원을 반환한다.
void mark(int readlimit) 현재위치를 표시해 놓는다. 후에 reset()에 의해서 표시해 놓은 위치로 다시 돌아갈 수 있다. readlimit은 되돌아갈 수 있는 byte의 수이다.
boolean markSupported() mark()와 reset()을 지원하는지를 알려 준다. mark()와 reset() 기능을 지원하는 것은 선택적이므로, mark()와 reset()을 사용하기 전에 markSupported()를 호출해서 지원여부를 확인해야한다.
abstract int read() 1 byte를 읽어 온다(0~255사이의 값). 더 이상 읽어 올 데이터가 없으면 -1을 반환한다.
abstract 메소드라서 InputStream의 자손들은 자신의 상황에 알맞게 구현해야한다.
int read(byte[] b) 배열 b의 크기만큼 읽어서 배열을 채우고 읽어 온 데이터의 수를 반환한다. 반환하는 값은 항상 배열의 크기보다 작거나 같다.
int read(byte[] b, int off, int len) 최대 len개의 byte를 읽어서, 배열 b의 지정된 위치(off)부터 저장한다. 실제로 읽어 올 수 있는 데이터가 len개보다 적을 수 있다.
void reset() 스트림에서의 위치를 마지막으로 mark()이 호출되었던 위치로 되돌린다.
long skip(long n) 스트림에서 주어진 길이(n)만큼 건너뛴다.

 

*OutputStream의 메소드

메소드명 설명
void close() 입력소스를 닫음으로써 사용하고 있던 자원을 반환한다.
void flush() 스트림의 버퍼에 있는 모든 내용을 출력소스에 쓴다.
abstract void write(int b) 주어진 값을 출력소스에 쓴다.
void write(byte[] b) 주어진 배열 b에 저장된 모든 내용을 출력소스에 쓴다.
void write(byte[] b, int off, int len) 주어진 배열 b에 저장된 내용 중에서 off번째부터 len개 만큼만을 읽어서 출력소스에 쓴다.

flush()는 버퍼가 있는 출력스트림의 경우에만 의미가 있으며, OutputStream에 정의된 flush()는 아무런 일도 하지 않는다.

스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아 주어야 한다. 그러나 ByteArrayInputStream과 같이 메모리를 사용하는 스트림과 System.in, System.out과 같은 표준 입출력 스트림은 닫아 주지 않아도 된다.

 

 

보조 스트림

 

보조스트림은 실제 데이터를 주고받는 스트림이 아니기 때문에 데이터를 입출력할 수 있는 기능은 없지만, 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있다. 그래서 보조스트림만으로는 입출력을 처리할 수 없고, 스트림을 먼저 생성한 다음에 이를 이용해서 보조스트림을 생성해야한다.

 

*보조스트림의 종류

입력 출력 설명
FilterInputStream FilterOutputStream 필터를 이용한 입출력 처리
BufferedInputStream BufferedOutputStream 버퍼를 이용한 입출력 성능향상
DataInputStream DataOutputStream int, float와 같은 기본형 단위로 데이터를 처리하는 기능
SequenceInputStream 없음 두 개의 스트림을 하나로 연결
LineNumberInputStream 없음 읽어 온 데이터의 라인 번호를 카운트
(JDK1.1부터 LineNumberReader로 대체)
ObjectInputStream ObjectOutputStream 데이터를 객체단위로 읽고 쓰는데 사용.
주로 파일을 이용하며 객체 직렬화와 관련있음
없음 PrintStream 버퍼를 이용하며, 추가적인 print 관련 기능
(print, printf, println 메소드)
PushbackInputStream 없음 버퍼를 이용해서 읽어 온 데이터를 다시 되돌리는 기능
(unread, push back to buffer)

 

 

문자기반 스트림 - Reader, Writer

 

바이트기반이라 함은 입출력의 단위가 1 byte라는 뜻이다. Java에서는 한 문자를 의미하는 char형이 2 byte이기 때문에 바이트기반의 스트림으로 2 byte인 문자를 처리하는데는 어려움이 있다.

이 점을 보완하기 위해서 문자기반의 스트림이 제공된다. 문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림을 사용하는 것이 좋다.

 

*바이트기반 스트림과 문자기반 스트림의 비교

바이트기반 스트림 문자기반 스트림
FileInputStream
FileOutputStream
FileReader
FileWriter
ByteArrayInputStream
ByteArrayOutputStream
CharArrayReader
CharArrayWriter
PipedInputStream
PipedOutputStream
PipedReader
PipedWriter
StringBufferInputStream (deprecated)
StringBufferOutputStream (deprecated)
StringReader
StringWriter
InputStream Reader
abstract int read()
int read(byte[] b)
int read(byte[] b, int off, int len)
int read()
int read(char[] cbuf)
abstract int read(char[] cbuf, int off, int len)
OutputStream Writer
abstract void write(int b)
void write(byte[] b)
void write(byte[] b, int off, int len)
void write(int c)
void write(char[] cbuf)
abstract void write(char[] cbuf, int off, int len)
void write(String str)
void write(String str, int off, int len)
바이트기반 보조스트림 문자기반 보조스트림
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
FilterInputStream
FilterOutputStream
FilterReader
FilterWriter
LineNumberInputStream (deprecated) LineNumberReader
PrintStream PrintWriter
PushbackInputStream PushbackReader

 

 

파일읽기위한 준비과정(예외처리)

 

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

public class Main8 {
	public static void main(String[] args) {
		File file = new File("d:\\myfolder\\memos\\todaymemo.txt");
		
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(file);
			// 파일 읽을거임
			int b = fis.read();
			System.out.println((char) b); // a
			b = fis.read();
			System.out.println((char) b); // p
			b = fis.read();
			System.out.println((char) b); // p
			b = fis.read();
			System.out.println((char) b); // l
			b = fis.read();
			System.out.println((char) b); // e
		
		} catch (FileNotFoundException e) { // 예외처리 (자식클래스가 먼저와야함)
			System.out.println("파일이 존재하지 않습니다.");
		} catch (IOException e) {
			System.out.println("입출력 예외 발생");
		} finally {
			// 인풋스트림을 닫아야함
			if (fis != null) { // null이 아닐떄만 인풋스트림 닫기
				try {
					fis.close();
				} catch (IOException e) {
					System.out.println("인풋스트림을 닫는 동안 입출력예외 발생");
				}
			}
		}
	}
}

 

 

인풋스트림

 

 

*FileInputStream() → byte 단위로 읽어주는 바이트스트림

*FileReader() → 캐릭터 단위로 읽어주는 캐릭터스트림

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

public class Main9 {
	public static void main(String[] args) {
		File file = new File("d:\\myfolder\\memos\\anotherfile.txt");
		
		FileReader fr = null;
		try {
			fr = new FileReader(file); // byte 단위로 읽어주는 바이트스트림
			int b;
			while ((b = fr.read()) != -1) {
				System.out.println((char) b);
			}
		} catch (FileNotFoundException e) {
			System.out.println("파일을 찾지 못했습니다.");
		} catch (IOException e) {
			System.out.println("입출력 예외 발생");
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
					System.out.println("입출력 예외 발생");
				}
			}
		}
	}
}

 

 

아웃풋스트림

 

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

public class Main10 {
	public static void main(String[] args) {
		File file = new File("D:\\myfolder\\memos\\output.txt");

		FileOutputStream fos = null; // 원래있던 내용은 무시하고 새로 작성
		try {
			fos = new FileOutputStream(file);
			
			String line = "write practice.";
			byte[] bytes = line.getBytes();
			
			fos.write(bytes);
			
		} catch (IOException e) {
			System.out.println("입출력 예외 발생");
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					System.out.println("입출력 예외 발생");
				}
			}
		}
	}
}

 

 

아웃풋스트림 활용

 

*정수 더하기

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

public class Main {
	public static void main(String[] args) {
		File file = new File("D:\\myfolder\\sum.txt");
		
		FileReader fr = null;
		try {
			fr = new FileReader(file);
			int c;
			while ((c = fr.read()) != -1) {
				System.out.print((char) c);
			}
			System.out.println();
		} catch (FileNotFoundException e) {
			System.out.println("더하기 수행 기록이 없습니다.");
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		
		Scanner scan = new Scanner(System.in);
		System.out.println("첫번째 정수? ");
		int left = scan.nextInt();
		
		System.out.println("두번째 정수? ");
		int right = scan.nextInt();
		
		int sum = left + right;
		System.out.println("결과: " + sum);
		
		FileWriter fw = null;
		
		try {
			fw = new FileWriter(file);
			String line = left + " + " + right + " = " + sum;
			fw.write(line);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

 

*방명록 남기기

 

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.time.LocalDate;
import java.util.Scanner;

// 프로그램 실행 시 마지막 방문자의 방명록 기록을 볼 수 있음(문자열)
// 새 기록을 남기는 동작이 가능

public class Main2 {

	// 파일 읽기
	public static String readFile(File file) {
		FileReader fr = null;
		StringBuilder result = new StringBuilder();

		try {
			fr = new FileReader(file);
			int c;
			while ((c = fr.read()) != -1) {
				result.append((char) c);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return result.toString();
	}

	// 파일 쓰기
	public static void writeFile(File file, String line) {
		FileWriter fw = null;

		try {
			fw = new FileWriter(file);
			fw.write(line);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	// 효율을 높이기위해 buffered가 있는 Reader를 사용 -> 대용량의 많은 양을 다룰때 효율의 차이
	public static String readFileWithBuffer(File file) {
		BufferedReader br = null;
		StringBuilder sb = new StringBuilder();
		try {
			br = new BufferedReader(new FileReader(file));
			String line;
			while ((line = br.readLine()) != null) {
				sb.append(line);
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return sb.toString();
	}

	// 효율을 높이기위해 buffered가 있는 Writer를 사용
	public static void writeFileWithBuffer(File file, String line) {
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter(file));
			bw.write(line);
			bw.flush(); // buffer를 가득채우지 못해도 결과물 잘보이게 하는것
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void main(String[] args) {
		File file = new File("D:\\myfolder\\recent.txt");

		String lastHistory = readFile(file);
		System.out.println(lastHistory);

		Scanner scan = new Scanner(System.in);
		System.out.println("방명록 남겨주세요.");
		System.out.print("이름: ");
		String name = scan.nextLine();
		System.out.print("메시지: ");
		String message = scan.nextLine();

		String guestMessage = name + "(" + LocalDate.now() + ")" + message;

//		writeFile(file, guestMessage);
		writeFileWithBuffer(file, guestMessage);

	}
}

 

 

파일복사하기

 

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main4 {
	public static void main(String[] args) {
		// 파일 복사하기
		File origin = new File("D:\\myfolder\\ee.pdf");
		File copy = new File("D:\\myfolder\\ee - copy2.pdf");
		
		BufferedInputStream fis = null;
		BufferedOutputStream fos = null;
		try {
			fis = new BufferedInputStream(new FileInputStream(origin));
			fos = new BufferedOutputStream(new FileOutputStream(copy));
			
			int b;
			while ((b = fis.read()) != -1) {
				fos.write(b);
				
			}
			byte[] buf = new byte[1024];
			int length = 0;
			while ((length = fis.read(buf)) != -1) {
				fos.write(buf, 0, length);
			}
			
			System.out.println("파일 복사 완료");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

 

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Scanner;

public class Main5 {
	public static void main(String[] args) {
		// 여러 사람의 이름을 콘솔 입력받을 수 있는 프로그램
		// 0을 입력하면 모든 사람의 이름을 콘솔 출력 후 종료
		Scanner scan = new Scanner(System.in);
		List<String> names = new ArrayList<>();
		
		while (true) {
			String input = scan.nextLine();
			if (input.equals("0")) {
				break;
			}
			names.add(input);
		}
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter("d:\\myfolder\\names.txt"));
			
			Iterator<String> iter = names.iterator();
			while (iter.hasNext()) {
				String elem = iter.next();
				
				bw.write(elem);
				bw.write(" ");
			}
			
			
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
				
	}
}