Search

레이블이 JAVA인 게시물을 표시합니다. 모든 게시물 표시
레이블이 JAVA인 게시물을 표시합니다. 모든 게시물 표시

2016년 10월 22일 토요일

[Java] [Library] 이메일 보내는 프로그램 만들기. (JavaMail API 이용)

#1. 들어가기
자바로 프로그래밍을 하다보면, 작업을 완료했거나, 에러가 생겼을때, 혹은 특정 시점에 메세지나 이메일을 사용자에게 보내주는 알림 기능이 필요할 때가 있다.
이번 글에서는 간단하게 JavaMail API와 네이버메일을 이용해 메일링하는 방법을 알아본다.



#2. 네이버메일 SMTP 설정하기
먼저 네이버에 로그인해서 환경설정을 해줘야 한다.

  2-1. 네이버 로그인

  2-2. '메일' 들어가기








  2-3. '환경설정' 들어가기







  2-4. 'SMTP' 설정하기
















- SMTP 설정을 하게되면 아래와 같은 정보를 확인할 수 있다.









#3. JavaMail API 다운받기
메이븐 레파지토리에는 거의 없는게 없다.. 이곳에서 다운받아보자.
https://mvnrepository.com/artifact/javax.mail/mail/1.4.7



























#4. Eclipse에서 Java 프로그래밍
이제 환경설정은 다 끝났으니, 본격적으로 이클립스에서 메일을 보내보자.

  4-1. 다운받은 mail-1.4.7.jar파일을 라이브러리에 추가하기
먼저, mail-1.4.7.jar 파일을 복사한 후, 자바프로젝트에 붙여넣어주자.
(개인적으로 정리하는 편이 프로그래밍을 할 때 편해서 lib폴더를 만들어 안에 넣었다.)
다음으로, 붙여넣은 jar파일에 마우스를 대고 우클릭을 한 후에 Build Path -> Add to Build Path를 눌러주자.




- 제대로 jar파일을 추가했다면, 아래와 같이 Referenced Libraries에 추가된다.












  4-2. 간단한 메일보내기 프로그램 작성하기
나름 작명을 해서(?) SendEmail이라는 클래스를 하나 만들었다.
(역시 정리를 위해 kr.sam.dev.martin이라는 패키지를 만들었는데, 저것까지 따라 만들 필요는 없다... 작명은 다들 취향것...)

① 보내는 쪽의 메일 설정 부분. (우리는 네이버로 설정을 했었다.)
② 받는 사람의 메일 주소.
③ 메일 제목.
④ 메일 내용.




























- SendEmail 클래스의 소스코드

package kr.sam.dev.martin;

import java.util.Properties;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class SendEmail {
 public static void main(String[] args) {

  String host     = "smtp.naver.com";
  final String user   = "NAVER_ID";
  final String password  = "PASSWORD";

  String to     = "ruserive@gmail.com";

  
  // Get the session object
  Properties props = new Properties();
  props.put("mail.smtp.host", host);
  props.put("mail.smtp.auth", "true");

  Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
   protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(user, password);
   }
  });

  // Compose the message
  try {
   MimeMessage message = new MimeMessage(session);
   message.setFrom(new InternetAddress(user));
   message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));

   // Subject
   message.setSubject("[Subject] Java Mail Test");
   
   // Text
   message.setText("Simple mail test..");

   // send the message
   Transport.send(message);
   System.out.println("message sent successfully...");

  } catch (MessagingException e) {
   e.printStackTrace();
  }
 }
}


  4-3. 테스트 및 확인
프로그램을 실행시키면 아래처럼 메일이 성공적으로 보내졌단 메세지가 뜬다.






그리고 받은쪽 메일에 들어가보면 아래처럼 내가 보낸 메일이 와있는 것을 확인할 수 있다.

















어때요 JavaMail API를 이용한 메일보내기, 참 쉽죠?






2016년 5월 16일 월요일

[Java] 두 int 값을 바꾸는 방법. (임시 변수 없이)

  #1. 들어가기.

코딩을 하다보면 가끔 두 변수의 값을 서로 바꿔야할 때가 있다.
예를 들어, 아래와 같이 변수 A와 B의 값이 서로 다르게 존재한다고 가정해보자.
int a = 10;     // a : 10
int b = 20;     // a : 20

이때, 서로의 값을 바꾸려면 어떻게 해야할까??
대부분의 사람들은 새로운 변수(temp)를 하나 더 만들어 다음과 같이 서로의 값을 바꾼다.
int temp = a;     // a : 10 |  b : 20 |  temp : 10
a = b;            // a : 20 |  b : 20 |  temp : 10
b = temp;         // a : 20 |  b : 10 |  temp : 10

여기에서, temp변수를 선언하는 것이 왠지 모르게 보기 싫다...
개발자라면 누구나 한 번씩은 고민해볼 것이다.
"temp 변수를 이용하지 않고 서로의 수를 변경할 수 있는 방법이 있을까?"


  #2-1. 방법1 - Calculation
수학에 흥미가 있는 개발자라면, 다음과 같은 식을 생각해볼 수 있다.
int a = 2;     // a : 2
int b = 4;     // b : 4

a = a + b;     // a : 6  |  b : 4
b = a - b;     // a : 6  |  b : 2
a = a - b;     // a : 4  |  b : 2

값이 서로 바뀌었다... 오?!


  #2-2. 방법2 - XOR

2-1의 방법과는 조금 다르지만... 간혹(?) 이런 방법을 생각해보는 개발자도 있을것이다...
아래 ( ) 안의 숫자는 binary 값이다.
int a = 2;    // a : 2 (0010)
int b = 4;    // b : 4 (0100)

a = a ^ b;    // a : 6 (0110)  |  b : 4 (0100)
b = a ^ b;    // a : 6 (0110)  |  b : 2 (0010)
a = a ^ b;    // a : 4 (0100)  |  b : 2 (0010)

이번에도 값이 서로 바뀌었다... 오...
(2진수와 XOR연산의 원리를 잘 모르겠다면 검색을 추천한다.)


  #3. 응용.

임시 변수를 이용해 값을 바꾸는 방법까지 총 세가지의 교환 방법을 알아보았는데,
"어떤 방법이 가장 유리한가?" 라는 질문에는
"각각의 상황에 따라 다르다"라고 대답할 수 있다.

예를 들어, 교환해야 할 수의 크기라던가 반복 횟수, 메모리의 제약 등등 고려할 사항이 많아,
상황에 맞추어 단위테스트를 진행해본 후 알고리즘에 적용하면 좋을것이다.

참고 사이트 : http://javarevisited.blogspot.kr/2013/02/swap-two-numbers-without-third-temp-variable-java-program-example-tutorial.html





2016년 4월 16일 토요일

[Database] [H2] [Java] Imbedded Database H2를 eclipse에서 사용하기.

#1. 들어가기
 앱을 개발 한다던가, 소규모의 프로젝트에서 간단하게 데이터베이스와 SQL 기능이 필요할 때,  도움이 될만한 데이터베이스를 소개하고자 한다. Imbedded Database나 H2에 관한 상세한 내용은 검색해보면 많이 나오니.. 찾아볼 것을 추천한다. 여기에서는 최초 Hello World를 찍듯, 이클립스로 "아~ 이렇게 사용하는구나" 하는 수준에서 알아본다.

#2. 준비
 1) H2 database 다운로드.
 http://www.h2database.com/html/main.html
 위 사이트에 들어가보면, All Platforms 라고 된 zip 파일을 다운받으면 된다. (만약, Java와 eclipse없이 H2만을 편하게 사용하려면, http://www.h2database.com/html/quickstart.html를 참조해 그냥 사용하면 된다. )























 2) zip파일의 압축을 풀면 bin 폴더에 h2-1.4.191.jar 파일이 있다.
  (버젼은 다운로드 시점에 따라 다를 수 있다.)









 3) eclipse에서 Java Project 생성 후, lib폴더를 만들어(정리정돈을 위해..) 복사해 넣어주자.











 4) h2-1.4.191.jar을 선택해 마우스 우클릭 ->  Build Path -> Add to Build Path.
 여기까지 된 상태면, H2 데이터베이스 사용을 위한 모든 준비가 끝났다고 봐도 좋다. (참 간단하죠??)











#3. 사용하기
 아주아주 간단하게 필요한 것만 구현한 코드를 아래에서 살펴보자.
1) 14~16번 줄에서 새로 만들 DB와 USER, PW를 설정.
2) 만약 프로그램을 실행시킬 때마다 DB를 Drop 시키지 않고 계속 유지하고 싶다면, 20번 줄은 주석처리.
3) 50~60번 줄을 통해 간단하게 테이블을 생성해 데이터를 넣고, 조회하는 것을 테스트 해봤다.
4) 참고로 H2는 왠만한 SQL문법들은 다 사용할 수 있다. (참조 : http://www.h2database.com/html/grammar.html)













package kr.oskarDevelopers.martin;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.h2.tools.DeleteDbFiles;

public class TestDriver {

    private static final String DB_DRIVER = "org.h2.Driver";
    private static final String DB_CONNECTION = "jdbc:h2:~/testdb"; // database name
    private static final String DB_USER = "martin";                 // user id
    private static final String DB_PASSWORD = "1234";               // passward

    public static void main(String[] args) {
        try {
            DeleteDbFiles.execute("~", "testdb", true); // drop db if exist 'testdb'
            initDB();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static Connection getDBConnection() {
        Connection dbConnection = null;
        try {
            Class.forName(DB_DRIVER);
        } catch (ClassNotFoundException e) {
            System.out.println(e.getMessage());
        }
        try {
            dbConnection = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD);
            return dbConnection;
        } catch (SQLException e) {
            System.out.println(e.getMessage());
        }
        return dbConnection;
    }

    private static void initDB() throws SQLException {
        Connection connection = getDBConnection();
        Statement stmt = null;
        try {
            connection.setAutoCommit(false);
            stmt = connection.createStatement();

            // create TEST_TABLE for example
            stmt.execute("CREATE TABLE TEST_TABLE(idx INT PRIMARY KEY, name VARCHAR(100));");
            
            // insert some values into TEST_TABLE
            stmt.execute("INSERT INTO TEST_TABLE VALUES(1, 'Martin.Park'), (2, 'OskarDevelopers');");
             
            // get result by using SELECT query
            ResultSet rs = stmt.executeQuery("SELECT * FROM TEST_TABLE;");
            while (rs.next()) {
                System.out.println("idx : " + rs.getString("idx") + " / " + "name : " + rs.getString("name"));
            }
            
            stmt.close();
            connection.commit();
            
        } catch (SQLException e) {
            System.out.println("Exception Message " + e.getLocalizedMessage());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            connection.close();
        }
    }
}


#4. 결과화면
 이제부터는 사용 목적에 맞게 이용하면 된다.  (너무 성의없나?..)











2016년 4월 2일 토요일

[Algorithm] [JAVA] 재귀함수 - 하노이의 탑 구현해보기.

#1. 들어가기
 알고리즘을 공부하다보면, 재귀함수가 단골손님으로 등장한다. 간단하게 말하면 자기 자신을 다시 호출하는 것이 재귀함수인데, 보통 잘 알려진 것이 하노이의 탑이다.
 하지만, 처음 알고리즘을 배우는 사람들은 "아, 그런가보다~" 하고 말지, 하노이의 탑을 어떻게 구현 해야할지는 막막하다.
 지금부터 간단하게 하노이의 탑을 살펴보고, 자바로 하노이의 탑을 구현해보자.


#2. 하노이의 탑?
 * 하노이의 탑에 대해서 자세하게 알고 싶으면 인터넷 검색을 추천한다.























 알고리즘 구현에 앞서, 간단하게 큰 특징을 정리해보면 다음과 같다.
1) 탑을 구성하는 원판은 번호(혹은 크기)가 모두 다르다.
2) 항상 번호(혹은 크기)가 큰것이 아래로 가야한다.
3) 쌓여있는 탑을 다른 기둥으로 똑같이 쌓아야 하며, 움직일 수 있는 원판은 한 번에 하나씩만 가능하다.
4) 원판을 움직일 때, 각 기둥의 가장 위에 위치한 원판만 가능하다.
5) 움직이려는 원판을 다시 내려놓을 때, 자신의 번호(혹은 크기)가 놓으려는 원판보다 작아야 한다.


#3. Java로 구현하기
 코딩을 하는 사람마다 구현하는 방법은 각자 다르겠지만, 여기서 사용한 방법은 다음과 같다. 아래의 그림처럼 먼저 클래스를 2개로 나누었고, Hanoi 클래스에서 알고리즘의 구현을 했고, Driver 클래스에서 실행을 한다.












1) Hanoi 클래스
매소드 중에 moveTower 부분을 자세히 살펴보면, 재귀함수가 사용됨을 알 수 있다.
lastMovedLine 의 숫자를 1 혹은 2로 바꿔서, 하노이 탑의 최종 위치를 변경할 수 있다. 
(구지 하노이의 탑을 항상 3번째 기둥으로 옮기고자 한다면, 하노이 탑이 짝수일 경우에 lastMovedLine을 2로 해주는 로직을 추가하면 된다.)


package hanoiTower;

public class Hanoi {

 private int x = 3; // fixed. A number of pillar.
 private int y = -1; // height
 private int[][] hanoiField;
 private int[] cntLine = new int[x];
 private int lastFoundLine = -1;
 private int lastMovedLine = 1; // choose the place to move. (1 or 2)
 private int moveCNT = -1; // moved times count

 public Hanoi(int num) {
  this.y = num;
  this.hanoiField = new int[num][x];
 }

 public void initHanoiTower() {
  System.out.println("Start!");
  System.out.println("==========" + "\n");

  // make HanoiTower
  for (int i = y; i > 0; i--) {
   hanoiField[i - 1][0] = i;
  }

  moveTower(y);

  System.out.println("==========");
  System.out.println("Done!");
  System.out.println("Total moved count : " + moveCNT);
 }

 public void showTower() {
  for (int i = 0; i < y; i++) {
   for (int j = 0; j < x; j++) {
    String s = String.valueOf(hanoiField[i][j]);
    if (s.length() == 1 || s.equals("0")) {
     System.out.print("| " + s.replace("0", " ")
       + blank(s.length()));
    } else {
     System.out.print("| " + s + blank(s.length()));
    }
   }
   System.out.print("|");
   System.out.println();
  }
  System.out.println("----------------" + "\n");
  moveCNT++;
 }

 public int countLine(int num) {
  for (int i = 0; i < x; i++) {
   int cnt = 0;
   for (int j = 0; j < y; j++) {
    if (hanoiField[j][i] != 0) {
     cnt = cnt + 1;
    }
   }
   cntLine[i] = cnt;
  }
  return cntLine[num];
 }

 public int[] findNumPlace(int num) {
  int[] coordinate = new int[2];
  coordinate[0] = -1;
  coordinate[1] = -1;
  for (int i = 0; i < y; i++) {
   for (int j = 0; j < x; j++) {
    if (hanoiField[i][j] == num) {
     lastFoundLine = j;
     coordinate[0] = j;
     coordinate[1] = i;
    }
   }
  }
  return coordinate;
 }

 public void moveTower(int num) {
  int to = -1;
  if (num <= 2) {
   showTower();

   // move 1, 2
   for (int i = 1; i <= 2; i++) {
    hanoiField[findNumPlace(i)[1]][findNumPlace(i)[0]] = 0;
    to = x - (lastFoundLine + lastMovedLine);
    hanoiField[(y - 1) - countLine(to)][to] = i;
    lastMovedLine = to;
    showTower();
   }

   // move 1 again
   hanoiField[findNumPlace(1)[1]][findNumPlace(1)[0]] = 0;
   hanoiField[(y - 1) - countLine(to)][to] = 1;
   showTower();

  } else {
   // reflexive
   moveTower(num - 1);

   // move the tower's number bigger than 2
   hanoiField[findNumPlace(num)[1]][findNumPlace(num)[0]] = 0;
   to = x - (lastFoundLine + lastMovedLine);
   hanoiField[(y - 1) - countLine(to)][to] = num;
   lastMovedLine = to;

   // shift place when the tower's number is even.
   if (num % 2 == 0) {
    // System.out.println("!!!!!");
    lastMovedLine = lastFoundLine;
   }

   // move 1, 2 again
   moveTower(num - 1);
  }
 }

 public String blank(int num) {
  String s = String.valueOf(this.y);
  int l = s.length();
  String o = " ";
  for (int i = l - num; i > 0; i--) {
   o = o + " ";
  }
  return o;
 }
}



2) Driver 클래스
7번 라인 Hanoi()안의 숫자를 변경하면, 하노이 탑의 크기를 변경해서 볼 수 있도록 해두었다.  


package hanoiTower;

public class Driver {

 public static void main(String[] args) {
  
  // You can change the start height of HanoiTower.
  Hanoi h = new Hanoi(5);
  h.initHanoiTower();
 }
}



#4. 결과 화면
 하노이 탑을 설명할 때 사용한 이미지와 동일하게 원판을 하나하나 움직여서 탑을 우측으로 옮긴 모습을 확인할 수 있다. 






































 만약, 15개 짜리 하노이의 탑이라면? 직접 프로그램으로 돌려보길 바란다.
(혹은 운이 좋다면, 정확하게 32,767회의 움직임 끝에 하노이 탑을 모두 옮길 수 있을 것이다.)

2015년 11월 13일 금요일

[JAVA] [Library] 웹 페이지의 내용을 가져와보자. HttpClient 튜토리얼.

* 웹페이지의 내용을 쉽게 가져오기 위해 HttpClient 라이브러리를 사용해보자.
* 먼저 아래의 사이트에서 Binary로 된 압축파일을 하나 다운 받아 압축을 풀자.
http://hc.apache.org/downloads.cgi



































* 위와같이 HttpClient 파일이 준비되었다면, 이클립스를 열어 Java프로젝트를 생성하자.
* 본 글에서는 프로젝트명을 httpClient로 했고, 정리정돈을 위해 lib 폴더를 만들었다..









* 좀전에 압축 푼 파일의 lib폴더에 있는 모든 .jar 파일들을 프로젝트 내 lib 폴더로 복사하자.



















* 이클립스에 복사된 모든 .jar파일을 선택해 빌드패쓰에 추가해주자.
* 우클릭 -> Build Path -> Add to Build Path





































* 정상적으로 빌드패쓰에 추가가 되었다면 다음과 같은 화면이 나올 것이다.


























* 다음으로는 이 라이브러리를 사용하기 위해 src 폴더에 기본 예제 소스코드들을 추가해보자. 아래 첨부 그림들 참조.
* src에서 우클릭 -> Import -> General -> File System -> Browse

























































* 디랙토리 선택 창까지 왔다면, 아까 압축 푼 파일의 examples 폴더를 선택하고 확인버튼을 눌러주자.
* 그러면 아래와 같이 파일시스템 좌측에 선택한 폴더가 뜨는데, 거기서 체크버튼을 누르고 완료한다.




























* Import가 성공하면 아래와 같이 모든 examples 패키지가 들어가게 된다.








































* 여기서 ClientWithResponseHandler를 열어보면 아래와 같은데, HttpGet의 주소명을 변경하고 실행하면 웹페이지의 내용을 가져올 수 있다.
package org.apache.http.examples.client;

import java.io.IOException;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

/**
 * This example demonstrates the use of the {@link ResponseHandler} to simplify
 * the process of processing the HTTP response and releasing associated resources.
 */
public class ClientWithResponseHandler {

    public final static void main(String[] args) throws Exception {
        CloseableHttpClient httpclient = HttpClients.createDefault();
        try {
            HttpGet httpget = new HttpGet("http://www.google.com/");

            System.out.println("Executing request " + httpget.getRequestLine());

            // Create a custom response handler
            ResponseHandler responseHandler = new ResponseHandler() {

                @Override
                public String handleResponse(
                        final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        throw new ClientProtocolException("Unexpected response status: " + status);
                    }
                }

            };
            String responseBody = httpclient.execute(httpget, responseHandler);
            System.out.println("----------------------------------------");
            System.out.println(responseBody);
        } finally {
            httpclient.close();
        }
    }
}

2015년 11월 5일 목요일

[JAVA] [Library] OpenCSV를 이용한 CSV 파일 파싱, 변환.

* CSV 파일은 쉼표로 구분된 파일을 말한다. 그런데, 때에 따라서 쉼표를 '|' 와 같은 형태로 구분해야 한다던가 하는 일도 생기기 마련이다.
* 그 때 유용한 것이 OpenCSV라는 JAVA라이브러리이다.
* 다운로드는 아래의 소스포지 사이트에서 받을 수 있으며, 본 블로그에서는 opencsv-3.5.jar 버젼을 사용했다.

http://sourceforge.net/projects/opencsv/


* 먼저, 아래와 같이 openCSV 라는 자바 프로젝트를 만들고, openCSV라는 패키지 안에
읽기에 필요한 클래스(CSVRead),
쓰기에 필요한 클래스(CSVWrite),
조작을 위한 메인 클래스(Driver)를 만들었다.
* 다음으로, lib 폴더에는 다운받은 jar파일을 넣어서 Build Path에 추가했고,
input 폴더와 output 폴더를 만들었고(정리정돈을 위해..),
input 폴더에는 테스트를 위한 csv파일 하나를 미리 넣어두었다.




















* CSVRead 클래스의 소스

package openCSV;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import com.opencsv.CSVReader;

public class CSVRead {

  private String filename = "input\\test.csv";

  public CSVRead() {}

  public List<String[]> readCsv() {

    List<String[]> data = new ArrayList<String[]>();

    try {
      // CSVReader reader = new CSVReader(new FileReader(filename), '\t');
      // UTF-8
      CSVReader reader = new CSVReader(new InputStreamReader(new FileInputStream(filename), "UTF-8"));
      String[] s;

      while ((s = reader.readNext()) != null) {
        data.add(s);
      }
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return data;
  }
}

* CSVWrite 클래스의 소스

package openCSV;

import java.io.FileWriter;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import com.opencsv.CSVWriter;

public class CSVWrite {

  private String filename = "output\\test.txt";

  public CSVWrite() {}

  public void writeCsv(List data) {
    try {
      CSVWriter cw = new CSVWriter(new FileWriter(filename), '|', CSVWriter.NO_QUOTE_CHARACTER);
      Iterator it = data.iterator();
      try {
        while (it.hasNext()) {
          String[] s = (String[]) it.next();
          cw.writeNext(s);
        }
      } finally {
        cw.close();
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

}


* Driver 클래스의 소스

package openCSV;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Driver {

  public static void main(String[] args) {

    List<String[]> data = new ArrayList<String[]>();
    CSVRead read = new CSVRead();
    data = read.readCsv();
    Iterator<String[]> it = data.iterator();

    while (it.hasNext()) {
      String[] array = (String[]) it.next();
      for (String s : array) {
        System.out.print(s + " ");
      }
      System.out.print("\n");
    }

    // 이곳은 데이터를 파일로 쓰기 위한 코드     CSVWrite cw = new CSVWrite();     cw.writeCsv(data);   } }

* 단순히 CSV파일을 읽기만 하려면, Driver 클래스에서 주석을 달아둔 부분 아래를 생략하고 실행하면 된다.