바로 직전에 FileWriter를 활용하여 텍스트 파일에 글을 남기는 방법을 알아보았습니다. 이번 글에서는 FileWriter에다가 BufferedWriter까지 활용하여 글을 남기는 방법을 알아보도록 하겠습니다.


근데, 왜 FileWriter만으로도 할 수 있는 작업을 BufferedWriter까지 활용해야 하냐구요? 바로 성능의 문제입니다.


작은 데이터를 쓰는 경우에야 FileWriter만으로도 큰 문제가 없지만, 100K 내외 이상의 데이터를 써야 하는 경우에는 성능상으로 봤을 때 BufferedWriter를 함께 사용하는 것이 더 효율적이라고 합니다. 그렇다면 여기서 등장하는 버퍼 (buffer)라는 개념은 무슨 의미일까요?


버퍼라는 단어 자체는 '완충'이라는 의미를 갖고 있습니다. 그리고 컴퓨터 과학에서 말하는 버퍼는 데이터가 한곳에서 다른 곳으로 이동하는 동안 일시적으로 그 데이터를 저장하는 메모리 공간을 의미합니다. 버퍼에 일정 이상의 데이터가 담기면 그 데이터는 다른 곳으로 전송이 되고, 새로운 데이터가 담기게 되는 과정을 반복합니다. 만약 버퍼가 없는 상태로 입출력을 주고 받는 경우라면, 입출력이 될때마다 매번 데이터를 처리하는 과정을 거쳐야 하므로 CPU 사용 횟수와 메모리 접근 횟수가 많아집니다. 버퍼를 사용함으로써 CPU 사용 횟수와 메모리 접근 횟수를 줄일 수 있으며, 따라서 입출력의 속도를 개선할 수 있는 겁니다. 


코드를 보이기에 앞서 우선 글로 사용법을 설명하자면, 이 역시 어려울것 하나 없습니다. BufferedWriter 인스턴스를 하나 더 생성하고, 그 인스턴스의 인자로 FileWriter 인스턴스를 집어넣으면 끝입니다. 그리고 write()와 flush() 메소드가 BufferedWriter 인스턴스를 통해 쓰여지게 하면 됩니다.


다음은 예제 코드입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteToFile {
    public static void main(String args[]) {
        
        String message = "This is a sample message.\n";
        
        File file = new File("test1.txt");
        FileWriter writer = null;
        BufferedWriter bWriter = null;
        
        try {
            writer = new FileWriter(file, true);
            bWriter = new BufferedWriter(writer);
            
            bWriter.write(message);
            bWriter.flush();
            
            System.out.println("DONE");
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(bWriter != null) bWriter.close();
                if(writer != null) writer.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


반응형

.txt 파일을 생성하고 여기에 텍스트를 쓰는 방법으로는 일단 다음과 같은 두가지 방법을 알고 있습니다.

1. FileWriter를 이용하여 쓰기

2. BufferedWriter 및 FileWriter를 이용하여 쓰기

3. FileOutputStream 클래스를 이용하여 쓰기


이 중에서 이 글에서는 FileWriter를 이용하여 글을 쓰는 방법을 알아보겠습니다. 


FileWriter 클래스

파일에 문자를 쓰기 위해 활용되는 클래스로 OutputStreamWriter를 상속하고 있습니다. 

FileWriter 클래스만을 활용하여 파일에 내용을 쓰는 경우, FileWriter 객체를 생성하고 그 인자로 File 인스턴스를 담은 뒤에 여기에 내용을 쓰고 flush()를 호출해 주면 됩니다.


다음과 같이 쓸 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
 
public class WriteToFile {
    public static void main(String args[]) {
        
        String message = "This is a sample message.\n";
        
        File file = new File("test1.txt");
        FileWriter writer = null;
        
        try {
            // 기존 파일의 내용에 이어서 쓰려면 true를, 기존 내용을 없애고 새로 쓰려면 false를 지정한다.
            writer = new FileWriter(file, true);
            writer.write(message);
            writer.flush();
            
            System.out.println("DONE");
        } catch(IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(writer != null) writer.close();
            } catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs


그런데, 위의 코드에서처럼 flush() 메소드를 호출하지 않고 실행을 해봐도 여전히 파일에 텍스트 메세지가 쓰여지는 것을 알 수 있었습니다.

그렇다면 이 flush() 메소드는 도대체 뭔가요?


위의 질문에 대한 답을 하기 전에 다른 질문 하나만 던져볼까 합니다. 파일에 내용을 쓰는 것은 입력이라고 할까요, 아니면 출력이라고 할까요?


이 질문에 답하기 위해 확실히 할 점은, 자바 IO에서 말하는 Reader, Writer, InputStream, 그리고 OutputStream의 주체는 바로 컴퓨터 자신이라는 겁니다. 즉,


컴퓨터가 파일을 읽어 들이는 경우에는 입력이 되는 것이고 (read IN, '읽어들임'이라고 이해하면 좀 더 쉬울까요?),

그 반대로 컴퓨터가 파일에 글을 쓰는 경우는 출력이라고 한다는 겁니다 (write OUT, '써서 내보내다'라고 이해하면 나을것 같습니다).


따라서 위의 샘플 코드는 파일에다 글을 쓰는, 즉 출력에 해당하는 작업인 것입니다.


다시 첫번째 질문으로 돌아가 보겠습니다. 컴퓨터가 파일에 내용을 쓰는 경우, 버퍼 (Buffer)라는 개념이 등장합니다. 버퍼는 일종의 완충지대인데요,

컴퓨터 입출력 속도를 높이기 위해 도입된 개념입니다.


모든 출력은 도착 지점으로 바로 나가지 않고 이 버퍼에 먼저 쌓이는데요, 여기서 flush()를 해주어야만 비로소 쌓인 버퍼를 목적지로 내보내게 되는 겁니다.


즉 flush()를 해주지 않으면 목적지에 내용이 도착하지 않을 수 있다는 것입니다. 그렇기 때문에 write() 메소드 호출 후에 꼭 flush()를 하는 것을 잊지 말아야 합니다.


이렇게 텍스트 파일을 생성하고 파일에 텍스트를 쓰는 기능은 나중에 소프트웨어 개발에서 로그 등을 저장할 때 유용하게 쓰일 수 있을거라고 생각됩니다.


반응형

출처: https://projecteuler.net/problem=1


문제 내용


10 이하의 수 중에서 3 혹은 5의 배수인 수를 추려내 본다면 3, 5, 6, 9가 있다. 이들을 모두 합하면 123이 된다.

그렇다면 1000 이하의 수에서 3 혹은 5의 배수인 숫자들의 합은 얼마인가?


원문: 

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.


코드:

public class No001 {
public static void main(String[] args) {
int n1 = 3;
int n2 = 5;
int limit = 1000;
SumMultiple sMultiple = new SumMultiple();
int n3 = sMultiple.sumMultiples(n1, n2, limit);
System.out.println(n3);
}
static class SumMultiple {
int sumMultiples(int n1, int n2, int limit) {
int sum = 0;
int n3 = lcd(n1, n2);
for(int i=n1; i<limit; i++) {
if((i%n3) == 0) {
sum += i;
} else if((i%n2) == 0) {
sum += i;
} else if((i%n1) == 0) {
sum += i;
}
}
return sum;
}
int lcd(int n1, int n2) {
int lcd = 0;
if((n1 > n2) || (n1 <= 0) || (n2 <= 0)) return 0;
for(int i=n1;; i++) {
if((i%n1==0) && (i%n2==0)) {
lcd = i;
break;
}
}
return lcd;
}
}
}


반응형

javap는 한편으로 'Java dissembler'라고 불린다. 왜 이렇게 불리는지에 대해서는 우선 간단한 코드를 보면서 이해해 보도록 하자.


1. 우선, HelloWorld.java라는 이름의 파일이다.

1
2
3
4
5
public class HelloWorld {
    public static void main(String args[]) {
        System.out.println("Hello World!");
    }
}



2. 이 파일을 바이트코드로 변환하여 HelloWorld.class라는 파일을 생성한다.


3. 여기에서 javap 커맨드를 사용해 본다. 다음과 같은 명령어를 입력하여 실행해 보면 된다.

$javap HelloWorld


그러면 터미널에 다음과 같은 결과가 뜰 것이다.

Compiled from "HelloWorld.java"

public class HelloWorld {

  public HelloWorld();

  public static void main(java.lang.String[]);

}

이것이 의미하는 것은 무엇일까? 하나하나 뜯어보자면, 첫번째 줄에서 HelloWorld라는 파일은 HelloWorld.java라는 파일로부터 컴파일된 소스라는 것을 확인할 수 있다. 그 이하로 나오는 부분은 클래스의 기본생성자 및 메인함수와 메인함수가 갖는 파라미터의 데이터 타입이다. 


즉, javap 커맨드는 어떤 바이트코드 파일이 어디서부터 나왔으며, 어떠한 필드와 메소드를 갖고 있는 파일인지를 알려주는 기능을 수행한다고 정리할 수 있겠다.


(javap 커맨드에 대한 정보는 Oracle Docs (http://docs.oracle.com/javase/8/docs/technotes/tools/windows/javap.html)에서 더 확인할 수 있습니다. 추후 한국어로 정리하여 페이지를 업데이트 하겠습니다.)


반응형

환경: macOS Sierra


다음과 같은 자바 코드를 생성하고 HelloWorld.java라고 저장한다.

public class HelloWorld {
public static void main(String args[]) {
System.out.println("Hello World!");
}
}


이를 다음 명령어로 컴파일 한다.


$javac HelloWorld.java


성공적으로 실행되면 HelloWorld.class라는 파일이 생성된다. 클래스 파일은 컴파일러에 의해 생성된 바이트코드 (bytecode)로 이루어진 파일이다. 


위에서 생성된 클래스 파일을 실행하고 싶으면 다음 명령어를 실행하면 된다.


$java HelloWorld


여기에서 .class 확장자는 붙지 않는다는 점을 확인할 수 있다.

반응형

+ Recent posts