시나리오 코드 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 (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
}
도시 이름을 입력하세요. (예 : Seoul, NewYork)
Seoul <-- 입력했음
Seoul에 대한 정보 입니다.
'서울'은 본래 한국어의 순우리말로서 '한 나라의 수도(首都)',
곧 '국도(國都)'를 가리키는 일반명사이다. 영어로 표기하면 'Capital City' 정도가 된다.
따라서 고유명사로서의 쓰임과 별개로 '미국의 서울은 워싱턴 D.C.이다',
'영국의 서울은 런던이다', '조선의 서울은 한양이다'로도 쓸 수 있는 것이다.
[36] 다만 1946년 지명이 '경성부'에서 '서울시', 다시 '서울특별자유시'로 바뀐지도 벌써 반세기가 넘었고
고유명사 '서울(특별시)'의 용례가 대두되어 일반명사인 '서울'은 일상 회화에서는 점차 쇠퇴하고 있다.
일상적으로 '서울'이라고 하면 지명인 '서울특별시'를 가리키는 경우가 대부분이기 때문이다.
사실상 고유명사가 된 일반명사의 사례이다.
남한의 기초자치단체, 광역자치단체, 일반구,
행정시 등 시군구 이상 행정구역 중에서 유일한 고유어(순우리말) 지명이기도 하다.
인코딩 설정을 위한 해결 방안 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 (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
}
- 파일 입력 스트림 (FileInputStream): 지정된 파일 이름으로부터 바이트 단위의 입력 스트림을 생성합니다.
- 문자 입력 스트림 변환기 (InputStreamReader): FileInputStream을 통해 읽은 바이트 데이터를 문자 데이터로 변환합니다. 여기서는 UTF-8 인코딩을 사용합니다.
- 버퍼링된 문자 입력 스트림 (BufferedReader): InputStreamReader 로부터 데이터를 효율적으로 읽기 위해 버퍼링을 추가합니다. readLine() 메서드를 사용하여 파일의 각 줄을 편리하게 읽을 수 있습니다.
도전 학습 - 가장 많이 사용된 단어 찾기(공백 기준)
파일에는 임의의 긴 문장이 저장되어 있으며 파일 스트림을 활용해서 데이터를 읽고 코드상에서 프로그램을 만들어 보자.
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]+: 이 정규 표현식은 소문자 알파벳으로 시작하고, 하나 이상의 소문자가 연속해서 나타나는 문자열에 매치됩니다. 단, 대괄호 안에서 캐럿을 사용하면 "부정 문자 클래스"를 의미합니다. |
[ … ] 대괄호의 주요 의미와 사용
- 문자 집합:
- 대괄호 안에 나열된 문자들 중 하나와 매치됩니다.
- 예: **[abc]**는 a, b, 또는 c 중 하나와 매치됩니다.
- 문자 범위:
- 대괄호 안에 하이픈(-)**``**을 사용하여 범위를 지정할 수 있습니다.
- 예: **[a-z]**는 소문자 알파벳 **a**에서 **z**까지의 모든 문자와 매치됩니다.
- 예: **[A-Z]**는 대문자 알파벳 **A**에서 **Z**까지의 모든 문자와 매치됩니다.
- 예: **[0-9]**는 숫자 **0**에서 **9**까지의 모든 문자와 매치됩니다.
- 부정 (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 = "article.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 단어가 이미 map 구조에 존재한다면
// 현재 값을 가져오고 없다면 0을 반환한다.
// wordCountMap key - String
// wordCountMap key - Integer
wordCountMap.put(word, wordCountMap.getOrDefault(words, 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
}
결과
가장 많이 사용된 단어 : ID.5 , 1회
'Java > JAVA 3 - 유용한 클래스' 카테고리의 다른 글
파일복사(문자기반 입/출력), ZIP파일로 압축 - 16 (0) | 2024.05.21 |
---|---|
파일 출력 스트림(문자 기반 스트림) - 15 (0) | 2024.05.21 |
문자 기반 스트림 - 13 (0) | 2024.05.21 |
파일 Copy (바이트기반 입/출력) - 12 (0) | 2024.05.21 |
파일 출력 스트림(바이트 기반) - 11 (0) | 2024.05.21 |