728x90
반응형



한국에서는 잘 사용하지않는 부분이지만, 일본에서는 거의 모든 프로젝트에 들어가는 LDAP ...
처음에는 뭔지 잘 몰랐지만, 조금씩 알것 같은 느낌...

너무 많은 곳에서 LDAP 관련 인증을 이용하여 로그인을 하기 때문에 LDAP에 관련 Java 프로그램을 만들어 보았다.

그럼 LDAP은 뭘까? 아래는 위키에 설명된 것을 발취한 내용이다.

LDAP(Lightweight Directory Access Protocol, 라이트웨이트 디렉터리 액세스 프로토콜)은 TCP/IP 위에서 디렉터리 서비스를 조회하고 수정하는 응용 프로토콜이다.

디렉터리는 논리, 계급 방식 속에서 조직화된, 비슷한 특성을 가진 객체들의 모임이다. 가장 일반적인 예로는 전화 번호부(telephone directory)가 있는데 가나다 순의 일련의 이름을 가지고 있고, 이름마다 전화 번호와 주소가 포함되어 있다. 이러한 기본 설계 때문에 LDAP는 인증을 위한 다른 서비스에 의해 자주 사용된다.

LDAP 디렉터리 트리는 선택된 모델에 따라 다양한 정치적, 지질학적, 조직적 경계를 반영하기도 한다. 오늘날 LDAP의 배치는 최상위 수준의 계급을 구조화하기 위해 도메인 이름 서비스의 이름을 사용하는 경향이 있다. 디렉터리 안에 들어가면 들어갈수록 사람들, 조직, 프린터, 문서, 그룹 등을 대표하는 항목들이 나타난다.

LDAP의 현재 버전은 LDAPv3이다.


쉽게 생각하면 디렉토리 서비스...디렉토리 트리를 이용하여 빠른 검색을 이용한다..뭐 이런것 같음...


java로 구현한 LDAP 디렉토리 삭제
(하위 디렉토리 추가는 관리자 계정으로 로그인을 해야한다.)

위 소스를 실행하면 디렉토리가 삭제된다.

지금까지 LDAP에 관련된 검색, 추가, 삭제, 수정에 관한것을 java를 이용하여 구현 해보았다. 실제로 LDAP을 잘 이용하기 위해서는 좀더 공부를 할 필요하가 있다.



728x90
반응형
728x90
반응형


한국에서는 잘 사용하지않는 부분이지만, 일본에서는 거의 모든 프로젝트에 들어가는 LDAP ...
처음에는 뭔지 잘 몰랐지만, 조금씩 알것 같은 느낌...

너무 많은 곳에서 LDAP 관련 인증을 이용하여 로그인을 하기 때문에 LDAP에 관련 Java 프로그램을 만들어 보았다.

그럼 LDAP은 뭘까? 아래는 위키에 설명된 것을 발취한 내용이다.

LDAP(Lightweight Directory Access Protocol, 라이트웨이트 디렉터리 액세스 프로토콜)은 TCP/IP 위에서 디렉터리 서비스를 조회하고 수정하는 응용 프로토콜이다.

디렉터리는 논리, 계급 방식 속에서 조직화된, 비슷한 특성을 가진 객체들의 모임이다. 가장 일반적인 예로는 전화 번호부(telephone directory)가 있는데 가나다 순의 일련의 이름을 가지고 있고, 이름마다 전화 번호와 주소가 포함되어 있다. 이러한 기본 설계 때문에 LDAP는 인증을 위한 다른 서비스에 의해 자주 사용된다.

LDAP 디렉터리 트리는 선택된 모델에 따라 다양한 정치적, 지질학적, 조직적 경계를 반영하기도 한다. 오늘날 LDAP의 배치는 최상위 수준의 계급을 구조화하기 위해 도메인 이름 서비스의 이름을 사용하는 경향이 있다. 디렉터리 안에 들어가면 들어갈수록 사람들, 조직, 프린터, 문서, 그룹 등을 대표하는 항목들이 나타난다.

LDAP의 현재 버전은 LDAPv3이다.


쉽게 생각하면 디렉토리 서비스...디렉토리 트리를 이용하여 빠른 검색을 이용한다..뭐 이런것 같음...


java로 구현한 LDAP Attribute 수정
(하위 디렉토리 추가는 관리자 계정으로 로그인을 해야한다.)

위 소스를 실행후 검색을 해보면...아래와 같이 변경이 된것을 확인 할수가 있다.



[관련글 바로 가기]

728x90
반응형
728x90
반응형


한국에서는 잘 사용하지않는 부분이지만, 일본에서는 거의 모든 프로젝트에 들어가는 LDAP ...
처음에는 뭔지 잘 몰랐지만, 조금씩 알것 같은 느낌...

너무 많은 곳에서 LDAP 관련 인증을 이용하여 로그인을 하기 때문에 LDAP에 관련 Java 프로그램을 만들어 보았다.

그럼 LDAP은 뭘까? 아래는 위키에 설명된 것을 발취한 내용이다.

LDAP(Lightweight Directory Access Protocol, 라이트웨이트 디렉터리 액세스 프로토콜)은 TCP/IP 위에서 디렉터리 서비스를 조회하고 수정하는 응용 프로토콜이다.

디렉터리는 논리, 계급 방식 속에서 조직화된, 비슷한 특성을 가진 객체들의 모임이다. 가장 일반적인 예로는 전화 번호부(telephone directory)가 있는데 가나다 순의 일련의 이름을 가지고 있고, 이름마다 전화 번호와 주소가 포함되어 있다. 이러한 기본 설계 때문에 LDAP는 인증을 위한 다른 서비스에 의해 자주 사용된다.

LDAP 디렉터리 트리는 선택된 모델에 따라 다양한 정치적, 지질학적, 조직적 경계를 반영하기도 한다. 오늘날 LDAP의 배치는 최상위 수준의 계급을 구조화하기 위해 도메인 이름 서비스의 이름을 사용하는 경향이 있다. 디렉터리 안에 들어가면 들어갈수록 사람들, 조직, 프린터, 문서, 그룹 등을 대표하는 항목들이 나타난다.

LDAP의 현재 버전은 LDAPv3이다.


쉽게 생각하면 디렉토리 서비스...디렉토리 트리를 이용하여 빠른 검색을 이용한다..뭐 이런것 같음...


java로 구현한 LDAP 디렉토리 추가
(하위 디렉토리 추가는 관리자 계정으로 로그인을 해야한다.)

실행결과 LDAPAddSubDir success. 가 출력된다. 앞에서 만든 검색소스를 이용하여 검색을 하면 ...
와 같은 결과가 나온다.



728x90
반응형
728x90
반응형

한국에서는 잘 사용하지않는 부분이지만, 일본에서는 거의 모든 프로젝트에 들어가는 LDAP ...
처음에는 뭔지 잘 몰랐지만, 조금씩 알것 같은 느낌...

너무 많은 곳에서 LDAP 관련 인증을 이용하여 로그인을 하기 때문에 LDAP에 관련 Java 프로그램을 만들어 보았다.

그럼 LDAP은 뭘까? 아래는 위키에 설명된 것을 발취한 내용이다.

LDAP(Lightweight Directory Access Protocol, 라이트웨이트 디렉터리 액세스 프로토콜)은 TCP/IP 위에서 디렉터리 서비스를 조회하고 수정하는 응용 프로토콜이다.

디렉터리는 논리, 계급 방식 속에서 조직화된, 비슷한 특성을 가진 객체들의 모임이다. 가장 일반적인 예로는 전화 번호부(telephone directory)가 있는데 가나다 순의 일련의 이름을 가지고 있고, 이름마다 전화 번호와 주소가 포함되어 있다. 이러한 기본 설계 때문에 LDAP는 인증을 위한 다른 서비스에 의해 자주 사용된다.

LDAP 디렉터리 트리는 선택된 모델에 따라 다양한 정치적, 지질학적, 조직적 경계를 반영하기도 한다. 오늘날 LDAP의 배치는 최상위 수준의 계급을 구조화하기 위해 도메인 이름 서비스의 이름을 사용하는 경향이 있다. 디렉터리 안에 들어가면 들어갈수록 사람들, 조직, 프린터, 문서, 그룹 등을 대표하는 항목들이 나타난다.

LDAP의 현재 버전은 LDAPv3이다.


쉽게 생각하면 디렉토리 서비스...디렉토리 트리를 이용하여 빠른 검색을 이용한다..뭐 이런것 같음...


아래는 내가 사용한 LDAP 구조이다.

위부분에서 중요한 부분은 바로 dn이다. 바로 이부분...(예를들어서 썼음..)

java를 이용한 검색 소스

실행 결과

마지막 "Errors listing attributes: java.lang.NullPointerException"부분은 아직 지정되지 않은telephonenumber Attribute를 참조하려고 했는데 실제, telephonenumber부분이 아직 없기 때문에 나오는 것이다.



728x90
반응형
728x90
반응형
출처 throw new *^^*; | 예영파피
원문 http://blog.naver.com/agapeuni/60064550602 
CCL

reference

한글문서

영문문서

링크

관련툴

<div class="note"> 위키북스에서 출판되는 iBATIS In Action에서 독자의 이해를 돕고자 하는 사항에 대해 정보를 제공한다. </div>

샘플코드

  • queryForMap()의 사용예제 - iBATIS사용시 대개의 개발자는 queryForObject와 queryForList를 사용한다. 그래서 queryForMap에 대한 이해나 예제가 부족한 실정이다. 그래서 이해를 돕고자 예제를 제공한다.
  • Procedure 사용예제 - Procedure사용예제를 다룬다. IN, OUT, INOUT타입을 다룬다.
  • iBATIS Error Message - iBATIS를 사용하면서 겪게 되는 에러 메시지.

 

[출처] http://openframework.or.kr

728x90
반응형
728x90
반응형

synchronized 는 method에 썼을 때에는 method 단위로, block으로 지정했을 때에는 block 단위로 배타제어가 됩니다.

 

public synchronized void func1() {

}

 

public void func2() {

  ...

  synchronized (obj) {

    ...

  }

}

 

위와 같이 두 함수가 같은 클래스에 있을 때 한 프로세스가 func1을 실행하고 있을 때 다른 프로세스는 func1을 실행할 수 없습니다. 하지만 func2는 실행이 가능하죠.

func2에서는 두 개 이상의 프로세스가 동시에 함수를 실행할 수는 있지만 synchronized 블럭은 한번에 하나씩만 실행됩니다.


===================================================================================


그럼...동시에 실행시 블록안에 있는건 기다렸다가 FIFO 방식으로 호출하는건가?? 이건 좀 알아 봐야 할듯...

728x90
반응형
728x90
반응형

 

1. 드라이버설치
해당 DB 드라이버를 JAVA_HOME/jre/lib/ext 또는 TOMCAT_HOME/common/lib 아래에 복사
 
 
2. URL 형식
url 형식의 문자열을 인자로 사용.
 
jdbc:subprotocol:subname
subprotocol -> 사용할 드라이버 이름 or 특정 데이터베이스와의 연결을 지정하는 방식
subname -> 찾고자 하는 특정 데이터베이스명
 
 
3. Database별 Driver 와 connection URL
DATABASE
VALUE
ORACLE
DRIVER
oracle.jdbc.driver.OracleDriver
URL
jdbc:oracle:thin:@hostname:port:SID
MSSQL
DRIVER
com.microsoft.jdbc.sqlserver.SQLServerDriver
URL
jdbc:Microsoft:sqlserver://localhost:1433;databasename=DB
MYSQL
DRIVER
com.mysql.jdbc.Driver
URL
jdbc:mysql://localhost:3306/DB

4. 드라이버테스트 (도스창)  
도스상에서 javap 드라이버명
ex)javap com.mysql.jdbc.Driver
 
 
5. DB 접속테스트 (JSP 테스트) 
<%@ page contentType="text/html;charset=euc-kr" import="java.sql.*" %>
<%
try {
  Class.forName("해당JDBC_DRIVER");
  String url = "해당CONNECTION URL";
  String id = "DB사용자아이디";
  String pass = "DB비밀번호";
 
  Connection conn = DriverManager.getConnection(url, id, pass); 
 
  out.println("데이터베이스연결성공")
  conn.close(); 
catch(SQLException e) { 
  out.println("데이버베이스연결실패" + e.printStackTrace());

%>

6. DB 접속테스트 (java 테스트)
 
import java.sql.*;

public class DriverTest{
       
       // mysql
       private static String JDBC_DRIVER = "com.mysql.jdbc.Driver";
       private static String JDBC_URL = 
           "jdbc:mysql://localhost:3306/dbname?uniCode=true&characterEncoding=euckr";
       private static String DBUSER = "root";
       private static String DBUSER_PASS = "passwd";

       
/* mssql
       private static String JDBC_DRIVER = "com.microsoft.jdbc.sqlserver.SQLServerDriver";
       private static String JDBC_URL = 
                                   "jdbc:microsoft:sqlserver://localhost:1433;databasename=gmpd";
       private static String DBUSER = "sa";
       private static String DBUSER_PASS = "passwd";
       */

 
       public static void main(String args[]){
             Connection con = null;
             try {
                 Class.forName(JDBC_DRIVER).newInstance();
                 con=DriverManager.getConnection(JDBC_URL, DBUSER, DBUSER_PASS);
                 System.out.println("Success");
             } catch(SQLException ex){ 
                 System.out.println("SQLException" + ex);
                 ex.printStackTrace();
             } catch(Exception ex){ 
                 System.out.println("Exception:" + ex);
                 ex.printStackTrace();                   
             }
       }
}
728x90
반응형
728x90
반응형

Jakarta POI

 

 

I. POI 란?

 

일반적으로 POI가 엑셀파일을 쓰는 컴퍼넌트로 알려져 있으나 POI는 프로젝트 이름입니다.
즉 POI는 Microsoft Format File을 액세스 할 수 있는 API를 제공합니다. (한마디로 자바에서 MS파일을 읽고 쓸수있도록 지원합니다.)

 

POI안에는 여러 컴퍼넌트들이 있습니다.

① POIFS 
Microsoft의 OLE2 포맷 형식의 문서를 자바로 읽고 쓸수 있는 컴퍼넌트입니다
기본적으로 POI의 모든 컴퍼넌트들이 POIFS를 사용합니다.
② 
HSSF
Microsoft의 엑셀파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다.
③ 
HWPF
Microsoft의 워드파일을 읽고 쓸수 있도록 지원하는 컴퍼넌트입니다.
이 컴퍼넌트는 디자인 초기단계입니다.
④ 
HPSF
Microsoft의 OLE2 포맷 형식의 문서 속성을 어플리케이션에서 사용 할수 있도록 지원하는 컴퍼넌트입니다.
현재 읽기 기능만 제공합니다

 

워드파일을 핸들링 하는 HWPF는 초기단계라 사용을 못하지만 기대는 되는군요 ^^

 

ps. 영어사전을 찾아보니 poi는 하와이의 토란 요리를 뜻하더군요.

우리나라말로 하니 자카르타 토란 프로젝트 쯤 될라나? ㅎㅎ

 

 

II. 다운로드 및 설치

 

다운로드 받으러 갑시다~!

http://jakarta.apache.org/site/downloads/downloads_poi.cgi

현재 2.5.1버젼입니다.

다운받은 파일을 압축을 풀면 *.jar 파일들이 있을겁니다 이 파일들을 자신의 어플리케이션 /lib/에 복사합시다

 

POI API http://jakarta.apache.org/poi/apidocs/index.html

Quick Guide http://jakarta.apache.org/poi/hssf/quick-guide.html

 

 

III. Formula(수식) 지원에 관해..

 

엑셀을 읽고 쓸때 수식을 지원합니다. 
org.apache.poi.hssf.usermodel.HSSFCell의 setCellFormula("formulaString") 메쏘드는 스프레드시트에 수식을 추가하는데 사용되며 getCellFormula() 메쏘드는 수식을 대표하는 문자열을 해석하는데 사용됩니다. 하지만 엑셀에서 사용하는 수식을 모두 사용 할 수는 없습니다.

 

 지원되는 부분
-. 셀 참조, 시트참조, 지역참조
-. 상대적 혹은 절대적 참조 
-. 수연산 및 논리연산
-. 시트 혹은 매크로 함수

-. 수식 결과값 반환

 

 부분적 지원
문자열을 포함하는 수식을 해석할 수는 있지만 문자열값을 반환하는 수식은 아직 지원하지 않습니다.

 지원되지 않는 부분

-. 배열 수식 
-. 1진법 수식
-. 3D 참조
-. 에러 값 (cells containing #REF's or #VALUE's)


 

IV. 기본객체


가장 기본이되는 객체가 다음 4가지 입니다

이름에서 무엇을 뜻하는지 대강 짐작 할 수 있겠죵?

 

 HSSFWorkbook - 엑셀 워크북을 말합니다.
 HSSFSheet - 엑셀 쉬트를 나타냅니다.
 HSSFRow - 엑셀에서 특정 행입니다.
 HSSFCell - 엑셀에서 특정 행에대한 특정 셀입니다

 

위 4가지 객체는 앞으로 계속 나올겁니다. 눈여겨 미리 봐 둡시다. @.@

 

 

V. 엑셀 읽기 예제

 

① POSFS을 이용하여 엑셀 워크북을 생성합니다.

 

POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("excelfile.xls"));
HSSFWorkbook workbook = new HSSFWorkbook(fs);

 

 

 생성된 워크북을 이용하여 시트 수만큼 돌면서 엑셀 시트 하나씩을 생성합니다.

 

int sheetNum = workbook.getNumberOfSheets();

for (int k = 0; k < sheetNum; k++) {
   System.out.println("Sheet Number : "+k);

   System.out.println(Sheet Name : " + workbook.getSheetName(k));
   HSSFSheet sheet = workbook.getSheetAt(k);

}

 

 

 생성된 시트를 이용하여 그 행의 수만큼 돌면서 행을 하나씩 생성합니다.

 

int rows = sheet.getPhysicalNumberOfRows();

for (int r = 0; r < rows; r++) {
   HSSFRow row   = sheet.getRow(r);

   System.out.println("Row : "+row.getRowNum());

}

 

 

 역시나 생성된 행을 이용하여 그 셀의 수만큼 돌면서 셀을 하나씩 생성합니다.

 

int cells = row.getPhysicalNumberOfCells();

for (short c = 0; c < cells; c++) {              <--!! short 형입니다. 255개가 max!
    HSSFCell cell  = row.getCell(c);

    int celltype = cell.getCellType();

    ...

}

셀을 생성하여 셀 타입에 따라 처리를 해주면 끝~

 

 주의사항

만약 엑셀에서 A열에 아무런 값이 없으면 그 행은 읽지 못합니다.

행을 읽지 못하니 셀또한 처리 할 수 없습니다

 

 

VI. 엑셀읽기 샘플소스

 

샘플 데이터

 

 

 

 

 

 

 

A열은 B열에 대한 셀 타입을 나타내며 C열은 D열에대한 셀 타입을 나타냅니다.

즉 B:1 의 123456의 셀 타입은 A:1 일반 이라는 것이며 마찬가지로

D:1의 2005-02-09의 셀타입은 C:1 사용자정의로 세팅하였다는 겁니다

 

이 엑셀의 데이터를 다음 소스로 읽어 보겠습니다.

 

<%@ page
language="java"
contentType="text/html;charset=euc-kr" 
import="java.io.*,
 org.apache.poi.poifs.filesystem.POIFSFileSystem,
 org.apache.poi.hssf.record.*,
 org.apache.poi.hssf.model.*,
 org.apache.poi.hssf.usermodel.*,
 org.apache.poi.hssf.util.*" %>

 

<html>
<head><title>Read example</title></head>
<body>

<%

  String excelfile = "C:\\Tomcat 5.0\\webapps\\ROOT\\example.xls";

  try {
       POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excelfile)); 

 

       //워크북을 생성!               

       HSSFWorkbook workbook = new HSSFWorkbook(fs);

       int sheetNum = workbook.getNumberOfSheets();

 

       for (int k = 0; k < sheetNum; k++) {

 

            //시트 이름과 시트번호를 추출
%>

            <br><br>
            Sheet Number <%= k %> <br>
            Sheet Name <%= workbook.getSheetName(k) %><br>
<%
            HSSFSheet sheet = workbook.getSheetAt(k);
            int rows = sheet.getPhysicalNumberOfRows();

 

            for (int r = 0; r < rows; r++) {

 

                // 시트에 대한 행을 하나씩 추출
                HSSFRow row   = sheet.getRow(r);
                if (row != null) { 
                     int cells = row.getPhysicalNumberOfCells();
%>
                     ROW  <%= row.getRowNum() %> <%=cells%></b><br>
<%

                     for (short c = 0; c < cells; c++) {

 

                         // 행에대한 셀을 하나씩 추출하여 셀 타입에 따라 처리
                         HSSFCell cell  = row.getCell(c);
                         if (cell != null) { 
                              String value = null;

                              switch (cell.getCellType()) {

                                   case HSSFCell.CELL_TYPE_FORMULA :
                                       value = "FORMULA value=" + cell.getCellFormula();
                                        break;
                                   case HSSFCell.CELL_TYPE_NUMERIC :
                                       value = "NUMERIC value=" + cell.getNumericCellValue(); //double
                                       break;
                                  case HSSFCell.CELL_TYPE_STRING :
                                       value = "STRING value=" + cell.getStringCellValue(); //String
                                       break;
                                  case HSSFCell.CELL_TYPE_BLANK :
                                      value = null;
                                     break;
                                 case HSSFCell.CELL_TYPE_BOOLEAN :
                                     value = "BOOLEAN value=" + cell.getBooleanCellValue(); //boolean
                                    break;
                                case HSSFCell.CELL_TYPE_ERROR :
                                     value = "ERROR value=" + cell.getErrorCellValue(); // byte
                                     break;
                                default :
                             }
%>         
                          <%= "CELL col=" + cell.getCellNum() + " VALUE=" + value %> <br>
<%
                        } 
                    }
                }
            }
       }
   } catch (Exception e) {
%>
       Error occurred:  <%= e.getMessage() %>
<%   
       e.printStackTrace();
    }

%>


</body>
</html>

 

위 소스의 결과입니다.

 

Sheet Number 0 
Sheet Name 한글
ROW 0 4
CELL col=0 VALUE=STRING value=일반 
CELL col=1 VALUE=NUMERIC value=123456.0 
CELL col=2 VALUE=STRING value=사용자정의 
CELL col=3 VALUE=NUMERIC value=38392.0 
ROW 1 4
CELL col=0 VALUE=STRING value=숫자 
CELL col=1 VALUE=NUMERIC value=123456.0 
CELL col=2 VALUE=STRING value=날짜 (yy-m-d h:mm) 
CELL col=3 VALUE=NUMERIC value=38393.0 
ROW 2 4
CELL col=0 VALUE=STRING value=통화 
CELL col=1 VALUE=NUMERIC value=123456.0 
CELL col=2 VALUE=STRING value=날짜 (yy年 mm月 dd日) 
CELL col=3 VALUE=NUMERIC value=38394.0 
ROW 3 4
CELL col=0 VALUE=STRING value=텍스트 
CELL col=1 VALUE=NUMERIC value=123456.0 
CELL col=2 VALUE=STRING value=날짜 (yyyy년 mm월 dd일) 
CELL col=3 VALUE=NUMERIC value=38395.0


 

결과를 보니 사용자가 지정한 셀 타입에 관계없이

숫자관련 셀은 POI에서 모두 숫자 타입으로 인식해 버렸습니다.

날짜 역시 지정한 셀 타입에 관계없이 모두 숫자 타입으로 인식해 버리는군요!

그럼 어떻게 날짜를 제대로 표현할까요?

날짜 타입을 제대로 나타내기 위해서는 날짜 Cell에는 getDateCellValue()를 사용하면

정상적으로 처리 할 수 있습니다.

SimpleDateformat sdf = new SimpleDateformat("yyyy-MM-dd hh:mm");
String date = sdf.format(cell.getDateCellValue());

등을 이용하면 나타내고자 하는 알짜를 표현 하기 더 쉽겠지요

나머지 수식을 가져 올때도 마찬가지입니다. 이런 사항을 도표로 나타내보았습니다.

 

org.apache.poi.hssf.usermodel.HSSFCell 에는 모두 6가지의 Cell Type이 있는데,

cell.getCellType()을 하면 그 셀의 반환값을 알 수 있으며 그에 상응하는 static 필드타입은 다음과 같습니다.

 

셀타입 필드타입

함수

함수반환값
0 CELL_TYPE_NUMERIC

getNumericCellValue()

-> 숫자 타입일때

getDateCellValue()

-> 날짜 타입일때

double

 

Date

 

1 CELL_TYPE_STRING

getStringCellValue()

String
2 CELL_TYPE_FORMULA

getCellFormula()

-> 수식자체를 가져올때

getNumericCellValue()

-> 수식 반환값이 숫자일때

getStringCellValue()

-> 수식 반환값이 문자일때

String

 

double

 

String

3 CELL_TYPE_BLANK

 

 

4 CELL_TYPE_BOOLEAN

getBooleanCellValue()

boolean
5 CELL_TYPE_ERROR

getErrorCellvalue()

byte

 

이번시간에는 POI 프로젝트를 이용하여 엑셀 파일을 읽어보았습니다. 다음 시간에는 엑셀파일에 쓰는 핸드링을 해 보도록 하지요~

출처 : [기타] 블로그 집필 - 민군네집

728x90
반응형
728x90
반응형



자바를 사용하다보면 사이트에서 이런저런 요청사항들이 많이 들어오게 마련입니다..

 

특히나 엑셀에 대한 요청도 많이 들어오게되죠..

 

프레임웍중에서 이런 기능을 제공하는것들이 있는지에대해선 잘 모르겠지만...(이전 MiPlatform에서는 제공해주던데..)

 

아래 방법은 apache의 POI를 사용하여, java로 구현한 프로그램입니다.

 

API를 보다보면 수많은 인터페이스와 클래스.. 그에대한 메서드들이 있는데..

 

JXL은 사용하기 쉬운반면, 상대적으로 적은API를 제공하고, POI는 어려운반면무궁무진한 기능을 구현할수있는 API를 제공합니다.

 

또 보다보면 그렇게 어렵지도 않아요..

 

라이브러리는 마지막으로 9월에 릴리즈된버전입니다.

 

POI에 대한 자세한 설명은 poi.apache.org에 가시면 많은 자료들이 있습니다.

 

이 아래 예제는 만들어진 excel파일이 있고, 그 excel파일 안에 있는 값들을 읽는것입니다.

 

주석까지 다 달아놨으니 보기 편할겁니다..

 

아래는 소스입니다.

============================================================================================

 

 

import java.io.*;

import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.model.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.*;

public class aas{

 public aas(){
  String excelFile = "d:\\test.xls"; //excel파일의 경로와 파일명
  
  try{
   POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(excelFile)); //엑셀파일의 경로와 이름을 통해 POIFSFileSystem을 생성
   
   //워크북을 생성!
   HSSFWorkbook workbook = new HSSFWorkbook(fs); //파일에 대한 워크북을 생성
   int sheetNum = workbook.getNumberOfSheets(); //그파일의 워크시트의 수를 가져온다
   
   for(int k = 0;k < sheetNum; k++){    //시트를 돌면서 모든 데이터를 얻는다.
    //시트이름과 시트번호를 추출
    System.out.println(k);      //시트의 index를 콘솔에 출력
    System.out.println(workbook.getSheetName(k)); //시트의 이름을 콘솔에 출력
    HSSFSheet sheet = workbook.getSheetAt(k);  //한개의 시트에대한 정보를 HSSFSheet형의 변수에 담는다.
    int rows = sheet.getPhysicalNumberOfRows();  //시트별 몇개의 row가 있는지 알아낸다.
    
    for(int r= 0; r<rows;r++){
     //시트에 대한 행을 하나씩 추출
     
     HSSFRow row = sheet.getRow(r);  //한개의 시트에 몇개의 로우가 있는지 체크  
     if(row != null){    //로우가 비어있지않다면
      int cells = row.getPhysicalNumberOfCells();  //한개의 로우마다 몇개의 cell이 있는지 체크
      System.out.print(row.getRowNum());   //row의 index를 콘솔에 출력
      System.out.println(cells);     //해당 row에 대한 cell의 갯수를 콘솔에 출력
      
//      for(short c = 0; c < cells; c++){ //셀의 마지막까지 잡는다. 이 부분은 오류가있어 사용하지않는다.
      for(short c = 0; c < 5; c++){ //5개의 칸까지 잡는다.
       //행에대한 셀을 하나씩 추출하여 셀 타입에 따라 처리
       HSSFCell cell = row.getCell(c);  //cell의 index
       
//       System.out.println(row.getPhysicalNumberOfCells());
       if(cell != null){
        String value = null;
        switch(cell.getCellType()){       //셀의 type에 대해 체크하고 type을 설정해준다.
        case HSSFCell.CELL_TYPE_FORMULA:     
         value = "FORMULA value="+cell.getCellFormula();
         break;
        case HSSFCell.CELL_TYPE_NUMERIC:
         value = "NUMERIC value="+cell.getNumericCellValue();
         break;
        case HSSFCell.CELL_TYPE_STRING:
         value = "STRING value="+cell.getStringCellValue();
         break;
        case HSSFCell.CELL_TYPE_BLANK:
         value = null;
         break;
        case HSSFCell.CELL_TYPE_BOOLEAN:
         value = "BOOLEAN value="+cell.getBooleanCellValue();
         break;
        case HSSFCell.CELL_TYPE_ERROR:
         value = "ERROR value"+cell.getErrorCellValue();
         break;
         default:
        }
        
        System.out.println("CELL col="+cell.getCellNum() + " VALUE="+value); //셀에대한 값을 콘솔에 출력해준다.
        
       }
      }
     }
    }
   }
  }catch(Exception e){
   e.printStackTrace();
  }
 }
 public static void main(String[] args)throws Exception{
  aas aas = new aas();
 }//main
}//class

 

============================================================================================

 

아래는 대상 excel파일의 구조입니다.

 

 

============================================================================================

아래는 프로그램의 결과물입니다.

 

0
Sheet1
04
CELL col=0 VALUE=NUMERIC value=1.0
CELL col=1 VALUE=NUMERIC value=1.0
CELL col=2 VALUE=NUMERIC value=1.0
CELL col=3 VALUE=NUMERIC value=1.0
14
CELL col=0 VALUE=NUMERIC value=2.0
CELL col=1 VALUE=NUMERIC value=2.0
CELL col=2 VALUE=NUMERIC value=2.0
CELL col=3 VALUE=NUMERIC value=2.0
24
CELL col=0 VALUE=NUMERIC value=3.0
CELL col=1 VALUE=NUMERIC value=3.0
CELL col=2 VALUE=NUMERIC value=3.0
CELL col=3 VALUE=NUMERIC value=3.0
34
CELL col=0 VALUE=NUMERIC value=4.0
CELL col=1 VALUE=NUMERIC value=4.0
CELL col=2 VALUE=NUMERIC value=4.0
CELL col=3 VALUE=NUMERIC value=4.0
44
CELL col=0 VALUE=NUMERIC value=5.0
CELL col=1 VALUE=NUMERIC value=5.0
CELL col=2 VALUE=NUMERIC value=5.0
CELL col=3 VALUE=NUMERIC value=5.0
54
CELL col=0 VALUE=STRING value=한글1
CELL col=1 VALUE=STRING value=한글2
CELL col=2 VALUE=STRING value=한글3
CELL col=3 VALUE=STRING value=한글4
66
CELL col=0 VALUE=STRING value=null
CELL col=2 VALUE=STRING value=null
CELL col=3 VALUE=STRING value=d
CELL col=4 VALUE=STRING value= 
1
Sheet2
2
Sheet3

출처 : [직접 서술] 직접 서술

728x90
반응형
728x90
반응형
Java Servlet & JSP API 개발/코딩
제목 : Re: MIME타입은 주의해서 사용... 이렇게 하면 어떨지...
글쓴이: 이원영(javaservice) 2000/04/07 19:51:27 조회수:6814 줄수:176
[프린트]
손님:
> 우연치 않게 <제1회 한국 자바개발자 컨퍼런스>안내창을 보구 처음으로 이 사이트를
> 방문하게 됐습니다.......
> 
> 저는 현재 서블릿으로 게시판을 만들고 있는 서블릿 초보자입니다.
> 다른 기능들은 어느 정도 구현을 해놓았는데, 화일 다운로드에서 벽에 부딪히게 돼서
> 도움을 요청하게 됐습니다.
> 
> html, image(jpg/gif), text와 같은 화일 다운로드시 여타 응용 프로그램 화일처럼 
> 다운로드 창이 먼저 떠서 지정디렉토리에 직접 저장이 가능하게 하려구 하는데,
> 그냥 바루 웹상에 뿌려지게 되더군요!
> 
> 제가 알기로는 mime type과 관련이 있는거 같은데, 거의 모든 방법을 동원했지만
> 역부족이더군요.........^^
> 
> 고수님들의 아낌없는 조언을 부탁드립니다.....!!!


게시판의 첨부파일을 클릭할 시 저장토록하는 기능이 필요한가 보네요. 사실 이 부분은
해당 Content에 오른쪽 마우스를 누른 후 "대상 다른이름으로 저장" 을 선택하면 동일한
효과가 나타나죠..
근데, 게시판을 만드는 사람의 입장에서 생각해 보면, 사용자에게 일일이 "오른쪽 마우스
누르세요" 라고 할 수도 없고, 그래서 꼭 찍으면 "저장하기 창"이 나타나는 기능을 구현하고
싶어지게 됩니다.


먼저, 약간의 얘기를 해 보겠습니다.

*.txt 파일을 HTTP URL로 호출해 보면, 브라우져에 그 텍스트 내용이 나타납니다.
이는 웹서버의 MIME 타입에 다음과 같은 설정이 있기 때문입니다.

    text/plain          asc txt

(아파치라는 <apache>/conf/mime.typs 파일입니다. 웹서버마다 조금씩 설정방법이 다릅니다.)

또, *.exe 파일을 HTTP URL로 호출하면 "저장하기" 창이 나타납니다. 이는 MIME 타입이 아래
처럼 설정되어 있기 때문입니다.

    application/octet-stream    bin dms lha lzh exe class


서버측에서 MIME 타입이 결정나면, 웹서버는 HTTP Protocol 상의 HEADER 부분에 그 MIME을
먼저 보내고, BODY부분의 실제 데이타를 보내게 되죠.
또한 브라우져는 넘어오는 HEADER부분을 읽어서 뒤따라오는 DATA의 형식을 판단하게 됩니다.
서버에서 MIME 타입을 설정할 수 있듯이 브라우져에도 마찬가지로 MIME에 대한 적절한 반응을
어떻게 하라라는 부분이 있습니다. 대부분의 사용자는 Install할 때의 Default로 그냥 사용하죠


만약 웹서버의 MIME 타입을 약간 고쳐 보면 어떻게 될 까요? 예를 들어 아래와 같은 부분이
기본적으로 설정되어 있을 겁니다.

    text/plain          asc txt
    application/octet-stream    bin dms lha lzh exe class

여기서 txt 라는 확장자에 대한 MIME 타입을 바꾸어 보겠습니다.    

    text/plain          asc
    application/octet-stream    bin dms lha lzh exe class txt

이렇게 저장하고 웹서버를 내렸다 다시 올린 후, 브라우져에서 호출해 보면, 기존에 *.txt파일이
브라우져에서 그냥 나타났는데, 이젠 "저장하기" 창이 나타나 저장할 수 있을 겁니다.


문제는 *.txt 정도는 이렇게 할 수 있겠는데, *.html, *.gif, *.jpg 조차 바꾸어버리면 어떻게
될까요? 빈대잡으려다 초가삼간 다 태우는 격으로, 웹페이지의 모든 *.html 을 읽으려고 하면
브라우져에 나타나지 않고, "저장하기" 창만 무성하게 나타나게 되죠.

따라서 웹서버의 MIME 타입은 알려지지 않은 특정 확장자에 대해 추가적으로 조심스럽게
등록시켜 주는 정도로 사용해야 합니다. (예: *.java, *.jar, *.cpp )
저 같은 경우 *.jar 를 tar 파일과 동일하게 등록시켜뒀습니다.

    application/x-tar       tar jar

이렇게 함으로써, *.jar 파일을 클릭하면, 압축프로그램이 있다면 그 압축프로그램을 실행 할
것이고, 없다면, 저장하려 하겠죠. 만약 jar 파일에 MIME 타입을 등록시켜주지 않은 상태에서
*.jar 파일을 클릭하면 브라우져에 이상한 글자들로 막 채워 질거예요. 등록되지 않은 MIME 
타입은 기본적으로 text/plain으로 인식하거든요.

따라서 *.html, *.gif, *.jpg 등 첨부파일의 링크를 클릭했을 때, 곧바로 저장하도록 하는
방법은 단순히 MIME 타입만 변경한다고 모든 문제가 해결되지는 않아요. 오히려 엉뚱한
문제를 야기하게 되죠...

그럼 어떻게 해야 하느냐...
자바로 하기 전에 UNIX ShellScript로 CGI를 만들어 설명토록 하겠습니다.

파일로 저장되게 하는 방법은 (누군지도 모르는 PC사용자 브라우져의 MIME 타입을 강제로
변경할 방법은 없고, 결국, 서버에서 MIME 타입이 "application/octet-stream" 로 정의해서
넘겨 주는 수 밖에 없습니다. 기본적으로 브라우져는 "application/octet-stream"에 대해선
저장하도록 반응 하니까요.

(임의의 MIME 타입을 하나 만들어 보낼 수도 있습니다. 브라우져는 이해할 수 없는 MIME 타입에
대해 최초에 저장하겠느냐, 혹은 특정 어플리케이션과 연결하겠느냐 라고 묻거든요. 그러나 이건
바람직한 방법은 아니예요. 그 사람이 실수로 엉뚱한 어플리케이션과 한번 연결하면, 수동으로
고치지 않는 한 계속 그 어플리케이션이 열리게 되니까요. 어쨌거나...)

MIME 타입에 대한 얘기는 아래의 RF1521 을 보시면 잘 설명되어 있습니다
   http://freesoft.org/CIE/RFC/1521/
또, 우리가 관심이 있는 "appliction/octet-stream" 형의 MIME 타입은 아래에 설명되어 있습니다.
   http://freesoft.org/CIE/RFC/1521/32.htm

여기서 관심이 있는 부분만 보면, 만약 웹서버에서 브라우져로 데이타가 아래와 같은 형식으로
Stream이 넘어 오면 "저장하기"창이 뜬다는 것입니다.

---------------------------------------------------------------------
Content-Type: application/octet-stream
Content-Disposition: filename=hello.txt
          <---!! 반드시 빈줄이 하나이상 있어야 함
@#$#@VSGVEY#$%YVRYTY#BY$EV$%GV#YY$%YCFFW$%Y$C$%CYF#$%YT$%Y#$V$YV$#%YVW$
$%WVRV$%ER$%FV$%#TTRYBY%EYB%UR&UIIIYNUBAS$B%^&#*&$#NN#^Q@^!FTR@!^NB^@F
@^BY^E%^YG#V&^@&G@V^!BN*#*#(HBHH&RTV$%WV#$^%F^F#$@V#W$ETCF#$TRF#T#V$TC
^BTYHE$CWERWF#FCYT@$B&IM(*OP>&()P^KR*(I#G!DW%#%FGTEY@F%@D$%@D%%D@%DQ%
@^BTR#$C#RE#FDDW$R@FVTW#$TF#TFW$T@FC#$TCFV
---------------------------------------------------------------------

이제 이러한 일을 하는 Shell Script도 된 CGI 프로그램을 하나 짜볼까요?
이 CGI를 호출하면 file 파라메터로 넘어온 파일을 읽어 브라우져에서 저장시켜주는
역할을 하게 됩니다.

--------------------------------------------------------------
javaservice:/# cd /usr/local/apache/cgi-bin
javaservice:/usr/local/apache/cgi-bin# cat file.cgi
#!/bin/sh
filename=$QUERY_STRING
echo "Content-Type: application/octet-stream"
echo "Content-Disposition: filename=$filename"
echo ""
cat $filename

javaservice:/usr/local/apache/cgi-bin# chmod 755 file.cgi
javaservice:/usr/local/apache/cgi-bin# cat hello.txt
안녕하세요? 이 텍스트 파일은 브라우져에서 
저장하기 창이 팍 생겨 저장할 수 있을 거예요.
프히히....

--------------------------------------------------------------

이제, netscape를 이용해 다음 URL을 클릭해 보세요.

     http://javaservice.net/cgi-bin/file.cgi?hello.txt


NOTE: 그러나 Netscape에선 잘 동작하는 데, IE는 너무 smart(!)해서인지
      BODY 부분이 텍스트랍시고, 그냥 브라우져에 뿌려버리네요... 
      Netscape에선 잘 됩니다.

결국, 브라우져는 "아항, MIME 타입이 appliction/octet-stream 이구낭...
음, 파일이름은 'Content-Disposition: filename=' 다음에 있는 걸로 하란 소리군.."
라고 파싱을 하게 됩니다.


이러한 일련의 일을 해 주는 것을 앞에선 CGI를 이용했지만, 동일하게 자바서블렛을
이용해서도 가능합니다.
이 부분은 서블렛을 아시니 직접 해보시지요...


PS: 본 게시판도 그냥 오른쪽 마우스를 눌러 "다른 이름으로 대상 저장"를 선택하도록
    되어 있습니다. 작은 기능엔 별로 신경쓰고 싶지 않군요...
    그냥 첨부파일 링크 바로 위에 "오른쪽 마우스를 눌러 대상저장하기를 하세요"라고
    적으시면 어떨까요?

PS2 : 이러한 부분을 잘 응용하면, DB 에서 쿼리한 Data를 "application/vnd.ms-excel"
    형의 MIME 타입으로 브라우져에게 넘겨주면 브라우져는 MS-EXCEL을 기동하여
    그 데이타를 핸들링하게 할 수도 있습니다.

-------------------------------------------------------  
  본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
  이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
  이원영(javaservice@hanmail.net)
  236-1, Hyosung-2dong, Kyeyang-gu, Inchun,
  407-042, KOREA
  Phone:(82-32)540-5243, Fax:(82-32)540-5402
  PCS:019-310-7324
================================================

제목 : 성의있는 답변에 감사드립니다!
글쓴이: 황효근(guest) 2000/04/09 16:16:16 조회수:1631 줄수:25
우선 이원영님의 성의있는 답변에 대단히 감사드립니다......!!

답변해 주신 내용은 잘 읽어봤습니다....
저에게는 아주 많은 도움이 된 거 같습니다.

잘못하면 web-server의 mimetype을 건드려서 더 큰일을 낸뻔 했군요....^^;

미처 몰랐는데, 넷스케이프에서는 원래 그 기능이 지원됐었군요?

res.setContentType("application/octet-stream")
------------------------------------------------
위 처럼 설정했을 때 말이죠!

역시 익스플로러에서는 힘든가 봅니다.(서블릿으로 무단히두 애써봤지만......음)

http://altair.chonnam.ac.kr/~his/ezboard2/ezboard.cgi?db=pds&action=list&page=1

그런데, 참고로 위 사이트 게시판에서는 익스플로러에서두
*.html, *.txt, *.jpg/gif 화일들두 다운로드 창을 띄어 주더라구요?

이게 어찌된 일인지........???

암튼 다시한번 감사드립니다.....(_ _)

 
제목 : Re: 파일다운로드 창에서 열기하면 한글이 깨짐
글쓴이: 나오(guest) 2005/08/09 15:18:33 조회수:1861 줄수:116
소스입니다.   
a.jsp 에서 href를 통해 b.jsp를 엽니다.

b.jsp 내용입니다. 
(네이버 블로그 http://blog.naver.com/popo0083/40004670769   
 짜자로니(popo0083) 님 페이지에서 얻었습니다.)
<%@ page import="java.lang.*,java.util.*, java.io.*, java.sql.*"%>
<%
	String file_name = request.getParameter("file_name");
//file_name -> C:/app/aaa/web/files/vender_file/200508/E000074_20050809_6.doc
	StringTokenizer tokenF = null ;
	tokenF = new StringTokenizer(file_name,".") ;
	int ct = tokenF.countTokens();
    String[] sType = new String[ct];
	String[] rType = new String[ct];
	if (ct > 1){
		for(int j=0; tokenF.hasMoreTokens(); j++){
			sType[j] = tokenF.nextToken();
		}
		rType[1] = sType[1];
	}
	//추가	
	if(rType[1].equals("doc")){ response.setContentType("application/msword;charset=MS949"); 
	}else if(rType[1].equals("xls")){ response.setContentType("application/x-msexcel;charset=MS949");
	}else if(rType[1].equals("pdf")){ response.setContentType("application/x-msdownload");
	}else if(rType[1].equals("ppt")){ response.setContentType("application/x-mspowerpoint");
	}else if(rType[1].equals("js")){ response.setContentType("application/x-javascript");
	}else if(rType[1].equals("zip")){ response.setContentType("application/zip");
	}else if(rType[1].equals("gif")){ response.setContentType("image/gif");
	}else if(rType[1].equals("jpeg") || rType[1].equals("jpg") || rType[1].equals("jpe")){ response.setContentType("image/jpeg");
	}else if(rType[1].equals("css")){ response.setContentType("text/css");
	}else if(rType[1].equals("html") || rType[1].equals("htm")){ response.setContentType("text/html");
	}else if(rType[1].equals("xml")){ response.setContentType("text/xml");
	}else{ response.setContentType("application/octet-stream"); 
	}

	//response.setHeader("Content-Disposition", "attachment; file_name=\""+file_name+"\";");
	response.setHeader("Content-Disposition", "attachment; file_name="+file_name+";");
	//response.setHeader("Content-Transfer-Encoding", "binary;");
	response.setHeader("Content-Transfer-Encoding", "ISO-8859-1;");
	//response.setHeader("Content-Length", ""+file.length());
	response.setHeader("Pragma", "no-cache;");
	response.setHeader("Expires", "-1;"); 

    File file = new File(file_name);


	if (file.isFile())
	{
		BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
		BufferedOutputStream outs = new BufferedOutputStream(response.getOutputStream());
		int read = 0;
		while ((read = fin.read()) != -1)
		{
			outs.write(read);
		}
		outs.close();
		fin.close();
	}

%>



==========================  추가 끝 =================================
  해서....   a.jsp에서 href된 부분을 클릭하면 박스가 나와서 열기,저장,취소가
잘 나옵니다. 열기를 클릭하면 파일형식은 제대로 보입니다. 근데 실제 열기를 수행
하면 글자들이 깨져서 보입니다. 알수 없는 글자들....

이거 어떻게 해결할수 있는지요.

환경은 resin에서 웹,어플리케이션 서버를 돌리고 있습니다.
resin.conf에서 mime를 셋팅하는 방법도 있던데요...

네이버 블로그 
http://blog.naver.com/leejs100/20009011825 에서 퍼옴

<!--MIME Type-->  
   <mime-mapping extension='.hdml' mime-type='text/x-hdml;charset=KS_C 
    _5601-1987' /> 
   <mime-mapping extension='.wbmp' mime-type='image/vnd.wap.wbmp' />  
   <mime-mapping extension='.wml' mime-type='text/vnd.wap.wml' />  
   <mime-mapping extension='.wmlc' mime-type='application/vnd.wap.wmlc '/>  
   <mime-mapping extension='.wmlsc' mime-type='application/vnd.wap.wmls
    criptc' />  
   <mime-mapping extension='.wmls' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.wmlscript' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.ws' mime-type='text/vnd.wap.wmlscript' />  
   <mime-mapping extension='.wsc' mime-type='application/vnd.wap. 
    wmlscriptc' />  
  
   <mime-mapping extension='.si9' mime-type='image/vnd.lgtwap.sis' />  
   <mime-mapping extension='.si7' mime-type='image/vnd.stiwap.sis' />  
  
   <mime-mapping extension='.nbmp' mime-type='image/nbmp' />  
   <mime-mapping extension='.sis' mime-type='image/sis' />  
   <mime-mapping extension='.si6' mime-type='image/si6' />  
   <mime-mapping extension='.toy' mime-type='image/toy' /> 
   <mime-mapping extension='.nsnd' mime-type='audio/nsnd' />  
   <mime-mapping extension='.ma1' mime-type='audio/ma1' />  
   <mime-mapping extension='.ma2' mime-type='audio/ma2' />  
   <mime-mapping extension='.pmd' mime-type='audio/pmd' />  
   <!--MIME Type--> 

이건 왑용이라서 ㅡㅡ;; j2me
저는 servlet이거든요 , j2se 저거를 resin에 추가해야한다면 좀 수정해주세요.

많은 가르침 부탁드립니다. 







728x90
반응형

+ Recent posts