바로 직전에 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()를 하는 것을 잊지 말아야 합니다.


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


반응형


프로젝트명: 스몰토크 (Small Talk)


프로젝트 내용: 안드로이드 플랫폼 메신저 어플리케이션


프로젝트 개발인원: 1명 (혼자)


프로젝트 개발기간: 2017년 3월 20일 - 2017년 4월 10일 (이후로도 계속 수정하고 새로운 기능 추가하고 있느라 사실 끝을 정의하기가 애매하긴 합니다)


사용된 기술

- 프로그래밍 언어: 자바 (클라이언트), PHP (백엔드)

- IDE: 안드로이드 스튜디오, 이클립스

- 버전관리: Git

- 라이브러리 (안드로이드 기본 라이브러리 및 support 라이브러리 제외): OkHttp 및 Retrofit (클라이언트 네트워크), Firebase Messaging (메세지 전송 및 푸시 구현), Google Analytics for Android (앱 활동내역 트래킹)

- 데이터베이스: SQLite (클라이언트), MySQL (백엔드) 


* 호스팅어 (hostinger.kr)라는 웹호스팅 사이트를 이용하였습니다.


현재도 계속 기능 추가를 하고 있으며, 관련 내용은 계속 블로그에 올릴 계획입니다.


개발중인 프로젝트의 소스코드를 다음 링크에서 확인할 수 있습니다. 많은 관심 부탁드립니다.

클라이언트: https://github.com/marshallslee/Small-Talk

백엔드: https://github.com/marshallslee/Small-Talk-Backend


또한, 단순하지만 에뮬레이터를 이용한 짧은 시연 동영상을 유투브에 올렸으니 이것도 한번 봐주시면 감사하겠습니다.


반응형

출처: 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;
}
}
}


반응형

프로그래밍을 하면서 모르는 점이 있을 때 블로그 등을 검색하여 글을 찾아보면 다음과 같이 코드 예시가 보기 좋게(?) 포맷되어 있는 경우가 많다.


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



이걸 어떻게 하는가 확인해 보니까 매우 간단했다. 다음 절차대로 하면 된다.


1. 컬러 스크립터 (http://colorscripter.com/) 라는 사이트에 접속해서 여기다가 코드를 쓴다. 몇가지 옵션을 제공하고 있어서 위의 예시처럼 검은 배경으로 할 수도 있고 다른것도 있다.


2. 화면 하단에 '클립보드에 복사'라는 버튼이 있는데 이걸 누르고 블로그 글쓰기에서 붙여넣기를 한다. 


3. 끝!

반응형

FileZilla로 localhost에 접속하는데만 무려 5시간 넘게 허비했다. 왜?


굉장히 간단하더라ㅡㅡ


컴퓨터가 ftp 서버에 접속해 있지 않은 상태에서 FileZilla로만 접속을 하려다 보니까 계속 서버 연결이 끊어진다는둥 헛소리가 나온 것이다.


결론:

$sudo -s launchctl load -w /System/Library/LaunchDaemons/ftp.plist를 터미널에서 실행한다.

그다음에 FilleZilla에서 localhost로 다시 접속한다.


성공!


반응형

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 확장자는 붙지 않는다는 점을 확인할 수 있다.

반응형

find라는 명령어를 활용하면 된다. Permission을 갖고 접근해야 하는 디렉토리에서도 파일을 검색해봐야 하는 경우에는 sudo 명령어를 앞에 추가해 주어야 한다.


$sudo find / -iname filename.extension


여기서 /는 디렉토리를 말한다. 즉 루트 이하의 모든 저장 장소 중에서 찾아내라는 조건을 뜻하는 것이다. -iname이라는 플래그는 대소문자와 관계 없는 (case-insensitive) 이름 검색을 주문하는 것이다. 다음 명령어는 결론적으로 루트 폴더 내에서 filename.extension라는 이름과 철자가 일치하는 파일이 있는지랑 그 파일의 소재 경로를 알려달라는 내용인 것이다.

반응형

'' 카테고리의 다른 글

FileZilla로 localhost 접속하는 방법  (0) 2016.11.11

환경: macOS Sierra


C++에서 제공하는 int형 변수 혹은 unsigned long long int 등의 최대값을 넘어서는 매우 큰 숫자를 활용해야 할 경우가 개발하는 도중에 있을지도 모르겠다.


그런 경우에 활용 가능한 라이브러리가 바로 GMP 라이브러리이다. GMP는 'the GNU Multiple Precision Arithmetic Library'를 말하며 이름에서 알 수 있듯 GNU 프로젝트에서 만든 라이브러리이다.


이 라이브러리를 활용하기 위해서는 우선 현재 사용하고 있는 컴퓨터에 gmp 라이브러리가 설치되어 있는지를 확인해야 한다. 맥 환경 기준으로 gmp 라이브러리를 설치하기 위해서는 다음과 같은 명령어를 터미널에서 실행하여 설치한다.


$brew install gmp


다음은 gmp 라이브러리를 활용한 test.cpp라는 이름의 예제이다. 


#include <iostream>
#include <gmpxx.h>
using namespace std;
mpz_class getFactorial(int);
int main(int argc, char **argv) {
int num = 100;
mpz_class factorial = getFactorial(num);
cout << "Factorial of " << num << ": " << factorial << endl;
return 0;
}
mpz_class getFactorial(int num) {
int i;
mpz_class factorial = 1;
for(i=1; i<=num; i++) {
factorial *= i;
}
return factorial;
}

위의 코드를 gcc를 통해 컴파일 할 경우, 커맨드 내에 별도의 플래그가 필요하다.


$gcc test.cpp -lstdc++ -lgmpxx -lgmp -o test


성공적으로 컴파일 되었을 경우 test라는 이름의 실행 파일이 만들어진다. 이를 실행시켜 보면 그 결과를 알 수 있을 것이다.

반응형

+ Recent posts