Set 인터페이스
•
순서를 유지하지 않는 데이터 집합
•
데이터 중복을 허용하지 않음
•
구현 클래스: HashSet, TreeSet
HashSet
: 내부적으로 HashMap을 이용해 만들어진 Set으로, `해싱(Hashing)`을 이용해서 구현
•
Set 인터페이스를 구현한 `가장 대표적인 컬렉션`
•
Set 인터페이스의 특징대로 `중복 허용 X`
•
저장순서를 유지하지 않음 → 순서를 유지하려면 `LinkedHashSet`
메서드 | 설명 |
boolean add(Object o) | 새로운 객체 삽입 |
boolean addAll(Collection c) | 주어진 컬렉션의 모든 객체 삽입 |
void clear() | 저장된 모든 객체 삭제 |
boolean contains(Object o) | 지정된 객체를 포함하고 있는지 리턴 |
boolean contains(Collection c) | 지정된 컬렉션의 모든 객체를 포함하고 있는지 리턴 |
boolean isEmpty() | HashSet이 비어있는지 리턴 |
boolean remove(Object o) | 지정된 객체 삭제 |
boolean removeAll(Collection c) | 지정된 컬렉션의 모든 객체 삭제 |
boolean retainAll(Collection c) | 지정된 컬렉션의 모든 객체를 제외한 나머지 삭제 |
int size() | HashSet에 저장된 객체의 수 리턴 |
파일 입출력
/*오늘 진도인 파일 읽기만 작성되었습니다*/
파일 입출력의 필요성
코딩을 하다 보면 파일의 데이터를 읽어오는 경우가 있고 ,
읽어온 데이터가 많이 쌓이면 DB에 저장하여 관리합니다.
이 흐름을 따라갈 수 있도록 개발자는 파일의 내용을 읽고 쓰고 출력하는 것에 익숙해져야 합니다.
Stream (시냇물)
•
스트림은 읽어나 쓸 수 있는 데이터의 흐름을 의미합니다.
•
모든 입출력 구조는 Stream으로 이루어져 있습니다.
•
간단히 말하자면 데이터를 운반하는데 사용되는 연결 통로라고도 할 수 있습니다.
•
스트림은 단방향이기 때문에 입력 스트림, 출력 스트림으로 나뉘어 사용됩니다.
•
스트림이 처리하는 data type에 따라 Byte 기반 스트림, Character 기반 스트림으로 나뉩니다.
텍스트 파일 읽기
수업 로그(10.06)에 올라온 예제를 통해 설명드리겠습니다.
BufferedReader
•
BufferedReader/BufferedWriter은 buffer을 사용하기 때문에 FileReader보다 효율적입니다.
Buffer이란? 데이터를 한 곳 에서 다른 곳으로 보낼 때 데이터가 임시로 저장되는 공간.
•
아래 예시를 보면 버퍼size가 16KB(KB = 1024) 인 BufferedReader객체를 만든다는 의미입니다.
•
위 그림처럼 한 바이트씩 읽어올 수도 있지만,
아래처럼 readLine()메소드를 통해 텍스트 파일 하나씩 읽을 수 있습니다.
•
readLine() 메소드
// 텍스트 파일을 한 줄씩 읽어서 return합니다.
String str;
while ((str = reader.readLine()) != null) { // 더이상 내용이 없으면 null
System.out.println(str);
}
Java
복사
FileReader
•
FileReader은 Character 파일을 읽을 수 있는 기능을 제공합니다.
•
이 클래스는 java.io.InputStreamReader 클래스를 상속받기 때문에, 조상클래스의 멤버 메소드인 read()를 사용하여 char 한 글자씩 읽어올 수 있습니다.
•
밑의 그림은 문자 하나를 읽어오는 로직입니다.
•
read() 메소드
public int read() throws IOException
Java
복사
텍스트 파일에서 한 글자씩 글자를 읽어서, 하나의 char을 return합니다.
더이상 읽을 글자가 없으면, -1을 return합니다.
•
read()사용하여 여러 문자를 출력하는 예시
public class ReadFile {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("D:\\file.txt");
int ch;
while ((ch = reader.read()) != -1) { //
System.out.print((char) ch);
}
}
}
Java
복사
예외처리
•
자바는 입력과 출력할 할 때 발생할 수 있는 예외에 대해서 까다롭게 규정하고 있습니다.
•
Java IOException은 I/O(입력/출력 예외)이며 입력 또는 출력 작업이 실패하거나 해석될 때마다 발생합니다.
◦
예를 들어 존재하지 않는 파일을 읽으려는 경우 Java는 I/O 예외를 발생시킵니다.
•
BufferedReader(BufferedWriter) 클래스의 메소드들은 입출력에러가 발생할 경우 자체적으로 IOException을 던지도록 정의되어있기 때문에, 메소드들을 사용할 때 반드시 예외처리를 해주어야 합니다.
•
테스트를 하고자 할 때 메소드 선언부 옆에 throws IOException을 사용하면 error없이 작성 가능합니다.
File 읽기 코드
•
자바에서 파일을 읽기 위해 다양한 방법을 활용할 수 있다.
•
코드를 통해 이러한 방법을 정리하고, 파일을 단계별로 읽어본다.
◦
파일에서 한 글자 읽어오기
◦
파일에서 두 글자 읽어오기
◦
파일에서 N 글자 읽어오기
◦
파일에서 한 줄 읽어오기
◦
파일에서 N 줄 읽어오기
•
파일을 읽을 때 예외사항이 발생하기 쉽다. 예외를 처리하는 방법도 생각해보자.
File path 설정
•
파일을 읽기 위해서는 두 가지 조건이 충족되어야 한다.
1.
읽을 수 있는 파일이 존재해야한다.
2.
해당 파일에 접근하기 위해 경로를 알아야 한다.
파일 생성
•
실습을 위해 파일을 생성하자. 인텔리제이의 자바프로젝트 최상위 폴더에 “afile.txt”을 만들었다.
•
텍스트 파일 안에는 다음과 같은 내용을 입력하였다.
파일 경로
•
파일의 경로는 해당 파일을 우클릭한 후 Copy Path/Reference를 클릭하면 알 수 있다.
파일 존재 여부 확인
•
파일의 경로를 알고 있다고 해도, 실제로 그 파일이 존재하는지 확인할 필요가 있다.
•
File 클래스를 활용하여 어떤 경로의 파일이 존재하는지 여부를 확인할 수 있다.
1.
파일 한 개 존재 여부 확인
import java.io.File;
public class FileExistCheck {
public static void main(String[] args) {
// File 클래스 활용
File file = new File("C:\\Users\\chanmin\\git\\BackEndSchool2\\afile.txt");
//File file = new File("afile.txt");
if (file.exists()){
System.out.println("파일이 존재합니다.");
} else{
System.out.println("파일이 존재하지 않습니다.");
}
}
}
Java
복사
File 클래스 exists()
•
File 클래스의 생성자는 파일의 경로를 String으로 입력받는다.
•
File 클래스의 exists() 메소드는 생성자에서 받은 파일 경로에 실제 그 파일이 존재하는지 여부를 boolean으로 반환한다.
•
인텔리제이에서 File file = new File("afile.txt"); 를 해도 파일이 존재한다는 출력문이 나오는데, 이는 인텔리제이의 Root Directory에 파일이 존재하기 때문이다.
2.
원하는 경로의 모든 파일 목록 확인
import java.io.File;
public class DirFileCheck {
public static void main(String[] args) {
File dir = new File("./");
File[] files = dir.listFiles();
// 현재 디렉토리의 파일 목록
for (File file : files) {
System.out.println(file);
}
}
Java
복사
File 클래스 listFiles()
•
File 클래스의 listFiles() 메소드 는 생성자에서 받은 파일 경로에 존재하는 모든 파일 목록을 File[] 에 담아 반환한다.
•
dir 인스턴스를 생성할 때 “/.” 를 전달하였는데, 이는 Root Directory의 경로이다.
•
for each 문으로 출력하면 현재 디렉토리의 모든 파일 목록을 출력할 수 있다.
파일 읽기
•
파일이 존재하고 파일의 경로를 알고 있다면, 해당 파일을 직접 읽을 수 있다.
•
만들어둔 afile.txt 텍스트 파일을 읽는 코드를 작성해보자.
•
텍스트 파일을 읽기 위해 사용할 수 있는 클래스는 크게 4가지이다.
1. FileReader
FileReader
•
FileReader는 String fileName을 전달하며 생성할 수 있다.
•
new FileReader(String fileName);
•
FileReader는 java.io.InputStreamReader 클래스를 상속받기 때문에, inputStreamReader 클래스의 read() 메소드를 사용하여, char를 한 글자씩 읽어올 수 있다.
•
read() 메소드는 텍스트 파일에서 한 글자씩 읽어서, int로 아스키코드를 반환한다. 이때 더 이상 글자가 없다면 -1을 반환한다.
파일에서 한 글자 읽기
import java.io.FileReader;
import java.io.IOException;
public class Read1Letter {
public static void main(String[] args) throws IOException {
FileReader reader = new FileReader("afile.txt");
char c = (char) reader.read();
System.out.println(c);
}
/* 출력결과
h
*/
}
Java
복사
•
FileReader에 "afile.txt"를 전달해 인스턴스를 생성했다.
•
read() 메소드를 활용해 "afile.txt"에서 한 글자를 읽었고 이를 char로 형변환해 char c에 초기화했다.
•
c를 출력하면 h가 나온다.
파일에서 두 글자 읽기
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
// Read2Letter 클래스
class Read2Letter{
private FileReader reader; //멤버변수 reader
public Read2Letter(String fileName) { //생성자
try { //인텔리제이의 도움을 받아 try-catch 예외처리
this.reader = new FileReader(fileName); // reader에 FileReader 인스턴스 초기화
} catch (FileNotFoundException e) { //입력된 파일경로에 파일이 존재하지 않는다면 예외
throw new RuntimeException(e);
}
}
public void print2Letter() {
for (int i = 0; i < 2; i++) { //2번동안 반복문 실행
try {
System.out.println((char)reader.read()); //파일에서 읽어온 글자를 출력
} catch (IOException e) { //입출력 과정에서 발생할 수 있는 다양한 에러들이 있을 때 예외처리
throw new RuntimeException(e);
}
}
}
}
// Main 클래스
public class Read2LetterMain {
public static void main(String[] args) throws IOException {
String fileName = "afile.txt";
Read2Letter read2Letter = new Read2Letter(fileName); //Read2Letter 객체 생성
read2Letter.print2Letter();// print2Letter 메소드 호출
}
/* 출력결과
h
e
*/
}
Java
복사
•
두 글자 읽는 코드는 객체지향을 지키며 작성하였다.
•
FileReader에 "afile.txt"를 전달할 수 있도록 Read2Letter 생성자를 작성하였다. 이때 적절한 예외처리를 할 수 있도록 했다.
•
Read2Letter에 접근할 수 있는 참조변수 read2Letter를 통해 print2Letter()를 호출하였다.
•
print2Letter() 메소드는 FileReader 객체를 통해 파일에서 두 글자를 읽어오고 출력한다.
파일에서 N글자 읽기
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
//ReadNLetter 클래스
class ReadNLetter{
private FileReader reader; //멤버변수 reader
public ReadNLetter(String filename) { //생성자
try { // 파일이 없는 경우를 대비한 예외처리
this.reader = new FileReader(filename); //객체 생성 시 filename 전달
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
}
}
public void printNLetter(int n){ //메소드 호출 시 int n을 받음
for (int i = 0; i < n; i++) { //n번만큼 반복문 순회
try {
int strNum = reader.read();
if (strNum != -1){ // -1이 아닌경우, 출력
System.out.println((char) strNum);
} else{
System.out.println("모두 출력되었습니다.");
break;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
// Main 클래스
public class ReadNLetterMain {
public static void main(String[] args) {
String fileName = "afile.txt";
ReadNLetter readNLetter = new ReadNLetter(fileName);
readNLetter.printNLetter(15);
}
/*
h
e
l
l
o
e
v
e
r
y
o
n
e
*/
}
Java
복사
•
N 글자 읽는 코드는 객체지향을 지키며 작성하였다.
•
FileReader에 "afile.txt"를 전달할 수 있도록 ReadNLetter 생성자를 작성하였다. 이때 적절한 예외처리를 할 수 있도록 했다.
•
ReadNLetter에 접근할 수 있는 참조변수 readNLetter를 통해 printNLetter(int num)를 호출하였다.
•
printNLetter(int num) 메소드는 FileReader 객체를 통해 파일에서 정수 num만큼 읽어오고 출력한다. 이때 int strNum = reader.read() 의 값이 -1인 경우 모든 글자가 출력된 것이므로, if - else 구문을 통해 strNum == -1인 경우 반복문이 끝날 수 있도록 했다.