[java] List 정렬하기

프로그래밍/Java 2011. 4. 6. 16:05 Posted by galad
http://ssami.tistory.com/291

정렬할 대상 List가 갖는 Info 클래스
###java;highlight: [27,28,29]
package com.omp.bp.cms.common.model;

public class CommonFileInfo implements Comparable<CommonFileInfo> {

    private String fileName;    // 파일명
    private String filePath;    // 파일경로
    private String name;        // 화면 표시용 이름

    public String getFileName() {
        return fileName;
    }
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }
    public String getFilePath() {
        return filePath;
    }
    public void setFilePath(String filePath) {
        this.filePath = filePath;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int compareTo(CommonFileInfo o) {
        return fileName.compareTo(o.getFileName());
    }
}
compartTo 메소드가 Collections를 이용해 정렬할 때 사용된다.
Info 클래스의 구성원 중 하나만 가지고 비교할 때는 Comparable를 구현하는 방법을 사용하고,
여러 개의 구성원 중 선택해서 정렬하는 방식을 원할 때는 맨 위의 링크를 참고.

정렬하는 메소드
###java
/**
 * 파일 정보를 목록으로 생성. 파일명 역순 정렬.
 * @param files
 * @return
 */
private List<CommonFileInfo> getFileInfos(File[] files) {

    List<CommonFileInfo> list = new ArrayList<CommonFileInfo>();

    for(File f : files) {
        CommonFileInfo info = new CommonFileInfo();
        info.setName(f.getName());
        info.setFileName(f.getName());
        info.setFilePath(f.getAbsolutePath());

        list.add(info);
    }

    Collections.sort(list);        // 정렬
    Collections.reverse(list);    // 역순

    return list;
}

http://nogun.tistory.com/64

컴을 바꿔서 소스를 옮기고 확인해봤더니 BASE64Decoder 사용한 곳에서 모두 에러 발생.
구글링 결과, 위와 같다는 군...

나도 따라서 간단한게 이클립스 설정을 변경 ㅡ.ㅡ;;
http://nogun.tistory.com/65

'프로그래밍 > Java' 카테고리의 다른 글

[java] List 정렬하기  (0) 2011.04.06
[java/펌] Java Character Set의 이해  (0) 2010.11.11
[zip] 압축하기3  (0) 2010.10.11
[zip] 압축하기2  (0) 2010.10.08
[zip] zip 압축하기/압축풀기  (0) 2010.10.08
http://kin.naver.com/knowhow/detail.nhn?docId=527939


현재 일하는 업무 상 String의 Code page를 변환해야 하는 작업이 많다.

 

하지만 이에 관한 자료들이 매우 미흡하며 잘못된 지식을 전달하는 블로그나 웹도 많이 보아왔다.

(처음에 그것이 잘못된 것인지도 몰랐지만)

 

그리고 믿고 사용했지만 여전히 깨져버리는 한글을 보며 고민하기도 했다.

 

사실 DB모니터링 툴 개발 업무를 하다보니 Character Set을 직접 변환해야 하는 작업들이 꽤 많았다.

 

Java에선 과연 어떤 형태로 변환작업을 수행할 수 있으면 읽을 수 있을까 고민도 했다.

 

이 글이 조금은 어려울 수도 있지만 천천히 읽어본다면 충분히 이해할 수 있고 명확하게 java의

 

캐릭터 셋에 대해 알 수 있을 것이다.

 

 영문은 대부분의 캐릭터셋이 1바이트기 때문에 변환작업에서 깨질일이 거의 없다고 할 수 있지만

 

한글은 utf-8의 경우 1에서 4바이트까지의 가변형으로 저장되기 때문에 1글자의 바이트 길이가 달라

 

명시적인 변환이 요구된다.

 

여기저기 자료도 많이 찾아봤지만 역시나 테스트 하는 것이 가장 빠르게 이해할 수 있었다.

 

결론 부터 언급하면 String 객체내 바이트 배열이 어떤 캐릭터셋으로 저장될 것이라는 생각이 오해를 불러왔고

 

잘못된 사고를 하게 했다. String이 실제 메모리 상에 어떠한 캐릭터셋의 바이트 배열로 저장되어 있는지

 

사용자들은 고민할 필요도 없이 자바는 잘 되어 있었다.

 

Jdk 1.4를 기준으로 내 머리의 이해를 도와봤다.

 

내 이름 한민호라는 세자를 utf-8로 byte 배열에 저장해보았다.

 

막무가내로 시작했지만 getBytes라는 함수가 어떻게 이용되는지 알 수 있었다.

 

byte [] bytes = new String("한민호").getBytes("utf-8");

 

처음 이 코드를 작성하고 "한민호"라는 객체는 어떤 캐릭터 셋의 바이트 배열로 저장되어 있을까 생각했지만

 

그것을 생각하면서 이미 정상적인 사고를 하기가 어려웠다. 자바에선 String 객체로 생성되었다면 어떠한 종류의

 

캐릭터 셋의 바이트 배열이든 리턴이 가능하기 때문이다.

 

단 한글로 생성했는데 한글을 지원하지 않는 캐릭터셋이라면 리턴한 바이트 배열의 값이 깨지게 된다.

 

 getBytes라는 메소드에 대해 전혀 알지 못했을 땐 String을 생성할 때 지정한 즉 메모리 상에 저장된

 

"한민호"라는 객체의 바이트 배열의 캐릭터 셋을 지정해줘야 되는 줄 알았다.

 

그러나 이 메소드가 내가 상상했던거 보다 훨씬 대단하다는 것을 알게 되었다.

 

 이 메소드는 현재 저장된 String값이 어떠한 캐릭터 셋으로 저장되든 상관없이

 

바이트 배열과 바이트 배열에 맞는 캐릭터 셋으로 생성만 했다면

 

java에서 한글을 지원(영문만 지원하는 캐릭터 셋은 깨지게 된다.) 하는

 

어떠한 캐릭터 셋으로든 변환하여 변환된 바이트 배열로 리턴한다.

 

 여기서 핵심은 정상적인 String 객체의 생성이라는 것이다. 아래서 정상적인 String 객체의 생성에 대해 알아보겠다.

 

 위에서 생성한 바이트 배열을 다시 String 객체로 변환해 보겠다.

 

String name = new String(bytes, "utf-8");

 

이런 식으로 변환이 가능하다. 간혹 String의 두 번째 파라메터로 넣는 캐릭터 셋을 바이트 배열의 캐릭터 셋이 아닌 다른

 

캐릭터셋을 넣어 변환하겠다는 코드를 많이 봤다. 이건 잘못된 것이다. 이 자린 바이트 배열에 저장된 바이트들의 캐릭터 셋을

 

설정하는 곳이다.

 

잘못된 변환의 사용예를 한가지 들어보겠다.

 

잘못된 변환

String convert = new String(message.getBytes("euc-kr"), "utf-8");

 

소스를 보면 message String에 저장된 문자를 getBytes를 이용하여 euc-kr라는 캐릭터셋 바이트 배열로 얻고있다.

 

분명 이것을 작성한 사람은 위 코드에서 new String(스트링배열, "euc-kr")라고 String 개체를 생성했을 것이다.

 

간단히 설명하면 euck-kr라는 캐릭터 셋으로 바이트 배열을 읽어들인 

 

다음 utf-8이라는 새로운 캐릭터셋으로 변환(?)을 시도하겠다는 것이다.

 

이것은 두 번째 파라메터에 대해 잘못된 이해를 하고 있기에 이런 코드가 가능한 것이다.

 

때문에 이렇게 변환을 하게 되면 한글이 저장된 경우 같은 계열(변환가능한)의 캐릭터 셋이 아니라면 100프로 깨지게 된다.

 

이러한 변환은 자바에서 지원을 안하는 사항이다.

 

또 문제는 다시 String 객체로 생성을 한다는 것이다. 이 때 String생성 시 잘못된 캐릭터 셋을 주었기 때문에 깨진

 

바이트 배열로 저장이 되게 된다. 때문에 이러한 경우 getBytes() 메소드를 통해 어떠한 캐릭터 셋으로 읽든

 

읽을 수가 없게 된다.

 

 그렇다면 이제까지의 사항들에 대해 테스트를 통해 명확히 알아보겠다.

 

아래는 테스트에 자주 사용될 byte 배열을 16진수로 보여주는 함수다.

 

public static String BinToHex(byte [] buf) {
  String res = "";
  String token = "";
  for (int ix=0; ix<buf.length; ix++) {
   token = Integer.toHexString(buf[ix]);
//   CommonUtil.println("[" + ix + "] token value : " + token + " len : " + token.length());
   if (token.length() >= 2)
    token = token.substring(token.length()-2);
   else {
    for(int jx=0; jx<2-token.length();jx++)
     token = "0" + token;
   }     
   res += " " + token;
  }
  
  return res.toUpperCase();
 }

 

< 테스트 소스 >

1   String name = new String("한민호");   
2   strs = name.getBytes();   
3   System.out.println("Length : " + strs.length);
4   System.out.println("Hex    : " + BinToHex(strs));
5   System.out.println("Value  : " + new String(strs));
6   System.out.println();   
7   strs = name.getBytes("utf-8");
8   System.out.println("Length : " + strs.length);
9   System.out.println("Hex    : " + BinToHex(strs));
10   System.out.println("Value  : " + new String(strs, "utf-8") );
11   System.out.println();   
12  name = new String(strs, "utf-8");
13   strs = name.getBytes();
14   System.out.println("Length : " + strs.length);
15   System.out.println("Hex    : " + BinToHex(strs));
16   System.out.println("Value  : " + name);   
17   System.out.println();   
18   String convert = new String(name.getBytes("euc-kr"), "utf-8");
19   System.out.println(convert);
20   strs = convert.getBytes();
21   System.out.println("Length : " + strs.length);
22   System.out.println("euc-kr Hex    : " + BinToHex(strs));
23   strs = convert.getBytes("utf-8");
24   System.out.println("Length : " + strs.length);
25   System.out.println("utf-8 Hex    : " + BinToHex(strs)); 
26   System.out.println();
27   System.out.println();

 

테스트 코드를 보며 이 결과들이 어떻게 나올것이라고 예측했는데 그것이 맞아떨어지지 않는다면

 

다시 글을 보면서 이해하면된다.

 

결과는 아래와 같다.

 

< 결과 >

Length : 6
Hex    :  C7 D1 B9 CE C8 A3
Value  : 한민호

Length : 9
Hex    :  ED 95 9C EB AF BC ED 98 B8
Value  : 한민호

Length : 6
Hex    :  C7 D1 B9 CE C8 A3
Value  : 한민호

????
Length : 4
euc-kr Hex    :  3F 3F 3F 3F
Length : 10
utf-8 Hex    :  EF BF BD D1 B9 EF BF BD C8 A3

 

1번 라인을 보면 한민호라는 String객체를 생성하고 있다

 

이 객체를 strs라는 바이트 배열에 getBytes()를 이용해서 받는다. getBytes에 아무 파라메터도 주지 않는다면

 

이것은 디폴트 캐릭터셋으로 바이트 배열이 리턴된다.

 

디폴트 캐릭터셋은 System.getProperty("file.encoding") 메소드를 통해 알수 있다.

 

이것을 utf-8로 저장하는 로직이 7번 라인이다. 단지 getBytes에 utf-8이란 파라메터를 주고 utf-8 캐릭터 셋의

 

바이트 배열을 받아 올 수 있다.

 

그리고 12번 라인은 이 utf-8로 저장된 바이트 배열을 다시 String객체로 파라메터 값으로 "utf-8"을 주고 생성한 것이다.

 

이때 파라메터를 주지 않거나(디폴트 파라메터가 지정됨) 다른 캐릭터셋을 준다면 깨지게 된다.

 

마지막으로 18번 라인은 잘못된 컨버팅 예이다. euc-kr을 utf-8로 변환하겠다는 건데

 

위에서 설명했듯 이러한 변환 때문에 바이트 배열이 깨져서 euc-kr이든 utf-8이든 어떠한 바이트 배열로 읽어오든

 

깨져있는 것을 확인할 수 있다. 이미 깨져서 생성된 String 객체의 바이트 배열은 어떻게든 복구가 불가능 하다.

 

<결론>

 이야기를 종합해보면 String 객체로 생성된 것을 다른 캐릭터 셋의 String 객체로 변환한다는 것은

 

어불성설인 것이다. 이러한 변환은 무지에서 나오는 것이며 String 객체에 이미 깨진 내용은 어떠한 변환이 있더라도

 

정상적인 출력이 불가능하다는 것이다. 캐릭터셋을 포함하여 관리하겠다면 철저하게 바이트 배열을 이용해야 한다.

 

그리고 String에 어떤 캐릭터 셋으로 저장되어 있는지에 대해 논하는 것은 애초부터 잘못된 것이다.

java에서 replaceAll 함수를 이용하여 문자열 내의 태그 제거하기

    /**
     * 주어진 문자열에서 태그를 모두 제거한다.
     * @param str 원본 문자열
     * @param replacement 대체할 문자열
     * @return
     */
    public static String replaceTag(String str, String replacement) {

        // <로 시작. /가 0번 또는 1번 나옴. (a-zA-Z문자가 0번 이상)이 한 묶음.
        // (\s 공백문자. a-Z문자가 0번 이상. = 나옴. > 제외한 문자 0번 이상.)이 한 묶음으로 0번 또는 1번 나옴. <- 태그 다음 공백부터 > 전까지. ==> 속성
        // 공백 0번 이상. /가 0번 또는 1번. >로 끝.
        // ex) <a href="www.naver.com" title="title" >NAVER</a>
        return str.replaceAll("<(/)?([a-zA-Z]*)(\\s[a-zA-Z]*=[^>]*)?(\\s)*(/)?>", replacement);
    }

    /**
     * 주어진 문자열에서 a 태그를 제외한 태그를 모두 제거한다.
     * @param str 원본 문자열
     * @param replacement 대체할 문자열
     * @return
     */
    public static String replaceTagExceptA(String str, String replacement) {

        // /aA 또는 aA가 아닌 것으로 시작하는 모든 태그
        return str.replaceAll("<(?!(/[aA])|([aA])).([a-zA-Z]*)(\\s[a-zA-Z]*=[^>]*)?(\\s)*(/)?>", replacement);
    }

?! 사용해야 하는 걸 알아내느라 애먹었다.
참고: http://nosyu.pe.kr/1139

(?<=.....) : 긍정형 룩비하인드 - 하위 표현식(..... 부분)이 왼쪽에 매치될 때
(?<!.....) : 부정형 룩비하인드 - 하위 표현식(..... 부분)이 왼쪽에 매치되지 않을 때
(?=.....) : 긍정형 룩어헤드 - 하위 표현식(..... 부분)이 오른쪽에 매치될 때
(?!.....) : 부정형 룩어헤드 - 하위 표현식(..... 부분)이 오른쪽에 매치되지 않을 때

(?!(/[aA])|([aA])). 에서와 같이 /a /A 또는 a A 와 매치하지 않는 것을 찾아내는 정규표현식임.

[zip] 압축하기3

프로그래밍/Java 2010. 10. 11. 16:39 Posted by galad
        // 압축 처리
        // 압축대상 폴더명을 압축에서 제외.
        // dirPath = /data/drm
        // zipPath = /data/drm/book
        // 압축 푼 디렉토리 = /data/drm/book
        // book 디렉토리를 대상으로 압축 시, 기본적으로는 book 디렉토리가 포함되어 압축되나
        // sourcePath를 한 depth 안쪽, 즉 zipPath로 지정하면 book 디렉토리를 제외한 상태로 압축된다.
        // (압축 시 압축대상 파일의 절대경로 - sourcePath의 경로)로 파일명 처리하므로, sourcePath를 조정하면 압축대상 디렉토리 제외 가능
        // 기존 압축파일 = book/내에 모든 파일. zipPath를 sourcePath로 하는 압축파일 = /모든 파일
//     zipEntry(dirPath, sourceFile, dirPath, zfileNm);
        zipEntry(zipPath, sourceFile, dirPath, zfileNm);


    /**
     * 압축 대상 파일이나 폴더를 압축 파일에 추가하여 압축한다.
     * 만일 넘겨 받은 파일이 폴더라면 하위 디렉토리 압축을 위해 재귀함수 호출로 처리한다.
     * @param sourcePath 압축할 디렉토리 또는 파일이 위치한 경로. 즉 압축대상의 부모의 경로 / 예) D:\APIs\
     * @param sourceFile 압축할 디렉토리명 또는 이름 / 예) D:\APIs\ 내의 압축대상 j2sdk-1_4_2-doc
     * @param targetDir 압축한 zip 파일을 위치시킬 디렉토리 경로와 이름 / 예) D:\APIs
     * @param zipOutputStream Zip출력스트림 - 압축할 zip 파일에 대한 zip출력스트림. / 예) D:\APIs\zipModuleTest.zip
     * @throws Exception
     */
    private static void zipEntry(String sourcePath,
                                File sourceFile,
                                String targetDir,
                                ZipOutputStream zipOutputStream) throws Exception{

        // 만일 디렉토리명이 .metadata라면 처리하지 않고 skip한다.
        if (sourceFile.isDirectory()) {
            if(sourceFile.getName().equalsIgnoreCase(".metadata")) {
                return;
            }

            File[] fileArray = sourceFile.listFiles();
            for(int i = 0; i < fileArray.length; i++) { // 디렉토리면 디렉토리 내 파일 목록을 가지고 재귀호출
                zipEntry(sourcePath, fileArray[i], targetDir,zipOutputStream);
            }
        } else {
            BufferedInputStream inputStream = null;
            byte[] buffer = new byte[BUFFER_SIZE];
            try {
                if (sourceFile.getAbsolutePath().equalsIgnoreCase(targetDir)) {
                    return;
                }

                String strAbsPath = sourceFile.getPath(); // 압축대상 파일의 절대경로

                // 압축대상 파일의 절대경로에서 원본경로를 제외한 경로를 추출
                // ex) /test/test.xml 에서 test.xml을 압축하면 sourcePath = /test/,
                // 압축대상의 절대경로는 /test/test.xml 이므로 zipEntryName은 test.xml 이 된다.
                // ex2) 만약 디렉토리 내의 파일을 압축하면(디렉토리도 압축에 포함됨), /test/dir/test.xml 에서 dir 을 압축하면
                // sourePath = /test/, 압축대상의 절대경로는 /test/dir/test.xml 이므로 zipEntryName은 dir/test.xml 이 된다.
                // 이 상태로 압축하면 압축파일 내에 dir 디렉토리도 생성됨.
                // sourcePath를 조절해서 압축대상 dir도 제외가능
                String strZipEntryName = strAbsPath.substring(sourcePath.length() + 1, strAbsPath.length());

                inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
                ZipEntry zentry = new ZipEntry(strZipEntryName);
                zentry.setTime(sourceFile.lastModified());
                zipOutputStream.putNextEntry(zentry);

                int cnt =0;
                while ( (cnt = inputStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
                    zipOutputStream.write(buffer, 0, cnt);
                }

                zipOutputStream.closeEntry();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                if (inputStream != null) {
                    inputStream.close();
                }
            }
        }
    }

    /**
     * 압축 대상 파일이나 폴더를 압축 파일에 추가하여 압축한다.
     * @param sourcePath 압축할 디렉토리 또는 파일이 위치한 경로. 즉 압축대상의 부모의 경로 / 예) D:\APIs\
     * @param sourceFile 압축할 디렉토리명 또는 이름 / 예) D:\APIs\ 내의 압축대상 j2sdk-1_4_2-doc
     * @param targetDir 압축한 zip 파일을 위치시킬 디렉토리 경로와 이름 / 예) D:\APIs
     * @param zipFileName zip파일명
     * @throws Exception
     */
    private static void zipEntry(String sourcePath,
                                    File sourceFile,
                                    String targetDir,
                                    String zipFileName) throws Exception {

        // java.util.zip.ZipOutputStream을 사용하면 압축시 한글 파일명은 깨지는 버그가 발생
        // 집출력 스트림에 집파일을 넣는다.
        ZipOutputStream zoutput = new ZipOutputStream((OutputStream) new FileOutputStream(new File(zipFileName)));

        zipEntry(sourcePath, sourceFile, targetDir, zoutput);

        if(zoutput != null)
            zoutput.close();
    }


[zip] 압축하기2

프로그래밍/Java 2010. 10. 8. 17:34 Posted by galad
아래 내용으로는 뭔가 부족해서 검색중에 발견. http://tjsoftware.tistory.com/6
훨씬 깔끔하고 좋다...

다만 주석 내용이 소스랑 다른 부분이 있어서 그 부분 주석 수정 및 기타 주석을 추가했음.
zipEntry() 이외는 직접 작성.

        // 폴더 안에 있는 파일들을 파일 배열 객체로 가져온다.
        File[] fileArray = sourceFile.listFiles();

        // 압축할 파일 이름
        String zfileNm = filePath + ".zip";
        int num = 1;
        while (new File(zfileNm).exists()) { // 압축할 파일 명이 존재한다면 다른 이름으로 파일명을 생성
            zfileNm = filePath + "_" + num++ + ".zip";
        }
        System.out.println("Zip File Path and Name : " + zfileNm);

        // Zip 파일을 만든다.
        File zfile = new File(zfileNm);

        // Zip 파일 객체를 출력 스트림에 넣는다.
        foutput = new FileOutputStream(zfile);

        // 집출력 스트림에 집파일을 넣는다.
        zoutput = new ZipOutputStream((OutputStream)foutput);

        long beginTime = System.currentTimeMillis();

        // 실제 압축 처리
        zipEntry(dirPath, sourceFile, dirPath, zoutput);

        if (zoutput != null) {
            zoutput.close();
        }
        if (foutput != null) {
            foutput.close();
        }

        long msec = System.currentTimeMillis() - beginTime;

        System.out.println("Check :: >> " + msec/1000 + "." + (msec % 1000) + " sec. elapsed...");

    /**
     * 압축 대상 파일이나 폴더를 압축 파일에 추가하여 압축한다.
     * 만일 넘겨 받은 파일이 폴더라면 하위 디렉토리 압축을 위해 재귀함수 호출로 처리한다.
     * @param sourcePath 압축할 디렉토리/파일의 경로 / 예) D:\APIs\
     * @param sourceFile 압축할 디렉토리 경로와 이름 / 예) D:\APIs\ 내의 압축대상 j2sdk-1_4_2-doc
     * @param targetDir 압축한 zip 파일을 위치시킬 디렉토리 경로와 이름 / 예) D:\APIs
     * @param zipOutputStream Zip출력스트림 - 압축할 zip 파일에 대한 zip출력스트림. / 예) D:\APIs\zipModuleTest.zip
     * @throws Exception
     */
    private static void zipEntry(String sourcePath,
                                File sourceFile,
                                String targetDir,
                                ZipOutputStream zipOutputStream) throws Exception{

        // 만일 디렉토리명이 .metadata라면 처리하지 않고 skip한다.
        if (sourceFile.isDirectory()) {
            if(sourceFile.getName().equalsIgnoreCase(".metadata")) {
                return;
            }

            File[] fileArray = sourceFile.listFiles();
            for(int i = 0; i < fileArray.length; i++) { // 디렉토리면 디렉토리 내 파일 목록을 가지고 재귀호출
                zipEntry(sourcePath, fileArray[i], targetDir,zipOutputStream);
            }
        } else {
            BufferedInputStream inputStream = null;
            byte[] buffer = new byte[BUFFER_SIZE];
            try {
                if (sourceFile.getAbsolutePath().equalsIgnoreCase(targetDir)) {
                    return;
                }

                String strAbsPath = sourceFile.getPath(); // 압축대상 파일의 절대경로

                // 압축대상 파일의 절대경로에서 원본경로를 제외한 경로를 추출
                // ex) /test/test.xml 에서 test.xml을 압축하면 sourcePath = /test/, 압축대상의 절대경로는 /test/test.xml 이므로
                // zipEntryName은 test.xml 이 된다.
                // ex2) 만약 디렉토리 내의 파일을 압축하면(디렉토리도 압축에 포함됨), /test/dir/test.xml 에서 dir 을 압축하면
                // sourePath = /test/, 압축대상의 절대경로는 /test/dir/test.xml 이므로 zipEntryName은 dir/test.xml 이 된다.
                // 이 상태로 압축하면 압축파일 내에 dir 디렉토리도 생성됨.
                String strZipEntryName = strAbsPath.substring(sourcePath.length() + 1, strAbsPath.length());

                inputStream = new BufferedInputStream(new FileInputStream(sourceFile));
                ZipEntry zentry = new ZipEntry(strZipEntryName);
                zentry.setTime(sourceFile.lastModified());
                zipOutputStream.putNextEntry(zentry);

                int cnt =0;
                while ( (cnt = inputStream.read(buffer, 0, BUFFER_SIZE)) != -1) {
                    zipOutputStream.write(buffer, 0, cnt);
                }

                zipOutputStream.closeEntry();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                if (inputStream != null) {
                    inputStream.close();
                }
            }
        }
    }

체크 포인트
1. ZipEntry 생성 시 디렉토리명/파일명 으로 생성하면, 압축 시 디렉토리도 같이 생성됨.
2. zipEntry(dirPath, sourceFile, dirPath, zoutput)
 
- dirPath : 압축 대상(디렉토리/파일)의 부모 디렉토리의 경로
 - sourceFile : 압축 대상 디렉토리 혹은 파일. File class
 - targetDir : 압축된 zip 파일이 위치할 디렉토리 경로. 특별히 필요는 없는 듯
 - zipoutput : 실제 압축될 zip 파일. ZipOutputStream class.
> 예를 들어, c:\test\test\test.xml 이 있고 c:\test\test 를 c:\test\test.zip 으로 압축한다고 하면
 dirPath = c:\test\
 sourceFile = new File(c:\test\).listFiles() 
 targetDir = c:\test\
 zipoutput = new ZipOutputStream((OutputStream)new FileOutputStream(c:\test\test.zip))
3. stream close 하는 것 까먹지 말 것. zip 파일을 못 열게됨.

'프로그래밍 > Java' 카테고리의 다른 글

[java/펌] Java Character Set의 이해  (0) 2010.11.11
[zip] 압축하기3  (0) 2010.10.11
[zip] zip 압축하기/압축풀기  (0) 2010.10.08
[java] zip 파일 압축풀기  (0) 2010.09.28
[java] String, StringBuffer, StringBuilder  (0) 2010.09.28

[zip] zip 압축하기/압축풀기

프로그래밍/Java 2010. 10. 8. 15:36 Posted by galad
http://kwaknu.egloos.com/4989599
http://yeon97.egloos.com/1551569
http://sourceforge.net/projects/jazzlib/

아래 내용은 위의 伏地不動 님의 블로그에서 복사한 글입니다.
오직 저장의 목적으로만 사용함을 밝힙니다.

import system.log.Logger;
import system.exception.Exception;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;


/**
 * Created by IntelliJ IDEA.
 * Date: 2006. 7. 6
 * Time: 오후 3:48:11
 * To change this template use File | Settings | File Templates.

 * java.util.zip에 있는 놈을 쓰게 되면 압축할 때 한글명으로 된 파일은 깨져서 들어간다..

 * 결국 그때문에 나중에 압축을 풀때 에러가 나게 된다...

 * 해서 이놈을 jazzlib 라이브러리를 사용하여 해결하였다....
 */

public class compressTest {
    static Logger logger = (Logger)Logger.getLogger();
    static final int COMPRESSION_LEVEL = 8;
    static final int BUFFER_SIZE = 64*1024;


    public static void main(String[] args) throws IOException {
        // 압축할 폴더를 설정한다.
        String targetDir = "D:\\test\\testest";
        // 현재 시간을 설정한다.
        long beginTime = System.currentTimeMillis();
        int cnt;
        byte[] buffer = new byte[BUFFER_SIZE];
        FileInputStream finput = null;
        FileOutputStream foutput;


        /*
         **********************************************************************************
         * java.util.zip.ZipOutputStream을 사용하면 압축시 한글 파일명은 깨지는 버그가

         * 발생합니다.
         * 이것은 나중에 그 압축 파일을 해제할 때 계속 한글 파일명이 깨는 에러가 됩니다.
         * 현재 Sun의 공식 입장은 이 버그를 향후 수정할 계획이 없다고 하며
         * 자체적으로 공식적 버그라고 인정하고 있지 않습니다.
         * 이런 비영어권의 설움...ㅠ.ㅠ
         * 해서 이 문제를 해결한 net.sf.jazzlib.ZipOutputStream을 추가하오니

         * 이 라이브러리 사용을 권장하는 바입니다.
         *********************************************************************************/
        net.sf.jazzlib.ZipOutputStream zoutput;


        /*
         ********************************************
         * 압축할 폴더명을 얻는다. : 절대 경로가 넘어올 경우 --> 상대경로로 변경한다...
         *********************************************/
        targetDir.replace('\\', File.separatorChar);
        targetDir.replace('/', File.separatorChar);
        String dirNm = targetDir.substring(targetDir.lastIndexOf(File.separatorChar)+1

                                                        , targetDir.length());

        // 압축할 폴더를 파일 객체로 생성한다.
        File file = new File(targetDir);
        String filePath = file.getAbsolutePath();
        logger.debug("File Path : " + file.getAbsolutePath());


        /*
         **************************************************************************
         * 폴더인지 파일인지 확인한다...
         * 만약 넘겨받은 인자가 파일이면 그 파일의 상위 디렉토리를 타겟으로 하여 압축한다.
         *****************************************************************************/
        if (file.isDirectory()) {
            logger.debug("Directory.........");
        } else {
            file = new File(file.getParent());
        }

        // 폴더 안에 있는 파일들을 파일 배열 객체로 가져온다.
        File[] fileArray = file.listFiles();


        /*
         *****************************************************************
         * 압축할 파일 이름을 정한다.
         * 압축할 파일 명이 존재한다면 다른 이름으로 파일명을 생성한다.
         *****************************************************************/
        String zfileNm = filePath + ".zip";
        int num = 1;
        while (new File(zfileNm).exists()) {
            zfileNm = filePath + "_" + num++ + ".zip";
        }

        logger.debug("Zip File Path and Name : " + zfileNm);

        // Zip 파일을 만든다.
        File zfile = new File(zfileNm);
        // Zip 파일 객체를 출력 스트림에 넣는다.
        foutput = new FileOutputStream(zfile);

        // 집출력 스트림에 집파일을 넣는다.
        zoutput = new net.sf.jazzlib.ZipOutputStream((OutputStream)foutput);

        net.sf.jazzlib.ZipEntry zentry = null;


        try {
            for (int i=0; i < fileArray.length; i++) {
                // 압축할 파일 배열 중 하나를 꺼내서 입력 스트림에 넣는다.
                finput = new FileInputStream(fileArray[i]);

                // ze = new net.sf.jazzlib.ZipEntry ( inFile[i].getName());
                zentry = new net.sf.jazzlib.ZipEntry(fileArray[i].getName());

                logger.debug("Target File Name for Compression : "

                                    + fileArray[i].getName()

                                    + ", File Size : "

                                    + finput.available());

                zoutput.putNextEntry(zentry);


                /*
                 ****************************************************************
                 * 압축 레벨을 정하는것인데 9는 가장 높은 압축률을 나타냅니다.
                 * 그 대신 속도는 젤 느립니다. 디폴트는 8입니다.
                 *****************************************************************/
                zoutput.setLevel(COMPRESSION_LEVEL);

                cnt = 0;
                while ((cnt = finput.read(buffer)) != -1) {
                    zoutput.write(buffer, 0, cnt);
                }

                finput.close();
                zoutput.closeEntry();
            }
            zoutput.close();
            foutput.close();
        } catch (Exception e) {
            logger.fatal("Compression Error : " + e.toString());
            /*
             **********************************************
             * 압축이 실패했을 경우 압축 파일을 삭제한다.
             ***********************************************/
            logger.error(zfile.toString() + " : 압축이 실패하여 파일을 삭제합니다...");
            if (!zfile.delete()) {
                logger.error(zfile.toString() + " : 파일 삭제가 실패하여 다시 삭제합니다...");
                while(!zfile.delete()) {
                    logger.error(zfile.toString() + " : 삭제가 실패하여 다시 삭제합니다....");
                }
            }
            e.printStackTrace();
            throw new Exception(e);
        } finally {
            if (finput != null) {
                finput.close();
            }
            if (zoutput != null) {
                zoutput.close();
            }
            if (foutput != null) {
                foutput.close();
            }
        }

        long msec = System.currentTimeMillis() - beginTime;

        logger.debug("Check :: >> " + msec/1000 + "." + (msec % 1000) + " sec. elapsed...");
    }
}


'프로그래밍 > Java' 카테고리의 다른 글

[zip] 압축하기3  (0) 2010.10.11
[zip] 압축하기2  (0) 2010.10.08
[java] zip 파일 압축풀기  (0) 2010.09.28
[java] String, StringBuffer, StringBuilder  (0) 2010.09.28
[junit] 멀티스레드 테스트  (0) 2010.09.27

[java] zip 파일 압축풀기

프로그래밍/Java 2010. 9. 28. 20:07 Posted by galad
    /**
     * 넘겨받은 zip파일이 위치한 디렉토리에 zip 파일을 풀고, zip파일 내의 파일 목록(파일명)을 반환한다.
     * @param zipFilePath
     * @return zip파일에 들어있던 파일path 목록
     * @throws IOException
     */
    public static List<String> unzip(File file) throws IOException {

        List<String> fileList = new ArrayList<String>();

        // zip 파일 압축 해제
        ZipFile zipFile = new ZipFile(file,"EUC-KR");
        Enumeration entries = zipFile.getEntries();

        String zipFilePath = file.getPath();
        String orgDirPath = zipFilePath.substring(0, zipFilePath.lastIndexOf(File.separator));

        while(entries.hasMoreElements()) {

            ZipEntry zipEntry = (ZipEntry)entries.nextElement();
            String entryFileName = zipEntry.getName();

            System.out.println("File in Zip = " + entryFileName);

            if(zipEntry.isDirectory()) {
                (new File(orgDirPath + File.separator + entryFileName)).mkdir(); // 디렉토리 생성
                continue;
            }
            else {

                String[] tmpSplit = null; // 폴더 채로 압축하면, 폴더 내의 파일명은 [폴더명/폴더명/파일명] 이런 식으로 됨.

                try
                {
                    tmpSplit   = entryFileName.split(File.separator);
                }
                catch(Exception e)
                {
//                    tmpSplit = entryFileName.split("\\\\");
                    tmpSplit = entryFileName.split("/");
                }

                if(tmpSplit.length > 1)
                {
                    String tmpDir = "";
                    for(int j = 0; j < tmpSplit.length - 1; j++) // 파일이 여러 depth의 폴더 내에 있는 경우. 폴더/폴더/폴더/파일
                        tmpDir += (tmpSplit[j] + File.separator); // 상위의 모든 폴더명 붙이기

                    tmpDir = orgDirPath + File.separator + tmpDir; // zip 파일이 위치한 디렉토리에 압축된 디렉토리 생성

                    File tmpFile = new File(tmpDir);
                    if(!tmpFile.exists())
                        tmpFile.mkdir();
                }

                // 대상 파일
                String targetFilePath = orgDirPath + File.separator + entryFileName;

                // 파일 복사
                copyInputStream(zipFile.getInputStream(zipEntry), new BufferedOutputStream(new FileOutputStream(targetFilePath)));
//                System.out.println("FILE [" + entryFileName + "] COPIED TO " + orgDirPath);

                fileList.add(entryFileName);
            }
        }

        if(zipFile != null) // 열은 zip 파일 닫기
            zipFile.close();

        return fileList;
    }

    /**
     * 파일을 stream으로 읽어들여 대상 outputStream에 복사하는 메소드
     * @param in
     * @param out
     * @throws IOException
     */
    private static final void copyInputStream(InputStream in, OutputStream out) throws IOException
    {
        byte[] buffer = new byte[1024];
        int len;

        while ((len = in.read(buffer)) >= 0)
            out.write(buffer, 0, len);

        in.close();
        out.close();
    }


'프로그래밍 > Java' 카테고리의 다른 글

[zip] 압축하기2  (0) 2010.10.08
[zip] zip 압축하기/압축풀기  (0) 2010.10.08
[java] String, StringBuffer, StringBuilder  (0) 2010.09.28
[junit] 멀티스레드 테스트  (0) 2010.09.27
[jar] jar 압축하기/해제하기  (0) 2010.09.10
참고: http://cacky.tistory.com/36
http://iolothebard.tistory.com/291

일단, StringBuffer랑 StringBuilder

StringBuffer와 StringBuilder의 유일한 차이점은, StringBuffer가 동기화(synchronized)되고, StringBuilder는 동기화되지 않는(unsynchronized) 란다.
따라서, 프로그램이 단일 쓰레드 환경(single thread)에서 동작해야 한다면 StringBuilder를 쓰는 것이 StringBuffer보다 더 효율적(efficient)이다.

자세한 것은 링크 참조...
참고: http://www.yunsobi.com/tt/subby/99
참고: http://decoder.tistory.com/37

첨부된 파일은 검색에서 나온 것으로 문제 있으면 삭제하겠습니다.

package com.omp.bp.cms.batchreg.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.log4j.Logger;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;

import com.omp.bp.cms.batchreg.BatchRegisterErrorConstants;
import com.omp.bp.cms.util.DateUtil;

/**
 * 배치 등록 관련 에러 로그 처리 클래스. 콘텐츠 하나에 대한 에러로그XML 생성.
 * @author Sung,HongJe
 *
 */
public class BatchRegisterError {

    private final static Logger log = Logger.getLogger(BatchRegisterError.class);

    private final String ERROR_FILE_NAME_HEADER = "ERROR_";
    private final String ERROR_FILE_EXT = "XML";

    /**
     * 에러 로그 파일 생성
     * @param ftpRepoPath ftp 디렉토리 패스
     * @param contentId 콘텐츠ID
     * @param contentType 콘텐츠타입 - C:채널, E:콘텐츠(에피소드)
     * @param errorCode 에러코드
     * @throws IOException
     */
    public void makeErrorLog(String ftpRepoPath, String contentId, String contentType, int errorCode) throws IOException {

        // 1. ERROR 파일패스 설정 : ftpRepo/ERROR_[TYPE]_[CID].XML
        // 2. 에러 코드를 이용해서 XML 내용 설정
        // 3. 파일로 저장

        // ftpRepo/ERROR_C_000050151.XML
        String filePath = ftpRepoPath + File.separator + ERROR_FILE_NAME_HEADER + contentType.toUpperCase() + "_" + contentId + "." + ERROR_FILE_EXT;
        String errorMsg = BatchRegisterErrorConstants.getErrorMsg(errorCode);

        // XML 내용 생성
        Document xmlDoc = makeErrorXML(contentId, errorCode, errorMsg, DateUtil.getToday() + DateUtil.getTime());

        File file = new File(filePath);
        FileOutputStream out = null;

        try {

            if(!file.exists()) { // 로그 파일 없으면 생성

                File dir = new File(ftpRepoPath); // ftp 디렉토리가 없으면 생성
                if(!dir.exists())
                    dir.mkdir();

                file.createNewFile();
            }

            out = new FileOutputStream(file);
            XMLOutputter serializer = new XMLOutputter();
            serializer.output(xmlDoc, out);
            out.flush();
        }
        catch (IOException e) {

            log.error("BatchRegisterError.makeErrorLog 로그 파일 작성 중 예외 발생", e);
            throw e;
        }
        finally {

            if(out != null) {

                try {

                    out.close();
                }
                catch (IOException e) {

                    log.error("BatchRegisterError.makeErrorLog 로그 파일 작성 종료 중 예외 발생", e);
                }
            }
        }
    }

    /**
     * 에러 메시지를 담는 XML을 생성 후 반환
     * @param contentId
     * @param errorCode
     * @param errorMsg
     * @param dateTime
     * @return
     */
    private Document makeErrorXML(String contentId, int errorCode, String errorMsg, String dateTime) {

        Document doc = new Document();

        Element error_log = new Element("error_log"); // root

        Element content_id = new Element("content_id");
        content_id.setAttribute("id", contentId); // set CID

        Element msg = new Element("msg");
        msg.setText(errorMsg);

        Element code = new Element("code");
        code.setText(String.valueOf(errorCode));

        Element time = new Element("time");
        time.setText(DateUtil.getToday() + DateUtil.getTime());

        content_id.addContent(msg);
        content_id.addContent(code);
        content_id.addContent(time);

        error_log.addContent(content_id);

        doc.addContent(error_log);

        return doc;
    }
}


볼드체를 참고하기

[java] 이미지 리사이즈

프로그래밍/Java 2010. 7. 23. 14:58 Posted by galad
ImageIO, BufferedImage 사용

private static BufferedImage createResizedCopy(Image originalImage, int scaledWidth, int scaledHeight, boolean preserveAlpha) {
       
        int imageType = preserveAlpha ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
       
        BufferedImage scaledBI = new BufferedImage(scaledWidth, scaledHeight, imageType);
        Graphics2D g = scaledBI.createGraphics();
        if (preserveAlpha) {
                g.setComposite(AlphaComposite.Src);
        }
        g.drawImage(originalImage, 0, 0, scaledWidth, scaledHeight, null);
        g.dispose();
       
        return scaledBI;
    }
   
    /**
     * 이미지 리사이즈
     * @param srcFile 원본 이미지
     * @param destFile 리사이즈 이미지
     * @param width 리사이즈될 가로 길이
     * @param height 리사이즈될 세로 길이
     * @param imageType 리사이즈될 이미지 타입(PNG/JPG 등)
     * @param preserveAlpha 투명화 여부
     * @throws IOException
     */
    public static void resizeImage(File srcFile, File destFile, int width, int height, String imageType, boolean preserveAlpha) throws IOException   {
       
        BufferedImage originalImage = ImageIO.read(srcFile);
        BufferedImage resizedImage = createResizedCopy(originalImage, width, height, preserveAlpha);
        ImageIO.write(resizedImage, imageType, destFile);
       
//        System.out.println(ImageIO.getReaderFormatNames().toString());
//        System.out.println(ImageIO.getWriterFormatNames().toString());
    }


'프로그래밍 > Java' 카테고리의 다른 글

[jar] jar 압축하기/해제하기  (0) 2010.09.10
[java] byte 단위로 문자열 잘라내기  (1) 2010.08.06
[java] 소수점 자리수 / 천단위 콤마  (0) 2010.05.18
[java] Convert Milliseconds to Date  (0) 2010.03.15
[java] invoke  (0) 2010.03.09
소수점 자리수
천단위 콤마

double s = files[i].length();
s = s / 1024 / 1024;
DecimalFormat df = new DecimalFormat("###.##");
String size = df.format(s) + "MB"; // 사이즈

###.## 에서 정수부분 #의 개수는 출력에 영향을 미치지 않음.
3개만 있어도 4자리 이상도 출력됨.

public static void main(String[] args) {
    NumberFormat nf = NumberFormat.getNumberInstance();
    System.out.println(nf.format(2500000));
    System.out.println(nf.format(2500000.23));
    
    NumberFormat pf = NumberFormat.getPercentInstance();
    System.out.println(pf.format(1));
    System.out.println(pf.format(0.25));
    System.out.println(pf.format(0.2535)); 
}

>>>
2,500,000
2,500,000.23
100%
25%
25%



'프로그래밍 > Java' 카테고리의 다른 글

[java] byte 단위로 문자열 잘라내기  (1) 2010.08.06
[java] 이미지 리사이즈  (0) 2010.07.23
[java] Convert Milliseconds to Date  (0) 2010.03.15
[java] invoke  (0) 2010.03.09
[java] getClass, getMethod, invoke  (0) 2010.01.22

[java] invoke

프로그래밍/Java 2010. 3. 9. 11:01 Posted by galad
String metaField = ProductConstant.FIELD_NAME_FOR_HD_DRM;
Class[] cParam = new Class[]{String.class}; // 메소드 얻을 때 사용할 파라미터 타입. 메소드명, 파라미터갯수 및 종류로 해당 메소드를 찾는다
Object[] oParam = new Object[]{hdProductDrmYn}; // 실제 invoke 시 사용할 파라미터값

Class cls = pi.getClass(); // 메소드를 invoke할 클래스

// 메소드 얻기 getMethod(메소드명, 파라미터타입) : get 메소드면 파라미터 필요없음
Method cMtd = cls.getMethod("set" + metaField.substring(0, 1).toUpperCase() + metaField.substring(1), cParam);

// invoke(invoke할 객체, 파라미터)
cMtd.invoke(pi, oParam);

'프로그래밍 > Java' 카테고리의 다른 글

[java] 소수점 자리수 / 천단위 콤마  (0) 2010.05.18
[java] Convert Milliseconds to Date  (0) 2010.03.15
[java] getClass, getMethod, invoke  (0) 2010.01.22
[java] Pattern / Matcher  (0) 2010.01.22
[java] 파일 관련  (0) 2010.01.07

[java] getClass, getMethod, invoke

프로그래밍/Java 2010. 1. 22. 15:22 Posted by galad
public static void setAllowedTypes(FileUploadInfo info, SubContentInfo sinfo) throws ContentException {
    log.debug("<< setAllowedTypes >> START");

    Class cls = info.getClass();
    Class scls = sinfo.getClass();
    Method[] mtd = cls.getDeclaredMethods(); // cls에 선언된 모든 메소드를 반환
    Pattern p = Pattern.compile("get_fileUpload_(\\d+)FileName"); // 패턴 설정. \d+ 는 정수 하나 이상(정규식)
    Matcher m = null;
    String mStr = null;
    String mType = null;
    String defExt = null;
    int i;

    for(i = 0; i < mtd.length; i++) { // 모든 메소드만큼 돌면서
        m = p.matcher(mtd[i].getName()); // 메소드명과 패턴을 비교
        if(m.find()) { // 매칭된 것이 발견되면
            try {
                // group으로 매칭된 내용(메소드명)을 받아서 그 메소드를 실행. 파일명을 얻음.
                mStr = FileUploadInfo.getValueOfMethod(info, m.group());
                if(mStr != null) { // 파일명이 존재하는 경우만
                    // group(1)으로 매칭된 번호를 얻어서 메소드 실행. 콘텐트 타입을 얻음.
                    mType = FileUploadInfo.getValueOfMethod(info, "get_fileUpload_" + m.group(1) + "ContentType");
                    // 기본 확장자 지정
                    defExt = "";
                    if(mType != null) {
                        defExt = mStr.substring(mStr.lastIndexOf(".") + 1);
                        defExt = defExt.toLowerCase().trim();
                       
                        log.debug("defExt = " + defExt);
                       
                        if("jpg".equals(defExt) ||
                           "gif".equals(defExt) ||
                           "xml".equals(defExt) ||
                           "xmp".equals(defExt) ||
                           "png".equals(defExt) ||
                           "zip".equals(defExt) ) {
                            // 진행
                        }else {
                            // 오류 발생
                            throw new ContentException("지원하지 않는 파일입니다.");
                        }
                    }
                   
                    Class[] cParam = new Class[]{String.class};
                    // 메소드를 찾는데, 메소드명이 "set...."이고 cParam형식을 파라미터로 갖는 메소드를 반환. null이면 파라미터 없는 메소드
                    // cParam이 Class 배열인 것은 파라미터가 여럿인 메소드가 있기 때문에.
                    // 여기서는 String을 파라미터로 갖는 set_fileUp.... 메소드를 반환.
                    Method cMtd = cls.getMethod("set_fileUpload_" + m.group(1) + "FileName", cParam);
                    Object[] oParam = new Object[]{mStr};
                    // FileUploadInfo에 등록
                    cMtd.invoke(info, oParam); // info의 set_fileUpload_XFileName 메소드를 실행. 파라미터는 oParam
                    // SubContentInfo에 등록
                    // 1. FileUPloadInfo의 FieldName을 찾는다.
                    cMtd = cls.getMethod("get_fileUpload_" + m.group(1) + "FieldName", null);
                    String tmpFieldName = (String)cMtd.invoke(info, null); // 업로드 파일명을 저장할 대상 필드명을 얻어서
                    // 2. SubContentInfo의 의 1번의 Method에 등록한다.
                    cMtd = scls.getMethod("set" + tmpFieldName.substring(0, 1).toUpperCase() + tmpFieldName.substring(1)  , cParam);
                    cMtd.invoke(sinfo, oParam); // 서브콘텐츠info에 저장함.

                }
            }
            catch (ContentException e) {
                log.debug("지원하지 않는 파일 예외 발생", e);
                throw e;
            }
            catch (Exception e) {
                    e.printStackTrace();
            }
        }
    }

}

public static String getValueOfMethod(Object obj, String methodName)
        throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    String str = "";
    Class cls = obj.getClass();
    Method mtd = cls.getMethod(methodName, null); // 넘겨받은 오브젝트의 클래스의 메소드를 얻어서
    str = (String)mtd.invoke(obj, null); // 메소드를 실행시킴.
    // 이때 파라미터로 받은 오브젝트는 메소드가 실행될 대상 오브젝트. 즉, obj의 메소드 mtd를 실행함.

    return str;
}

동적으로 움직이는 기능을 만들기 위해서는 필수적.

'프로그래밍 > Java' 카테고리의 다른 글

[java] Convert Milliseconds to Date  (0) 2010.03.15
[java] invoke  (0) 2010.03.09
[java] Pattern / Matcher  (0) 2010.01.22
[java] 파일 관련  (0) 2010.01.07
[java] thorws .....  (0) 2009.12.11

[java] Pattern / Matcher

프로그래밍/Java 2010. 1. 22. 15:02 Posted by galad
public class MatcherTest {

    /**
     */
    @Test
    public void testMatcher() {
        //Method[] mtd = cls.getDeclaredMethods(); // cls에 선언된 모든 메소드를 반환
        String mtd = "get_fileUpload_0FileName";
        Pattern p = Pattern.compile("get_fileUpload_(\\d+)(FileName)"); // 패턴 설정. \d+ 는 정수 하나 이상(정규식)
        Matcher m = null;
       
        m = p.matcher(mtd);
        if(m.find()) {
            System.out.println(m.group()); // matcher에서 매칭된 것 전체를 반환
            System.out.println(m.group(0)); // group() 과 같음.
            System.out.println(m.group(1)); // matcher에서 매칭된 것 중, pattern에서 첫 번째 ()로 묶인 것을 반환. 결과는 "0"
            System.out.println(m.group(2)); // matcher에서 매칭된 것 중, pattern에서 첫 번째 ()로 묶인 것을 반환. 결과는 "FileName"
        }
    }
}

Pattern.complie 과 정규식으로 패턴 설정.
matcher 로 그 매칭 결과를 받은 후, group 으로 매칭된 내용을 확인

'프로그래밍 > Java' 카테고리의 다른 글

[java] invoke  (0) 2010.03.09
[java] getClass, getMethod, invoke  (0) 2010.01.22
[java] 파일 관련  (0) 2010.01.07
[java] thorws .....  (0) 2009.12.11
[java] 소스 분석  (0) 2009.09.06

[java] 파일 관련

프로그래밍/Java 2010. 1. 7. 14:16 Posted by galad
출처: http://wearekorean.co.kr/zbxe/645

1. File 객체로 작업하기

        1> File 객체의 정의

                 * File객체는 하드디스크에 존재하는 실제 파일이나 디렉토리가 아니고 그것에 대한 경로(Pathname) 또는 참조(reFerence)를 추상화한 객체이다. 파일 객체는 새 파일에  대한 경로나 만들고자하는 디렉토리를 캡슐화한 것이다.

        2> File 객체의 용도

                 * 물리적 파일 시스템에 대해 캡슐화한 경로명을 확인하고 실제의 파일이나 디렉토리와 대응되는지 알아볼 때.

                 * 파일 스트림객체를 생성하고자 할 때.


2.  File 객체 생성하기

        1>File 객체를 생성하는 데에는 네 개의 생성자를 사용할 수 있다.

                * 인자로 String 객체를 전달하는 것.

                       File mtDir - new File("c:/j2SDK 1.4.0/src/java/io");

                       File 클래스의 생성자는 인자로 전달된 경로를 확인하지 않는다 .

                       File 클래스의 생성자로 어떤 문자열을 넘겨도 된다는 것을 알 수 있다.

                       File 객체는 불변적이므로 객체를 생성하고 나면 그것이 가진 경로를 바꿀 수 없다

                * 첫번째 인자로 부모 디렉토리를 가진 File객체 전달, 두번째 인자로 String객체 전달.

                  부모 디렉토리 - 해당 파일을 가지고 있는 디렉토리.

                * 첫번째 인자로 부모 디렉토리의 경로를 String객체로 전달, 두번째 인자로 String객체  전달.

                * URL이용.

        2>경로에 대한 이식성을 고려

                * 경로 이름을 만드는 것은 시스템에 의존적이지만 File 클래스의 separator 변수를 사용함으로써 좀 더 시스템에 독립적으로 myFile에 대한 경로를 지정 가능.

        3>절대경로와 상대경로

                * 절대 경로 : 접두사(c:\, c://)를 포함하는 경로.

                  ex) cd c:\java\API 이런 식의 경로 이동을 하는 방법이 절대 경로.

                * 상대 경로 : 접두사가 없는 경로.

                  ex) cd java 이런 식의 경로 이동을 하는 방법이 상대 경로.

        4>시스템 속성에 접근하기

                * 파일에 대한 상대 경로를 지정하는 것이 시스템 독립적이긴 하지만 현재의 환경에 독립적인 경로를 지정하고자 하는데, 현재 디렉토리 또는 현재 디렉토리의 하위 디렉토리는 데이터 파일을 저장하기에 적합하지 않은 상황도 있을 수 있다. 이런 경우에 시스템 속성에 접근하는 것이 도움이 될 수 있다.


3. File 객체를 확인하고 테스트하기

        1> File 객체에 대한 정보를 얻을 수 있는 메서드

                getName() - 경로를 제외한 파일의 이름. 즉, 경로의 가장 마지막 부분을 String 객체로 리턴한다.

                getPath() - 파일이나 디렉토리 이름을 포함한 File 객체의 경로를 String으로 리턴한다.

                isAbsolute() - File 객체가 절대경로를 참조하고 있다면 true, 아니라면 false를 리턴한다.

                getParent() - 현재 File 객체가 나태내는 파일 EH는 디렉토리의 부모 디렉토리의 이름을 String으로 리턴한다. 이때 리턴되는 경로는 파일 이름을 포함하지 않은 순수한 경로명이다. 만약 File 객체가 현재 디렉토리에서 단순히 파일 이름만을 사용해서 만들어져 부모 디렉토리가 명시되어 있지 않을 경우에는 null을 리턴한다.

                toString() - 현재 File 객체의 String표현을 리턴하며 File 객체가 String 객체로 변환될 필요가 있을 때 자동으로 호출된다.

                hashCode() - 현재 File 객체의 해시코드 값을 리턴한다.

                equals() - 두 개의 File 객체가 동일한 것인지 비교할 때 사용되는 메소드이다. 인자로 넘겨지는 File 객체가 현재의 객체와 같은 경로를 가지고 있으면 true를 그렇지 않으면 false를 리턴한다.

        2> File 객체가 참조하는 파일이나 디렉토리를 테스트하기 위한 메서드

                exist() - File 객체가 참조하는 파일 또는 디렉토리가 실제로 존재하면 true를, 그렇지않으면 false를 리턴한다.

                isDirectory() - File 객체가 디렉토리를 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                isFile() - File 객체가 파일를 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                isHidden() - File 객체가 숨김 속성이 있는 파일을 참조하는 경우 true를, 그렇지 않으면 false를 리턴한다.

                canRead() - File 객체가 참조하는 파일 또는 디렉토리를 읽을 권한이 있다면 true를, 없다면 false를 리턴한다. 만약 권한이 없는데 읽으려고 시도하면 SecurityException이 발생한다.

                canWrite() - File 객체가 참조하는 파일 또는 디렉토리에 쓰기 권한이 있다면 true를, 없다면 false를 리턴한다. 만약 권한이 없는데 읽으려고 시도하면 SecurityException이 발생한다.

                getAbsolutePath() - 현재의 File 객체가 참조하는 파일 또는 디렉토리의 절대경로를 리턴한다. 만약 객체가 절대경로를 포함하고 있다면 getPath() 메소드에 의해 리턴되는 것과 동일한 문자열을 리턴할 것이다. 그렇지  않다면 윈도우즈 환경에서는 현재 디렉토리가 나타내는 경로의 드 라이브 이름을 사용하거나 경로에 드라이브 이름이 명시되어 있지 않다면 현재 사용자 디렉토리에 대해서 절대경로가 결정된다. 유닉스 환경에서는 현재 사용자 디렉토리에 대해서 절대 경로가 결정된다.

                getAbsoluteFile() - 현재 File 객체가 참조하는 파일 또는 디렉토리의 절대경로를 포함한 File 객체를 리턴한다.

 

=======================================소스 코드=======================================

import java.io.File;

 

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

 

    // 디렉토리를 참조하는 객체 생성
    File myDir = new File("C:/javaex1");
    System.out.println(myDir + (myDir.isDirectory() ? " is" : " is not") + " a directory.");

 

    // 파일을 참조하는 객체 생성
    File myFile = new File(myDir, "TryFile3.java");
    System.out.println(myFile + (myFile.exists() ? " does" : " does not") + " exist");
    System.out.println(myFile + (myFile.isFile() ? " is" : " is not") + " a file.");
    System.out.println(myFile + (myFile.isHidden() ? " is" : " is not") + " hidden");
    System.out.println("You can" + (myFile.canRead() ? " " : "not ") + "read " + myFile);
    System.out.println("You can" + (myFile.canWrite() ? " " : "not ") + "write " + myFile);
    return;
  }

}

 


=======================================소스 코드=======================================

 

        3> 존재하는 파일 또는 디렉토리에 대해 더 많은 정보를 제공해주는 메서드

                list() - 현재 File 객체가 디렉토리를 나태내고 있다면 디렉토리 내의 파일 이름과 하위 디렉토리의 이름들을 담고 있는 String 배열이 리턴된다. 만일 디렉토리가 비어 있다면 배열도 비어있을 것이다. 또한 File 객체가 파일을 나태내고 있다면 null을 리턴할 것이다. 이 메소드는 허가되지 않은 디렉토리를 접근하려 할 경우 SecurityException을 발생시킨다.

                listFiles() - 이 메소드를 호출한 객체가 디렉토리라면, 그 디렉토리 내의 파일과 하위 디렉토리에 대응되는 File 객체 배열이 리턴된다. 빈 디렉토리라면 빈 배열이 리턴될 것이다. 호출된 객체가 디렉토리가 아니거나 입출력 오류가 발생한다면 null을 리턴할 것이다. 이 메소드는 허가되지 않은 디렉토리에 접근하려 할 때 SecurityException을 발생시킨다.

                length() - 현재 File 객체가 참조하는 파일의 길이를 바이트 단위로 표현한 long 형의 값을 리턴한다. 현재 File 객체의 경로가 존재하지 않는 파일을 참조하고 있다면 0을 리턴할 것이다. 만약 그 경로가 디렉토리를 참조한다면, 정의되지 않은 값이 리턴된다.

                lastModified() - 현재 File 객체가 나타내는 파일 또는 디렉토리가 마지막으로 수정된 시각을 나타내는 long형의 값을 리턴한다. 이때 시각은 그리니치 표준시(GMT)로 1970년 1월 1일 자정 이후로부터 지난 시간을 멀리 초 단위로 계산한 값이다. 파일이 존재하지 않는다면 0을 리턴한다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.util.Date;   // Date 클래스를 사용하기 위해 포함시킴
 
public class TryFile2 {
  public static void main(String[] args) {
 
    // 디렉토리를 참조하는 객체 생성
    File myDir = new File("C:/javaex1");
    System.out.println(myDir.getAbsolutePath()  + (myDir.isDirectory() ? " is " : " is not ") + "a directory");
    System.out.println("The parent of " + myDir.getName() + " is " + myDir.getParent());
 
    // 디렉토리 내의 파일 리스트를 얻어옴
    File[] contents = myDir.listFiles();
 
    // 파일 리스트를 출력
    if (contents != null) {
      System.out.println("\nThe " + contents.length + " items in the directory " + myDir.getName() + " are:");
      for (int i = 0; i < contents.length; i++) {
        System.out.println(contents[i] + " is a "  + (contents[i].isDirectory() ? "directory" : "file") + " last modified " 
                   + new Date(contents[i].lastModified()));
      }
    } else {
      System.out.println(myDir.getName() + " is not a directory");
    }
 
    System.exit(0);
  }
}
 

=======================================소스 코드=======================================

 

        4> 파일 리스트 필터링

                * list()와 listFiles() 메서드는 파일 리스트를 필터링하는 인자를 받도록 오버로드 되어 있다.

                * list() 메서드의 인자는 FilenameFilter 타입의 변수여야 하지만,

                * listFiles() 메서드는 FilenameFilter와FileFilter 두 가지를 모두 사용할 수 있다.

 

4. 파일과 디렉토리를 생성하고 수정하기

        File 클래스에는 그 파일을 읽기 전용으로 만들거나 이름을 바꾸는 등 물리적인 파일에 변화를 줄 수 있는 메서드가 있다. 또한 파일 또는 디렉토리를 생성하거나 삭제할 수 있게 해주는 메서드들도 있다.

                renameTo(File path) - 현재 객체가 나타내는 파일의 이름이 메소드의 인자로 전달된 File 객체가 나타내는 경로를 변경될 것이다. 이것은 프로그램에서 현재의 File 객체를 변경하는 것이 아니라 물리적인 파일을 실제로 바꾸는 것이라는 점을 주의해야 한다. 따라서 현재 File 객체가 나타내던 파일은이 메소드가 수행되고 나면 새로운 이름을 가지게 되므로 더 이상 존재하지 않을 것이며 다른 디렉토리에 위치하게 될 수도 있다. 새로운 경로에 있는 파일의 디렉토리가 원래의 것과 다르다면 파일은 새로운 디렉토리로 옮겨질 것이다. 만일 새로운 경로가 존재하지 않는 디렉토리이거나 그 곳에 쓰길을 할 수 없다면 이 메소드는 실패할 것이다. 이 메소드는 작업이 성공적으로 이루어지면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

                setReadOnly() - 현재 객체가 나타내는 파일을 읽기 전용으로 설정한다. 성공하면 true를 리턴한다.

                mkdir() - 현재의 File 객체에 의해 지정된 경로로 디렉토리를 생성한다. 이 메소는 생성하려는 디렉토리의 부모 디렉토리가 미리 존재하지 않으면 실패할 것이다. 이 메소드는 성공하면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

                mkdirs() - 현재 File 객체가 나타내는 디렉토리를 생성하며, 이때 필요한 모든 부모 디렉토리도 함께 생성한다. 새로운 디렉토리가 성공적으로 생성되었다면 true를 그렇지 않으면 false를 리턴한다. 메소드가 false를 리턴한 경우에도 부모 경로 중 일부가 생성되었을 수도 있다.

                createNewFile() - 현재 File 객체로 정의돈 경로에 비어있는 새로운 파일을 생성한다. 파일이 성공적으로 생성되면 true를 리턴한다. 경로에 지정된 디렉토리가 존재하지 않는다면 IOException 예외가 발생하고, 지정된 파일이 이미 존재한다면 실패한다.

                createTempFile(String prefix, String suffix, File directory) - 이것은 directory 디렉토리에 처음 두 개의 인자를 사용해서 생성된 이름으로 임시 파일을 생성하는 정적 메소드이고, 생성된 파일에 해당하는 File 객체를 리턴한다. 문자열 prefix는 파일 이름의 앞부분을 나타내며 최소한 세 글자 이상은 되어야 한다. 문자열 suffix는 파일의 확장자를 나타낸다. 파일 이름이 prefix와 다섯자 이상은 생성된 문자, 그리고 확장자로 이루어진다. 만약 suffix가 null이라면 확장자는 .tmp 가 될 것이다. prefix나 suffix가 현재 시스템의 파일 이름으로 쓰기에 너무 길다면 끝 부분을 잘라내고 사용하지만, 세 글자 이하로 잘라내지는 않는다. directory 인자가 null이라면 시스템의 임시 디렉토리가 사용될 것이다. 만일 파일이 생성될 수 없다면 IOEception이 발생하며 prefix가 세글자 이하라면 IllegalArgument Exception이 발생할 것이다.

                createTempFile(String prefix, String suffix) - createTempFile(String prefix, String suffix, File directory)와 동일하다.

                delete() - 현재 File 객체가 나타내고 있는 파일 또는 디렉토리를 삭제하며 성공적으로 삭제되었다면 true를 리턴한다. 이 메소드는 비어있지 않은 디렉토리는 지우지 않는다. 그러므로 디렉토리를 삭제하려면 디렉토리 내의 모든 파일을 먼저 지워야 한다.

                deleteOnExit() - 현재 File 객체가 나타내는 파일 또는 디렉토리가 프로그램이 끝날 때에 삭제 되도록 한다. 이 메소드는 값을 리턴하지 않으며, 삭제는 JVM이 정상적으로 종료될 경우에만 시도된다. 일단 File 객체에 대해서 이 메소드를 호출하면 삭제 작업은 돌이킬 수 없기 때문에 주의해서 사용해야 한다.

5. 파일 출력 스트림 생성하기

        디스크에 존재하는 물리적인 파일에 무언가 쓰고자 할 때 FileOutputStream 객체를 사용할 수 있다.

         1>FileOutputStream 객체의 다섯 개의 생성자

                FileOutputStream(String filename) - filename이라는 이름의 파일에 대한 출력 스트림을 생성한다. 파일에 이미 존재하는 내용을 덮어쓰게 된다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(String filename, boolean append) - filename이라는 이름의 파일에 대한 출려 스트림을 생성하며, 만약 append인자 값이 true이고 파일 내용이 존재한다면 그 내용 뒤에 덧붙여 쓴다. append인자 값이 false라면 이미 존재하는 파일의 내용을 덮어쓰게 된다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(File file) - File 객체가 나타내는 파일에 대한 출력스트림을 생성하며, 이미 파일 내용이 존재하면 그 내용을 덮어쓴다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(File file, boolean append) - File 객체가 나타내는 파일에 대한 출력 스트림을 생성하며, 만약 append 인자 값이 true이고 파일 내용이 이미 존재한다면 그 내용 뒤에 덧붙여 쓴다. 어떤 이유로든 파일이 열리지 않는다면 FileNotFoundException이 발생한다.

                FileOutputStream(FileDescriptor desc) - desc와 해당하는 출력 스트림을 생성한다. FileDescriptor 객체는 파일에 대해 이미 존재하고 있는 연결을 참조한다. 그래서 파일이 반드시 존재하므로 이 생성자는 FileNotFoundException이 발생한다.

  

6. 파일이 존재하는 것을 보장하기

        1> 파일이 존재하면 이 파일에 데이터를 덧붙이고 존재하지 않는 파일이면 생성하고자 할 때 파일 출력 스트림을 생성해야하는데, 여기서 확인해야 할 것들이 있다.

        2> File 객체를 사용해서 실제로 디렉토리가 아니라 파일을 나타내고 있는지 확인한다. 만일 파일이 아니라면 더 이상 진행하지 말고 오류 메시지를 출력해 주어야 한다.

        3> 그 파일이 존재하는지 확인하기 위해 File 객체를 사용한다. 파일이 존재하지 않는다면 File 객체가 절대경로를 가지고 있는지 확인해야 한다. 이것은 부모 디렉토리를 얻어오고 확인하는 데 사용된다.

        4> 부모 디렉토리에 대한 경로를 얻어오고 이것을 사용해서 다른 File 객체를 생성한다. 부모 디렉토리가 존재하는지 확인하기 위해 새로운 File 객체를 사용한다. 만약 존재하지 않는다면 File 객체의 mkdir() 메서드를 사용해서 새로 생성한다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

public class GuaranteeAFile {
  public static void main(String[] args) {
    String filename = "C:/Beg Java Stuff/Bonzo/Beanbag/myFile.txt";
    File aFile = new File(filename);    //File 객체 생성

    //경로가 파일인지를 확인
    if (aFile.isDirectory()) {

      // 오류 메세지 후에 종료함

      // 여기서 키보드로부터 입력을 받아 다시 시도하도록 할 수 있음
      System.out.println("The path " + aFile.getPath() + " does not specify a file. Program aborted.");
      System.exit(1);
    }

    // 파일이 존재하지 않을 경우
    if (!aFile.isFile()) {
      // 부모 디렉토리를 확인
      aFile = aFile.getAbsoluteFile();
      File parentDir = new File(aFile.getParent());
      if (!parentDir.exists()) {   // ... and create it if necessary
        parentDir.mkdirs();
      } 
    }

    // 스트림에 대한 참조를 저장할 장소
    FileOutputStream outputFile = null; 
    try {

      // 데이터를 추가하는데 사용될 스트림 생성
      outputFile = new FileOutputStream(aFile, true);
    } catch (FileNotFoundException e) {
      e.printStackTrace(System.err);
    } 
    System.exit(0);
  } 
}

=======================================소스 코드=======================================

 

7. 파일 덮어쓰는 것을 방지하기

        * 이미 파일이 존재할 때 그 파일을 덮어쓰고 싶을 않을 때 덮어쓰기를 막을 수 있는 방법이 있다. 저장하려는 원래 이름을 어떠한 방법으로든 바꿔준다면 그것이 덮어쓰기를 막을 수 있는 한 가지 방법이 될 수 있다.

 

=======================================소스 코드=======================================

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileNotFoundException;

 
public class AvoidOverwritingFile {
  public static void main(String[] args) {
    String filepath = "C:/Beg Java Stuff/myFile.txt";
    File aFile = new File(filepath);
    FileOutputStream outputFile = null;     // 스트림에 대한 참조를 저장할 장소
    if (aFile.isFile()) {
      File newFile = aFile;                 // 원래의 파일을 가지고 시작함
     
      // 유일한 이름이 될 때까지 파일 이름에 "_old"를 덧붙임
      do {
        String name = newFile.getName();    // 파일의 이름을 얻어옴
        int period = name.indexOf('.');         // 확장자의 구분자를 찾음
        newFile = new File(newFile.getParent(), name.substring(0, period) + "_old" + name.substring(period));
      } while (newFile.exists());             // 이름이 바뀔 때까지 반복
      aFile.renameTo(newFile);               
    }
 
    // 새로운 파일 생성
    try {
      // 데이터를 추가하기 위한 스트림 생성
      outputFile = new FileOutputStream(aFile);
      System.out.println("myFile.txt output stream created");
    } catch (FileNotFoundException e) {
      e.printStackTrace(System.err);
    } 
    System.exit(0);
  }
}
 
 

=======================================소스 코드=======================================


8. FileDescriptor 객체

        1> FileDescriptor 객체

                * FileOutputStream에는 FileDescriptor 타입의 객체를 리턴해주는 getFD() 메서드가 있다.

                * 여기서 FileDescriptor는 물리적인 파일에 대한 현재의 연결을 나타내는 객체이다.

                * 직접 FileDescriptor 객체를 생성할 수는 없고 파일 스트림을 나타내는 객체로부터 getFD() 메서드를 호출해서 FileDescriptor 객체를 얻을 수 있다

                * 스트림을 한번 닫고 나면 파일에 대한 연결이 끊어지므로 더 이상 FileDescriptor 객체를 얻을 수 없다

        2> FileDescriptor 객체 사용

                * 표준 스트림에 대응되는 바이트나 문자 스트림을 만들고자 할 때 편리하게 사용할 수 있다

 

 

<요약>


1> File클래스의 객체는 파일 또는 디렉토리의 경로를 포함한다. File 객체가 가지고 있는 경로는 물리적인 파일이나 디렉토리와 반드시 대응되어야 할 필요는 없다.

2> File 객체가 가지고 있는 경로가 실제의 파일이나 디렉토리를 참조하는지를 확인하기 위해 File객체를 사용할 수 있다. 만약 실제 파일이나 디렉토리를 참조하고 있지 않은 경우 필요한 디렉토리나 파일을 생성할 수 있는 메소드들이 있다.

3> File클래스는 임시 파일을 생성할 수 있는 정적 메소드를 가지고 있다.

4> FileDescriptor 타입의 객체도 물리적인 파일을 나타낼 수 있다.

5> FileOutputStream 객체는 File 객체로부터 생성될 수 있으며, 쓰기 위해 파일이 열린다. 만약 파일이 존재하는 않는다면 가능한 곳에 새로 생성된다.


'프로그래밍 > Java' 카테고리의 다른 글

[java] getClass, getMethod, invoke  (0) 2010.01.22
[java] Pattern / Matcher  (0) 2010.01.22
[java] thorws .....  (0) 2009.12.11
[java] 소스 분석  (0) 2009.09.06
[HttpURLConnection] POST로 파라미터 넘기기  (0) 2009.07.27

[java] thorws .....

프로그래밍/Java 2009. 12. 11. 16:53 Posted by galad
메소드 정의 시 throws 하면, 그 메소드 사용하는 부분에서 반드시 try-catch 해야한다.
메소드 구현 시에 exception을 던지든 말든지 말이지...

반대로 정의 시에 throws 안하면, 그 메소드 사용하는 부분에서 try-catch 안해도됨.
메소드에서 exception을 던지든 말든지 말이지...

기본기가 점점 사라지는 느낌.
공부 좀 하자꾸나...

[java] 소스 분석

프로그래밍/Java 2009. 9. 6. 15:19 Posted by galad
public static void setAllowedTypes(FileUploadInfo info, SubContentInfo sinfo) throws ContentException {
        log.debug("<< setAllowedTypes >> START");
       
        Class cls = info.getClass();
        Class scls = sinfo.getClass();
        Method[] mtd = cls.getDeclaredMethods();
        Pattern p = Pattern.compile("get_fileUpload_(\\d+)FileName");
        Matcher m = null;
        String mStr = null;
        String mType = null;
        String defExt = null;
        int i;
       
        for(i = 0; i < mtd.length; i++) {
            m = p.matcher(mtd[i].getName());
            if(m.find()) {
                try {
                    // 파일명이 존재하는 경우만
                    mStr = FileUploadInfo.getValueOfMethod(info, m.group());
                    if(mStr != null) {
                        mType = FileUploadInfo.getValueOfMethod(info, "get_fileUpload_" + m.group(1) + "ContentType");
                        // 기본 확장자 지정
                        defExt = "";
                        if(mType != null) {
                            defExt = mStr.substring(mStr.lastIndexOf(".") + 1);
                            defExt = defExt.toLowerCase().trim();
                           
                            log.debug("defExt = " + defExt);
                           
                            if("jpg".equals(defExt) ||
                               "gif".equals(defExt) ||
                               "xml".equals(defExt) ||
                               "xmp".equals(defExt) ||
                               "png".equals(defExt) ||
                               "zip".equals(defExt) ) {
                                // 진행
                            }else {
                                // 오류 발생
                                throw new ContentException("지원하지 않는 파일입니다.");
                            }
                        }
                       
                        Class[] cParam = new Class[]{String.class};
                        Method cMtd = cls.getMethod("set_fileUpload_" + m.group(1) + "FileName", cParam);
                        Object[] oParam = new Object[]{mStr};
                        // FileUploadInfo에 등록
                        cMtd.invoke(info, oParam); // 마찬가지로 첫번째 인자는 실행시킬 메소드를 갖고 있는 obj, 두번째는 실제 메소드의 파라미터
                        // SubContentInfo에 등록
                        // 1. FileUPloadInfo의 FieldName을 찾는다.
                        cMtd = cls.getMethod("get_fileUpload_" + m.group(1) + "FieldName", null);
                        String tmpFieldName = (String)cMtd.invoke(info, null);
                        // 2. SubContentInfo의 의 1번의 Method에 등록한다.
                        cMtd = scls.getMethod("set" + tmpFieldName.substring(0, 1).toUpperCase() + tmpFieldName.substring(1)  , cParam);
                        cMtd.invoke(sinfo, oParam);

                    }
                }
                catch (ContentException e) {
                    log.debug("지원하지 않는 파일 예외 발생", e);
                    throw e;
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
       
    }
   
public static String getValueOfMethod(Object obj, String methodName) throws SecurityException, NoSuchMethodException,                               IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        String str = "";
        Class cls = obj.getClass(); // obj의 클래스 종류를 얻고
        Method mtd = cls.getMethod(methodName, null); // 위에서 얻은 클래스의 어떤 메소드를 얻는데, 메소드명을 인자로 받음
        str = (String)mtd.invoke(obj, null); // 위에서 얻은 메소드를 실행하는데, 그 메소드를 갖고 있는 obj를 인자로 받음?
        return str;
    }

[MD5] MD5 암호화

프로그래밍/Library 2009. 3. 13. 16:52 Posted by galad
출처: http://edit.tistory.com/tag/MD5%EC%95%94%ED%98%B8%ED%99%94
        http://www.javapattern.info/50

MD5 는 해시 함수의 일종입니다..
해시 함수는.. 기본적으로 복호화를 목적으로 하지 않습니다.

http://ko.wikipedia.org/wiki/%ED%95%B4%EC%8B%9C_%ED%95%A8%EC%88%98

복호화는 불가능하다고 생각하시는게 편할 겁니다.

복호화는 안된단다... 원래 그렇게 만들어진게 아니라네...
그럼 ID/PW를 암호화할 필요가 있나?

▶ SecurityUtil.java

import java.security.*;

public class  SecurityUtil {

    /**
     * byte[] ret = HashUtil.digest("MD5", "abcd".getBytes());
     *  처럼 호출
     */
    public static byte[] digest(String alg, byte[] input) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance(alg);
        return md.digest(input);
    }

    public static String getCryptoMD5String(String inputValue) throws Exception {
        if( inputValue == null ) throw new Exception("Can't conver to Message Digest 5 String value!!");
        byte[] ret = digest("MD5", inputValue.getBytes());
        String result = Base64Util.encode(ret);  
        return result;
    }
}


위 의 클래스에 해당 스트링값을 던지게 되면 실제 digest된 결과 문자열을 되돌려 줄수 있도록 처리하였는데 이것이 끝이냐~ 아닙니다. 실제 던져진 해쉬함수에 의한 결과를 System.out으로 찍게 되면 찌그러진 코드형태로 나오게 되는데 이것을 우리 눈으로 비교하여 String문자비교를 통하여 추후 사용할 수 있도록 하려면 Base64 인코딩을 시도해야 합니다.

그 유틸리티 클래스는 아래와 같습니다.

▶ Base64Util.java

import sun.misc.*;
import java.io.*;

/**
*

* Filename  : Base64Util.java

* Class     : Base64Util   

* Function  : Base64 Encoding/Decoding을 수행하는 클래스

* Comment   :

* History    : 2000-08-16 2:48오후                    

*


* @version  1.0
* @author carouser
*/
public class Base64Util {

    public Base64Util() {}

    /**
     * Base64Encoding을 수행한다. binany in ascii out
     *
     * @param encodeBytes encoding할 byte array
     * @return encoding 된 String
     */
    public static String encode(byte[] encodeBytes) {
      
        BASE64Encoder base64Encoder = new BASE64Encoder();
        ByteArrayInputStream bin = new ByteArrayInputStream(encodeBytes);
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buf = null;

        try{
            base64Encoder.encodeBuffer(bin, bout);
        } catch(Exception e) {
            System.out.println("Exception");
            e.printStackTrace();
        }
        buf = bout.toByteArray();
        return new String(buf).trim();
    }

    /**
     * Base64Decoding 수행한다. binany out ascii in
     *
     * @param strDecode decoding할 String
     * @return decoding 된 byte array
     */
    public static byte[] decode(String strDecode) {
      
        BASE64Decoder base64Decoder = new BASE64Decoder();
        ByteArrayInputStream bin = new ByteArrayInputStream(strDecode.getBytes());
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        byte[] buf = null;

        try {
            base64Decoder.decodeBuffer(bin, bout);
        } catch(Exception e) {
            System.out.println("Exception");
            e.printStackTrace();
        }

        buf = bout.toByteArray();

        return buf;

    }
}


String passwd = SecurityUtil.getCryptoMD5String("Carouser");

'프로그래밍 > Library' 카테고리의 다른 글

[Subclipse] ignore  (0) 2009.04.02
[firebug] 파이어버그 가이드  (0) 2009.03.20
[BASE64] BASE64 인코딩  (0) 2009.02.27
[가니메데] 이클립스 가니메데에서 WTP사용하기  (0) 2009.02.03
[Cognos] 기본개념  (0) 2009.01.29
참고 : http://charmpa.egloos.com/1336665

        String RMS_URL = "http://localhost:8080/SMILE_RMS/rms/request_deploy";
        URL url = new URL(RMS_URL);
        HttpURLConnection uc = (HttpURLConnection) url.openConnection();
       
        uc.setDoInput(true);
        uc.setDoOutput(true);
        uc.setUseCaches(false);
        uc.setRequestMethod("POST");
       
        // Http Header
        String ver = "X-RMS-VER 1.0";
        String uid = "X-RMS-UID 1.0";
        String upw = "X-RMS-UPW 1.0";
        String tid = "X-RMS-TID " + System.currentTimeMillis();
        String length = msg.length()+"";
        uc.setRequestProperty("X-RMS-VER", ver);
        uc.setRequestProperty("X-RMS-UID", uid); // md5 encoded
        uc.setRequestProperty("X-RMS-UPW", upw); // md5 encoded
        uc.setRequestProperty("X-RMS-TID", tid);
        uc.setRequestProperty("Content-Length", length);
       
        // 보내기
        PrintWriter pw = new PrintWriter(uc.getOutputStream());
        pw.write(msg.toString());
        pw.flush();
        pw.close();
       
        // 받기
//        BufferedReader br = new BufferedReader(new InputStreamReader(uc.getInputStream()));
//        String str = null;
//        while((str = br.readLine()) != null) {
//            System.out.println(str);
//        }
       
        // 실질적으로 웹서버에 접속하여 요청을 보내고 응답을 수신하는 시점은 con.getResponseCode();로 판단된다.
        // getResponseCode() 를 호출하지 않으면, Network Connection 연결 요청 자체가 시도되지 않음이 확인되었다..
        // 실제로 서버로부터 아무런 정보도 받지 않더라도(현재 InputStream처리부분은 주석임), request의 결과로
        // response가 어떤지(성공/실패 등)를 받지 않으면 서버에 아무것도 보내지 않는듯.
        // 결국 서버가 request에 대한 처리를 하고 response를 주기 전까지는 대기상태. 동기화되어서 작동.
//        OutputStream out = uc.getOutputStream();// internally change to 'POST'
        int resCode = uc.getResponseCode(); // connect, send http reuqest, receive htttp request
        System.out.println ("code = "+ resCode);

'프로그래밍 > Java' 카테고리의 다른 글

[java] 소스 분석  (0) 2009.09.06
[HttpURLConnection] POST로 파라미터 넘기기  (0) 2009.07.27
CLASSPATH  (0) 2009.01.06
HttpURLConnection 사용례  (0) 2009.01.06
[펌] HttpURLConnection 을 이용하세요  (0) 2009.01.02