[JAVA] Scanner, BufferedReader, BufferedWriter, StringBuilder 의 차이점과 사용법, 주요 메서드 + 예시 코드

dejeong·2024년 6월 28일
0

JAVA

목록 보기
1/24
post-thumbnail

📍 Scanner

간편하게 사용자 입력을 받거나 파일에서 데이터를 읽는 데 사용된다. 다양한 데이터 타입 (int, double, String 등)을 쉽게 읽을 수 있으나, 내부적으로 많은 메서드 호출과 정규 표현식 처리를 하기 때문에, 성능(+속도) 면에서 BufferedReader에 비해 떨어진다. (느림)

🔸주요 메서드

- nextInt() : 정수를 읽음
- nextLine() : 한 줄 전체를 읽음
- next() : 다음 토큰을 읽음

🔸예시 코드 (기본 문법 참고!)

import java.util.Scanner;

public class ScannerExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("Enter a number: ");
        int number = scanner.nextInt();
        
        scanner.nextLine(); // 남아있는 개행 문자를 처리
        
        System.out.print("Enter your name: ");
        String name = scanner.nextLine();
        
        System.out.println("You entered number: " + number);
        System.out.println("You entered name: " + name);
        
        scanner.close();
    }
}

주로 사용자 입력을 받을 때 사용되며, 간단한 파일 읽기나 입력 데이터 검증에도 유용하다.

🔸예시 상황

  • 콘솔을 통해 사용자로부터 숫자나 문자열을 입력받는 경우
  • 파일로부터 숫자 리스트를 읽어와서 처리하는 경우

🔸예시 문제

  • 사용자로부터 나이를 입력받아 검증하고 출력하기
  • 텍스트 파일에서 숫자를 읽어와서 합계를 구하기

🔸예시 상황별 코드 응용

import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;

public class ScannerExample {
    public static void main(String[] args) {
        // 예시 1: 사용자로부터 나이를 입력받아 검증하고 출력하기
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter your age: ");
        if (scanner.hasNextInt()) {
            int age = scanner.nextInt();
            System.out.println("Your age is: " + age);
        } else {
            System.out.println("Invalid input. Please enter a number.");
        }
        scanner.close();

        // 예시 2: 텍스트 파일에서 숫자를 읽어와서 합계를 구하기
        try {
            Scanner fileScanner = new Scanner(new File("numbers.txt"));
            int sum = 0;
            while (fileScanner.hasNextInt()) {
                sum += fileScanner.nextInt();
            }
            System.out.println("The sum of numbers in the file is: " + sum);
            fileScanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

<장단점 및 주의사항>

  • 장점: 사용법이 간단하고 다양한 데이터 타입을 손쉽게 읽을 수 있다.
  • 단점: 파일을 읽을 때 성능이 떨어질 수 있으며, 기본적으로 동기화되지 않아서 멀티스레드 환경에서 주의가 필요하다.
  • 주의사항: nextLine() 메서드를 사용할 때, 앞서 nextInt(), nextDouble() 등과 함께 사용하면 개행 문자가 남아 입력 오류가 발생할 수 있으며, 이를 해결하기 위해 개행 문자를 처리해야 한다.

<개행 문자 처리 추가 코드>

import java.util.Scanner;

public class ScannerExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("Enter a number: ");
        int number = scanner.nextInt();
        
        scanner.nextLine(); // 남아있는 개행 문자를 처리
        
        System.out.print("Enter your name: ");
        String name = scanner.nextLine();
        
        System.out.println("You entered number: " + number);
        System.out.println("You entered name: " + name);
        
        scanner.close();
    }
}

📍 BufferedReader

큰 파일이나 네트워크 스트림에서 데이터를 읽을 때 사용된다. readLine() 메서드를 사용하여 한 줄씩 읽을 수 있으며, 버퍼를 사용하여 성능을 향상시킨다.

🔸주요 메서드

- readLine() : 한 줄을 읽음
- read() : 단일 문자를 읽음

🔸예시 코드 (기본 문법 참고!)

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

주로 큰 파일을 효율적으로 읽어야 할 때 사용되며, 줄 단위로 읽어들일 수 있기 때문에 로그 파일 처리나 텍스트 파일 분석에 적합하다.

🔸예시 상황

  • 로그 파일을 읽어와서 특정 패턴을 찾거나 분석하는 경우
  • 텍스트 파일의 내용을 줄 단위로 처리하는 경우

🔸예시 문제

  • 로그 파일에서 특정 키워드를 포함한 줄을 찾아 출력하기
  • 대용량 텍스트 파일을 읽어와서 단어 빈도를 계산하기

🔸예시 상황별 코드 응용

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        // 예시 1: 로그 파일에서 특정 키워드를 포함한 줄을 찾아 출력하기
        try (BufferedReader br = new BufferedReader(new FileReader("logfile.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                if (line.contains("ERROR")) {
                    System.out.println(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 예시 2: 대용량 텍스트 파일을 읽어와서 단어 빈도를 계산하기
        try (BufferedReader br = new BufferedReader(new FileReader("largefile.txt"))) {
            Map<String, Integer> wordCount = new HashMap<>();
            String line;
            while ((line = br.readLine()) != null) {
                String[] words = line.split("\\s+");
                for (String word : words) {
                    wordCount.put(word, wordCount.getOrDefault(word, 0) + 1);
                }
            }
            wordCount.forEach((word, count) -> System.out.println(word + ": " + count));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

<장단점 및 주의사항>

  • 장점: 대용량 파일을 효율적으로 읽을 수 있으며, 줄 단위로 읽기 때문에 텍스트 데이터 처리에 적합하다.
  • 단점: 초기 설정과 예외 처리가 필요. 성능을 위해 버퍼 크기를 적절하게 설정하는 것이 중요하다.
  • 주의사항: 파일을 열고 닫는 작업을 확실히 처리해야 함. 이를 위해 자바 7 이상에서는 try-with-resources 구문을 사용하여 리소스를 자동으로 닫을 수 있다.

<버퍼 크기 설정 추가 코드>

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"), 8192)) { // 8KB 버퍼 크기 설정
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

📍 BufferedWriter

텍스트 파일에 데이터를 쓸 때 사용되며, 버퍼를 사용하여 여러 번의 I/O 작업을 최소화하여 성능을 향상시킨다. 한 줄씩 쓰는 경우 newLine() 메서드를 사용할 수 있다.

🔸주요 메서드

- write(String s) : 문자열을 씀
- newLine() : 새 줄 문자를 씀
- flush() : 버퍼를 비움 (필요 시 수동으로 호출 가능)

🔸예시 코드 (기본 문법 참고!)

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExample {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            bw.write("Hello, world!");
            bw.newLine();
            bw.write("This is another line.");
            bw.flush(); // 명시적으로 버퍼를 비움
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

대용량 데이터를 파일에 효율적으로 쓰거나, 빈번한 쓰기 작업이 필요한 경우에 유용. 줄 단위로 쓰기 작업을 할 때 특히 적합하다.

🔸예시 상황

  • 로그 데이터를 파일에 저장하는 경우
  • 텍스트 데이터를 대량으로 생성하여 파일에 저장하는 경우

🔸예시 문제

  • 로그 데이터를 파일에 기록하기
  • 대량의 텍스트 데이터를 생성하여 파일에 저장하기

🔸예시 상황별 코드 응용

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExample {
    public static void main(String[] args) {
        // 예시 1: 로그 데이터를 파일에 기록하기
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("logfile.txt", true))) {
            bw.write("INFO: Application started");
            bw.newLine();
            bw.write("ERROR: Null pointer exception");
            bw.newLine();
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 예시 2: 대량의 텍스트 데이터를 생성하여 파일에 저장하기
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            for (int i = 0; i < 1000; i++) {
                bw.write("This is line number " + (i + 1));
                bw.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

<장단점 및 주의사항>

  • 장점: 대량의 데이터를 효율적으로 파일에 쓸 수 있다. newLine() 메서드를 사용하여 시스템 독립적인 방식으로 줄바꿈을 처리할 수 있다.
  • 단점: 초기 설정과 예외 처리가 필요. flush() 메서드를 적절히 사용하여 데이터를 버퍼에서 파일로 밀어내는 것이 중요하다.
  • 주의사항: 데이터를 작성한 후에는 반드시 flush() 메서드를 호출하거나 close() 메서드를 사용하여 자원을 해제해야 합니다.

<flush 예시 추가 코드>

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterExample {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            for (int i = 0; i < 100; i++) {
                bw.write("This is line number " + (i + 1));
                bw.newLine();
                if (i % 10 == 0) {
                    bw.flush(); // 10줄마다 flush() 호출
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

📍 StringBuilder

문자열을 조작할 때 효율적. String 객체는 불변(immutable)이라서 문자열을 수정할 때마다 새로운 객체를 생성하지만, StringBuilder는 내부 버퍼를 사용하여 문자열을 변경할 수 있다. 이는 문자열을 여러 번 수정하는 경우 성능 면에서 큰 이점을 제공한다.

🔸주요 메서드

- append(String s) : 문자열을 덧붙임
- insert(int offset, String s) : 특정 위치에 문자열을 삽입
- delete(int start, int end) : 문자열의 일부분을 삭제
- reverse() : 문자열을 반대로 뒤집음

🔸예시 코드 (기본 문법 참고!)

public class StringBuilderExample {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        sb.append("Hello");
        sb.append(", ");
        sb.append("world!");
        System.out.println(sb.toString()); // 출력: Hello, world!

        sb.insert(5, " beautiful");
        System.out.println(sb.toString()); // 출력: Hello beautiful, world!

        sb.delete(5, 15);
        System.out.println(sb.toString()); // 출력: Hello, world!

        sb.reverse();
        System.out.println(sb.toString()); // 출력: !dlrow ,olleH
    }
}

문자열을 빈번하게 수정해야 하는 경우에 사용. 성능을 최적화하기 위해 불변 객체인 String 대신 가변 객체인 StringBuilder를 사용한다.

🔸예시 상황

  • 긴 문자열을 반복적으로 추가하거나 수정하는 경우
  • 문자열을 조작하여 다양한 형식을 만들 때

🔸예시 문제

  • 여러 문자열을 결합하여 하나의 긴 문자열을 만들기
  • 특정 조건에 따라 문자열을 반복적으로 수정하기

🔸예시 상황별 코드 응용

public class StringBuilderExample {
    public static void main(String[] args) {
        // 예시 1: 여러 문자열을 결합하여 하나의 긴 문자열을 만들기
        StringBuilder sb = new StringBuilder();
        sb.append("Hello");
        sb.append(", ");
        sb.append("world!");
        System.out.println(sb.toString()); // 출력: Hello, world!

        // 예시 2: 특정 조건에 따라 문자열을 반복적으로 수정하기
        sb.setLength(0); // 초기화
        for (int i = 1; i <= 10; i++) {
            sb.append("Number: ").append(i).append("\n");
        }
        System.out.println(sb.toString()); // 1부터 10까지의 숫자 문자열 출력
    }
}

<장단점 및 주의사항>

  • 장점: 문자열을 빈번하게 수정해야 할 때, 불변 객체인 String 대신 사용하여 성능을 최적화할 수 있다.
  • 단점: 동기화되지 않아서 멀티스레드 환경에서는 사용할 수 없으며, 이 경우 StringBuffer를 사용해야 한다.
  • 주의사항: StringBuilder는 String 객체와 달리 가변 객체이기 때문에, 다른 객체에 의해 참조되고 있을 때 변경하면 예상치 못한 결과가 발생할 수 있다.

<멀티스레드 환경 주의사항 추가 코드>

public class StringBuilderExample {
    public static void main(String[] args) {
        // 멀티스레드 환경에서는 StringBuilder 대신 StringBuffer 사용 권장
        StringBuilder sb = new StringBuilder();
        sb.append("Hello");
        sb.append(", ");
        sb.append("world!");
        System.out.println(sb.toString()); // 출력: Hello, world!

        // 문자열 조작 예시
        sb.setLength(0); // 초기화
        for (int i = 1; i <= 10; i++) {
            sb.append("Number: ").append(i).append("\n");
        }
        System.out.println(sb.toString()); // 1부터 10까지의 숫자 문자열 출력
    }
}

<마무리..>
Scanner는 간편한 입력 처리를, BufferedReader와 BufferedWriter는 효율적인 파일 I/O를, StringBuilder는 효율적인 문자열 조작을 제공한다.

관련 개념 정리 글 ) 여기로


알면 알수록.. ㅎ... 이야 쉽지 않다 아주 그냥...

profile
룰루

0개의 댓글