- 파일 입력 스트림 (FileInputStream) : 지정된 파일 이름으로부터 바이트 단위의 입력 스트림을 생성한다.
- 문자 입력 스트림 변환기 (InputStreamReader) : FileInputStream 을 통해 읽은 바이트 데이터를 문자 데이터로 변환한다. 여기서는 UTF-8 인코딩을 사용한다.
- 버퍼링된 문자 입력 스트림 (BufferedReader) : InputStreamReader 로부터 데이터를 효율적으로 읽기 위해 버퍼링을 추가한다. readLine() 메서드를 사용하여 파일의 각 줄을 편리하게 읽을 수 있다.
시나리오 코드1
Seoul.txt, NewYork.txt 파일 생성하고 내용을 넣어주세요.
기반 스트림 FileReader → 단 인코딩에 대한 단점이 존재한다.
package io.file.ch05;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.Scanner;
public class CityInfoApp1 {
public static void main(String[] args) {
System.out.println("도시 이름을 입력하세요. (예 : Seoul, NewYork)");
// try catch resource
try (Scanner scanner = new Scanner(System.in)) {
String city = scanner.nextLine();
String fileName = city + ".txt";
// 1. 파일에 있는 데이터를 응용프로그램으로 가져와야한다. (문자 기반)
// FileReader (문자 기반 스트림이다), 단 주의할 사항
// 파일을 읽을 때 시스템의 기본 문자 인코딩을 사용, 운영 체제, 지역에 따라 다름
try (FileReader fr = new FileReader(fileName);
BufferedReader br = new BufferedReader(fr)) {
System.out.println(city + " 에 대한 정보입니다.");
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.out.println("해당 파일을 찾을 수 없습니다.");
}
} catch (Exception e) {
e.printStackTrace();
}
}// end of main
}// end of class
인코딩 설정을 위한 해결 방안 1-2
package io.file.ch05;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Scanner;
public class CityInfoApp2 {
public static void main(String[] args) {
System.out.println("도시 이름을 입력하세요. (예 : Seoul, NewYork)");
// try catch resource
try (Scanner scanner = new Scanner(System.in)) {
String city = scanner.nextLine();
String fileName = city + ".txt";
// 1. FileReader 단점 보안 코드
try (FileInputStream fis = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
BufferedReader br = new BufferedReader(isr)){
System.out.println(city + "에 대한 정보 : ");
String line;
while( (line = br.readLine()) != null ) {
System.out.println(line);
}
} catch (Exception e) {
System.out.println("해당 파일을 찾을 수 없습니다.");
}
} catch (Exception e) {
e.printStackTrace();
}
}// end of main
}// end of class
String 클래스의 split 메서드 활용 (사전 기반 지식)
Java의 split 메서드는 String 클래스의 메서드로, 문자열을 특정 패턴 또는 정규 표현식을 기준으로 분리하여 문자열 배열 (String[])로 반환한다.
public String[] split(String regex)
public String[] split(String regex, int limit)
- regex : 분리할 기준이 되는 정규 표현식이다.
- limit : 결과 배열의 크기를 제한할 수 있는 옵션이다. 이 값을 설정하면 반환되는 배열의 최대 요소 수를 제한할 수 있다.
String[] words = line.split("\\s+"); // 공백을 기준으로 분리
String[] words = line.split("[,.\\s]+"); // 쉼표, 마침표, 공백을 구분자로 사용
String[] words = line.split("[^가-힣A-Za-z]+"); // 한글과 영문을 제외한 모든 문자를 구분자로 사용
// "[^가-힣A-Za-z]+"
^ (캐럿)
- 용도 : 입력 문자열의 시작을 나타내는 앵커이다. 이 메타 문자는 패턴이 문자열의 시작 부분과 일치해야 함을 지정할 때 사용된다.
- 예시 : ^abc : "abc"로 시작하는 문자열에만 일치한다. 예를 들어 "abcdef" 는 매치되지만, "defabc"는 매치되지 않는다.
+ (플러스)
- 용도 : 바로 앞에 있는 요소가 하나 이상 존재할 경우에 일치한다. 즉, 앞의 표현이 최소 한 번이상 반복되어야 할 때 사용한다.
- 예시 : a+: 'a'가 하나 이상 있는 모든 시퀀스에 일치해야 한다. 'a', 'aa', 'aaa' 등이 이에 해당한다.
💡 ^[a-z]+: 이 정규 표현식은 소문자 알파벳으로 시작하고, 하나 이상의 소문자가 연속해서 나타나는 문자열에 매치된다.
단, 대괄호 안에서 캐럿을 사용하면 "부정 문자 클래스"를 의미한다.
[ ... ] 대괄호의 주요 의미와 사용
1. 문자 집합 :
- 대괄호 안에 나열된 문자들 중 하나와 매치된다.
- 예 : [abc]는 a, b 또는 c 중 하나와 매치된다.
2. 문자 범위 :
- 대괄호 안에 하이픈 (-) 을 사용하여 범위를 지정할 수 있다.
- 예 : [ a-z ]는 소문자 알파벳 a 에서 z 까지의 모든 문자와 매치된다.
- 예 : [ A-Z ]는 대문자 알파벳 A 에서 Z 까지의 모든 문자와 매치된다.
- 예 : [ 0-9 ]는 숫자 0 에서 9 까지의 모든 문자와 매치된다.
3. 부정 (not) :
- 대괄호 안의 첫 번째 문자로 ^를 사용하여 부정을 나타낼 수 있다. 이는 대괄호 안에 나열된 문자들을 제외한 모든 문자와 매치됨을 의미한다.
- 예 : [^abc] 는 a, b, c를 제외한 모든 문자와 매치된다.
[^가-힣A-Za-z]+ 의 의미 :
- 가-힣 : 한글 문자 범위 (가에서 힣까지 모든 한글 문자)
- A-Za-z : 모든 영문 대소문자
- [^가-힣A-Za-z] : 한글 문자와 영문 대소문자를 제외한 모든 문자
- + : 한 번 이상 반복
💡 문자열 " 안녕하세요! Hello123 " 에서 [^가-힣A-Za-z]+ 패턴을 적용하면, " ! " 와 " 123 " 이 매치된다.
도전문제 - 가장 많이 사용된 단어 찾기 (공백 기준)
파일에는 임의의 긴 문장이 저장되어 있으며 파일 스트림을 활용해서 데이터를 읽고 코드 상에서 프로그램을 만들어보자.
package io.file.ch05;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;
public class WordFinder {
public static void main(String[] args) {
String fileName = "Seoul.txt";
try (FileInputStream fis = new FileInputStream(fileName);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader br = new BufferedReader(isr);) {
// 단어 빈도를 저장하기 위한 HashMap 생성
Map<String, Integer> wordCountMap = new HashMap<>();
String line;
while ((line = br.readLine()) != null) {
String[] words = line.split("\\s+");
// 분리된 단어들을 반복 처리
for (String word : words) {
// System.out.println("word : " + word);
// 빈 문자열이 아닐 경우에만 처리
if (!word.isEmpty()) {
// getOrDefault - 분리한 word 단어가 이미 맵 구조에 존재한다면
// 현재 값을 가져오고 없다면 0을 반환한다.
// wordCountMap key - String
// wordCountMap value - Integer
wordCountMap.put(word, wordCountMap.getOrDefault(word, 0) + 1);
}
}
} // end of while
String mostCommon = null;
int maxCount = 0;
for (Map.Entry<String, Integer> entry : wordCountMap.entrySet()) {
if (entry.getValue() > maxCount) {
mostCommon = entry.getKey();
maxCount = entry.getValue();
}
}
System.out.println("가장 많이 사용된 단어 : " + mostCommon + " , " + maxCount + "회");
} catch (Exception e) {
e.printStackTrace();
}
}// end of main
}// end of class
728x90
'Java' 카테고리의 다른 글
파일복사 ( 문자기반 입/출력 ), ZIP 파일로 압축 (0) | 2024.05.21 |
---|---|
파일 출력 스트림 ( 문자 기반 스트림 ) (0) | 2024.05.20 |
문자 기반 스트림 (0) | 2024.05.17 |
파일 Copy ( 바이트기반 입/출력 ) (0) | 2024.05.16 |
파일 출력 스트림 ( 바이트 기반 ) (0) | 2024.05.16 |