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

2012-10-31

JAVA] RSS Reader 만들기


** java]Http 통신 의 예제 파일 참조

javascript를 이용한 초간단 Rss Reader 구현하기 : javascript 를 이용한 초간단 Rss Reader 구현하기
참조사이트 : http://blog.naver.com/sullim75?Redirect=Log&logNo=140028752352


춣처 : http://poolpiri.egloos.com/7021118


간단한 Rss Reader 만들기...


블로그를 만들어보다가 Rss를 읽어서 웹상에서 보여주는 RssReader가 필요할꺼 같아서...
간단하게 만들어봅니다.
자카르타 오픈 컴포넌트중에 하나인 commons.digester를 이용한겁니다...그래서 간단허져...
일단 아래와 같이 간단한 메서드를 만들어봅니다.
/**
* RSSDigester를 이용해서 링크의 스트림(xml)을 파싱해서 Channel객체를 리턴한다.
*
* @param xmlLink
* @param response
* @return org.apache.commons.digester.rss.Channel
* @throws Exception
*/


private Channel getChannel(String xmlLink)
      throws Exception {
    Channel chan = null;
    try {
       RSSDigester digester = new RSSDigester();
      // 방법 1. Rss Link를 이용한 파싱...
       //chan = (Channel) digester.parse(xmlLink);
       // 방법 2. Rss Link를 URL로 연결해서 얻은 스트림으로 파싱...
       //chan = (Channel) digester.parse(new URL(xmlLink).openStream());
       // 방법 3. 국내 사이트 Character Encoding문제 때문에...추가...

       chan = (Channel) digester.parse(getEncodedReader(xmlLink));
    } catch (java.io.IOException ioe) {
       chan = new Channel();
       chan.setTitle("ERROR");
       StringBuffer sb = new StringBuffer("<span class="error">");
       sb.append("IOException parsing RSS XML LINK : " + xmlLink);
       sb.append("</span>n<p>");
       sb.append(ioe.toString());
       chan.setDescription(sb.toString());
    } catch (org.xml.sax.SAXException se) {
       chan = new Channel();
       chan.setTitle("ERROR");
       StringBuffer sb = new StringBuffer("<span class="error">");
       sb.append("SAXException parsing RSS XML LINK : " + xmlLink);
       sb.append("</span>n<p>");
       sb.append(se.toString());
       chan.setDescription(sb.toString());
    }
return chan;
}
파라미터로 와야하는 String xmlLink은 본 엠파스 블로그에 있는거같은 RSS링크 유알엘을 넣어주심 됩니다. 제 블로그를 예를 들면..."http://blog.empas.com/poolpiri3/rss.xml" 이게 들어오면 되는겁니다.
여기 예제는 엠파스에서 제공하는 rss.2.0 버전에만 잘돌아갑니당...이 버전은 웬만한 국내 RSS가 지원하는 버전입니다...

소스 중간에 있는 주석을 보시면 몇가지 방법이 있습니다만...국내 사이트의 경우 한글 인코딩 문제로 파싱이 제대로 안됩니다. 여기 엠파스도 마찬가지구여... 이럴줄 알았으면 굳이 digester를 쓰지 않고 방법을 생각했으면 더 쉬워질 수 도 있었습니다만...제가 무지한지라...하여 아래와 같은 메서드를 무식하게 추가했습니다.
/**
* xml파일의 encoding타입을 읽어서 그 타입대로 컨버전후 InputStreamReader를 리턴한다.
*
* @param xmlLink
* @return InputStreamReader
*/


private InputStreamReader getEncodedReader(String xmlLink) {
   URL url = null;
    InputStreamReader reader = null;
    BufferedReader br = null;
    try {
       url = new URL(xmlLink);
       reader = new InputStreamReader(url.openStream());
       byte b[] = new byte[1024];
       br = new BufferedReader(reader);
       String line = br.readLine();
       while (line != null) {
          if (!(line.trim().equals(""))) {
             int index = line.toLowerCase().indexOf("encoding");
             String prefix = """;
             String encoding = "";
             if (index != -1) {
                int start = line.indexOf(prefix, index) + 1;
                if (start == -1) {
                   prefix = "'";
                   start = line.indexOf(prefix, index) + 1;
                   if (start == -1) {
                     start = line.indexOf("=", index) + 1;
                     prefix = "?";
                   }
                }
             encoding = line.substring(start, line.indexOf(prefix, start));
             if (encoding != null && !("".equals(encoding))) {
                reader =  new InputStreamReader( url.openStream(),  encoding.trim());
             } else {
                reader = new InputStreamReader(url.openStream());
             }
       } else {
          reader = new InputStreamReader(url.openStream());
       }
    break;
   }
   line = br.readLine();
   }
   } catch (MalformedURLException e) {
       e.printStackTrace();
    } catch (IOException e) {
       e.printStackTrace();
    } finally {
       if (br != null) {
          try {
             br.close();
          } catch (IOException e1) {
             e1.printStackTrace();
          }
       }
    }
    return reader;
}
하여튼 이렇게 얻어진 channel를 객체를 통해서 아래와 같이 jsp에서 뿌려주심 됩니다.
<% int maxItems = 10;
if (channel != null) {
if ("ERROR".equals(channel.getTitle())) {%>

<tr bgcolor="#FFCCFF">
<td width="100" bgcolor="#CCCCFF">블로그 이름</td>
<td bgcolor="#CCFFCC"><%=channel.getDescription()%></td>
</tr>
<%return;
}%>
<% String divId = Utility.replace(channel.getTitle(), " ", "_");
divId = Utility.replace(channel.getTitle(), "'", "_");%>
<!--<%=channel.getLastBuildDate()%><%=channel.getCopyright()%><%=channel.getDocs()%><%=channel.getLanguage()%>-->

<tr bgcolor="#FFCCFF">
<td bgcolor="#CCFFCC" width="500" colspan="2" valign="bottom"><a href="<%=channel.getLink()%>" target="_blank"><h3><%=channel.getTitle()%></h3></a><br>
<%=channel.getDescription()%></td>
</tr>
<% Image image = channel.getImage();
if (image != null) {%>
<tr bgcolor="#FFFFFF">
<td colspan="2" height="50"><img src="<%=image.getURL()%>" alt="<%=image.getTitle()%>" > <!--width="<%=image.getWidth()%>" height="<%=image.getHeight()%>"-->
</td>
</tr>
<% }
Item[] items = channel.getItems();
for (int j = 0; j < items.length; j++) {
if (items[j].getTitle() != null && items[j].getLink() != null) {%>
<tr bgcolor="#FFFFFF">
<td colspan="2"><a href="<%=items[j].getLink()%>" target="_blank" class="RssLink"><%=items[j].getTitle()%></a></td>
</tr>
<% } else if (items[j].getTitle() != null) {%><tr bgcolor="#FFFFFF">
<td colspan="2"><div class="RssTitle"><%=items[j].getTitle()%></div></td>
</tr>
<% }
if (items[j].getDescription() != null) {%>
<tr bgcolor="#FFFFFF">
<td colspan="2"><div class="RssDesc"><%=items[j].getDescription()%>...</div></td>
</tr>
<% }
if (maxItems != -1 && j >= maxItems)
break;
}
} else {%>
<tr bgcolor="#FFFFFF">
<td colspan="2">블로그 리스트가 하나도 없습니다. -_-</td>
</tr>
<% }%>
흠흠...제가 봐도 어설프네여...
이렇게 하면 자기 홈페이지나 특정사이트에 기존에 IFRAME같은 방법으로 넣어줬던 다른 사이트의 특정 게시물 리스트를 RSS와 RSS Reader를 통해서 출력해줄 수 있습니다.
물론 항상 신규 리스트겠죠 또한 해당 사이트에서 RSS를 지원해야만 가능한거구여...요샌 상당수 사이트들이 지원을 하구여...
그럼...
위의 소스는 commons.digester 1.5/1.6 을 기준으로 작성 되어서 2.x에서는 RSSDigester()를 찾을 수 없었다...(2010.07.06 기준)
그래서 아래의 소스로 rss reader를 구현하게 되었다...



RssReader.java
=================================

package rss;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Scanner;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class RssReader {

    private static RssReader instance = null;
    private static String ENCODING = "UTF-8";
    static String NL = System.getProperty("line.separator");
  
    private RssReader() {
    }
  
    public static RssReader getInstance() {
        if(instance == null) {
            instance = new RssReader();  
        }
        return instance;
    }
  
    public void writeNews() {
        try {

            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
//            URL u = new URL("http://mutasyon.net/cs/blogs/hakkiocal/rss.aspx");
//            URL u = new URL("http://rss.joins.com/joins_news_list.xml");
//            URL u = new URL("http://feeds.feedburner.com/afriken");
            URL u = new URL("http://blog.rss.naver.com/jeffyang.xml");
          
            Document doc = builder.parse(u.openStream());
          
            NodeList nodes = doc.getElementsByTagName("item");
            NodeList nodeChannel = doc.getElementsByTagName("channel");
          
            for(int i=0;i<nodes.getLength();i++) {
              
                Element element = (Element)nodes.item(i);
              
                System.out.println("Title: " + getElementValue(element,"title"));
                System.out.println("Category: " + getElementValue(element,"category"));
                System.out.println("Link: " + getElementValue(element,"link"));
                System.out.println("Publish Date: " + getElementValue(element,"pubDate"));
                System.out.println("author: " + getElementValue(element,"author"));
                System.out.println("comment: " + getElementValue(element,"comments"));
                System.out.println("guid: " + getElementValue(element,"guid"));
                System.out.println("language: " + getElementValue(element,"language"));
                System.out.println("description: " + getElementValue(element,"description"));
                System.out.println();
            }//for          
        }//try
        catch(Exception ex) {
        ex.printStackTrace();  
        }
      
    }
  
    public void writeNews(String url) {
        try {
          
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

            URL u = new URL(url);
          
            Document doc = builder.parse(u.openStream());
          
            NodeList nodes = doc.getElementsByTagName("item");
          
            for(int i=0;i<nodes.getLength();i++) {
              
                Element element = (Element)nodes.item(i);
              
                System.out.println("Title: " + getElementValue(element,"title"));
                System.out.println("Category: " + getElementValue(element,"category"));
                System.out.println("Link: " + getElementValue(element,"link"));
                System.out.println("Publish Date: " + getElementValue(element,"pubDate"));
                System.out.println("author: " + getElementValue(element,"author"));
                System.out.println("comment: " + getElementValue(element,"comments"));
                System.out.println("guid: " + getElementValue(element,"guid"));
                System.out.println("language: " + getElementValue(element,"language"));
                System.out.println("description: " + getElementValue(element,"description"));
                System.out.println();
            }//for          
        }//try
        catch(Exception ex) {
            ex.printStackTrace();  
        }
      
    }
      
      
    private String getCharacterDataFromElement(Element e) {
        try {
            Node child = e.getFirstChild();
            if(child instanceof CharacterData) {
                CharacterData cd = (CharacterData) child;
                return cd.getData();
            }
        }
        catch(Exception ex) {
          
        }
        return "";          
    } //private String getCharacterDataFromElement
  
    protected float getFloat(String value) {
        if(value != null && !value.equals("")) {
            return Float.parseFloat(value);  
        }
        return 0;
    }
  
    protected String getElementValue(Element parent,String label) {
        return getCharacterDataFromElement((Element)parent.getElementsByTagName(label).item(0));  
    }
  
    /**
     * 파일 읽기
     * @param ctx
     * @param fileName
     * @return
     * @throws FileNotFoundException
     */
    public static StringBuffer readFile(String fileName, String fEncoding) throws FileNotFoundException {
        StringBuffer result = new StringBuffer();
//        Scanner scanner = new Scanner(new File(fileName), fEncoding);
        try {
            BufferedReader in = new BufferedReader(new FileReader(fileName));
            try {
                String line = null;
              
                while ((line=in.readLine()) != null) {
                    result.append(line+NL);
                }
            } finally {
                in.close();
            }
//            while (scanner.hasNextLine()) {
//                result.append(scanner.nextLine()+NL);
//            }
        }catch(IOException ex ) {
            ex.printStackTrace();
        }
      
        return result;
    }
  
    public static StringBuffer readFileScanner(String fileName, String fEncoding) throws FileNotFoundException {
        StringBuffer result = new StringBuffer();
        Scanner scanner = new Scanner(new File(fileName), fEncoding);
        try {
            while (scanner.hasNextLine()) {
                result.append(scanner.nextLine()+NL);
            }
        } finally {
                scanner.close();
        }
      
        return result;
    }
  
    public static void main(String[] args) {
        try {
//            StringBuffer strUrl = readFile(args[0],  ENCODING);
            StringBuffer strUrl = readFileScanner(args[0],  ENCODING);
            if(strUrl != null ){
                String[] urls = strUrl.toString().split(NL);
                for(int i=0; i < urls.length;i++) {
                    RssReader reader = RssReader.getInstance();
                    reader.writeNews(urls[i]);  
                }
            }

            RssReader reader = RssReader.getInstance();
            reader.writeNews();  
                      
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
//            e.printStackTrace();
            System.out.println("지정된 파일을 찾을 수 없습니다. 파일을 확인하시기 바랍니다.");
        }

    }
}

java] random 사용하여 난수 구하기.



    // 1 ~ 10  사이의 정수 난수
    for (int i = 1; i <= 20; i++) {
      int n = (int) (Math.random() * 10) + 1;   <== *10 부분을 100, 1000 으로 늘리면 1-100, 1-1000 까지의 난수를 구할 수 있다.
      System.out.println(n);
    }

    // 0.0 ~ 1.0    사이의 실수 난수
    for (int i = 1; i <= 20; i++)
      System.out.println(Math.random());

java Framework/java] PDF 작업 관련 url





  •   iText 에서 장평 처리 
    • iText의 예제 소스 중 part/chapter14/TextStateOperateors.java 의 59-62 줄 사이의 canvas.setHorizontalScaling(50) 으로 조정 가능(이미지로 처리하는 듯 함) 
  • 거니네(iText관련 문서/강좌??) http://guni.loveyust.net/tag/itext


      iText.jar :    iText-5.0.5.jar



pdfContentByte 에서 bold 를 사용할 수 있는 방법??
.
// first define a standard font for our text
Font helvetica8BoldBlue = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.BOLD, Color.blue);

// create a column object
ColumnText ct = new ColumnText(cb);

// define the text to print in the column
Phrase myText = new Phrase("Lorem ipsum dolor sit amet, ...", helvetica8BoldBlue);
ct.setSimpleColumn(myText, 72, 600, 355, 317, 10, Element.ALIGN_LEFT);
ct.go();

java Framework/java] Object와 JSONObject


[다운]
Java에서 Json 객체로 변환할 때, json-lib라는 오픈 소스를 이용한다.
http://json-lib.sourceforge.net

json-lib에서 array를 변환할 때는 EZMorph 라이브러리가 필요하다.
http://ezmorph.sourceforge.net

자바스크리브에서 객체를 json 객체로 변환시에는 json.js를 이용한다.
http://json.org

[사용법]
Java에서 Json-lib를 사용하기 위해서 필요한 라이브러리는 다음과 같고, eclipse 사용시 Build Path -> Add Exeternal Archives 에 추가한다.
json-lib-2.1-jdk15.jar
jakarta commons-lang 2.3
 
jakarta commons-beanutils 1.7.0  

jakarta commons-collections 3.2  

jakarta commons-logging 1.1

ezmorph 1.0.4

[예제]
   1. 자바스크립트에서
      object.toJSONString();

   2. 자바에서
      JSONObject oJSONObject = JSONObject.fromObject( object );
      JSONArray = JSONArray.fromObject( retlist );

json형식 ==>{"jsontest":[{"name":"Mr.Cho","location":"Seoul"}]}

import java.util.Iterator;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

public class JSONParse {
   public static void main(String[] ar) {
      String s = "{\"jsontest\":[{\"name\":\"Mr.Cho\",\"location\":\"Seoul\"}]}";
      JSONObject jo = JSONObject.fromObject(s);
      JSONArray ja = jo.getJSONArray("jsontest");
      for (Iterator i = ja.iterator(); i.hasNext();) {
          JSONObject ob = (JSONObject) i.next();
          String a = ob.getString("name");
          String b = ob.getString("location");
          System.out.println(a);
          System.out.println(b);
      }
   }
}



아래 fromObject를 사용할 수 있어서 json.jar (org.json.JSONObject) 보다는 json-lib.jar (net.sf.json.JSONObject) 이 더 편한 것 같다.
JSONObject.fromObject( obj )
obj에 문자열도 가능하며, 이것이 JSONText 규칙에 맞을 경우 적절한 JSON 객체를 만들어준다.
이때, obj에 있는 문자열은 작은따옴표(')도 문자열로 간주한다.

   Map states = JSONObject.fromObject("{'':'선택안함','1':'신청','2':'완료','3':'보류'}")

위와 같이 하면 꽤 깔쌈하게 Map 객체를 만들 수 있으며, 이를 Velocity에서도 #set 구문을 이용해서 똑같이 쓸 수도 있다.

JAVA] Java.util.HashMap() 분석



원본 출처 : http://iilii.egloos.com/4457500


HashMap은 Object.hashCode()를 이용하는 java.util.Map 인터페이스의 구현체입니다. 대표적인 Map의 구현체입니다. Map의 주요 구현체는 이 외에 Hashtable과 TreeMap이 있습니다. Hashtable은 이 글에서 함께 설명할 것이고, TreeMap의 구현에 대해서는 따로 정리를 하겠습니다.

일단 Map의 기본 컨셉은 Key-Value입니다. 주민등록번호와 개인 정보같은 경우를 생각하시면 됩니다. 어떤 주민등록번호를 입력하면, 그 사람의 개인정보를 볼 수 있도록 하겠다는 겁니다. 맵에 정보를 추가하는 것은 put(K key, V value)로 정의됩니다. K는 Key의 타입이고 V는 Value의 타입입니다. 주민번호의 예를 들자면, K는 주민등록번호 객체가 될 것이고, V는 개인정보 객체가 될 것입니다. 그리고, 맵에서 정보를 조회하는 것은 get(K key)입니다. put(key, value)로 저장이 된 value는 get(key)를 하면 가져올 수 있다는 겁니다.

간단한 코들를 보여드리자면, 아래와 같습니다.

Map<String, String> map = new HashMap<String, String>();
map.put("key", "value");
String b = map.get("key");

위의 코드에서 b는 "value"라는 String을 가집니다.

HashMap과 Hashtable의 큰 차이는 두 가지입니다.
첫째, HashMap은 null키와 null값을 허용합니다. 허나, Hashtable은 허용하지 않습니다.
둘째, HashMap은 synchronized가 없습니다. 하지만 Hashtable은 대부분의 method가 synchronized로 처리가 됩니다.

이제부터는 HashMap을 중심으로 얘기할 것이며, 위에서 얘기한 두 가지 차이점을 제외하고는 Hashtable도 거의 유사하다고 보시면 됩니다.

1. 순서 보장하지 않음

Map 에 보면, keySet()이라는 메쏘드가 있습니다. 어떤 키값들이 들어있는지 알려주는 겁니다. HashMap의 경우 keySet()으로 받아온 데이터는 입력한 순서와 무관하며, 호출할 때마다 순서가 달라질 수도 있습니다. 따라서 어떠한 순서에도 의존해서는 안 됩니다. 입력한 순서대로 데이터를 받아오고자 한다면, LinkedHashMap을 사용하셔야 하며, 정렬된 순서대로 쓰고자 한다면 TreeMap을 써야 합니다.

2. hashCode()와 equals()

put, get에 있어서 모두 hashCode()와 == 연산 및 equals()를 사용합니다. value와는 전혀 상관없고, key에 대해서만 이런 방식을 씁니다. hashCode()를 사용하는 것은 두 가지 의미가 있는데, 첫째는 equals()에 비해 부하가 적다는 것입니다. 두번째는 hashCode() 값을 기준으로 분류가 가능하다는 것입니다. 두번째의 의미가 훨씬 큽니다. 잠시 후 자세히 설명하겠습니다.
일단 hashCode()를 가지고 비교를 하고 == 로 비교해서 true를 리턴하거나 equals()로 비교해서 true를 리턴하는 지 체크해서 기존 element를 덮어 쓸 것인지를 결정합니다.
hashCode()는 java.lang.Object에 정의가 되어 있으며, 여기에 정리가 되어있습니다.

3. bucket

HashMap은 내부적으로 bucket을 사용합니다. bucket은 Map이 가지는 element들을 적당히 분산시켜 놓는 것입니다. Map이 서랍장이라면, bucket은 각각의 서랍이 라고 생각하시면 됩니다. 첫번째 서랍에는 양말이 두번째 서랍에는 티셔츠가 세번째 서랍에는 바지가 있다면 서랍장 전체를 뒤지지 않아도 찾고자하는 것을 찾을 수 있을 겁니다. 즉, "파란 양말"을 찾기 위해서는 양말 서랍만 찾으면 됩니다.
element가 어떤 bucket에 들어가게 될지는 그 element의 hashCode()값에 의해 결정됩니다. bucket이 n개가 있다면, element는 그 hashCode()%n 번째 bucket에 들어갑니다.(대략적으로 그렇단 얘기고, 정확히 얘기하면 비트연산으로 처리됩니다.) element를 가져올 때 입력되는 키는 같은 bucket에 있는 element 들만 비교를 하게 됩니다. bucket 수가 많으면 한 bucket에 들어가는 element의 수가 적을 것이고, 이는 속도를 향상시키는 길이 됩니다.
데 이터를 이래저래 추가하고 한 번에 뽑아서 따로 저장하는 로직을 생각해봅시다. 데이터를 추가하는 부분에 비해 뽑아쓰는 부분이 적기 때문에 bucket을 작게 유지하는 게 유리해 보이지만 그렇지 않습니다. 왜냐하면, get()이 호출될 때 뿐만 아니라 put()이 호출될 때도 기존에 데이터가 있는 지 확인하는 작업이 다시 한번 실행된다는 것입니다. 키값이 기존에 있던 것과 동일하면, 새로운 입력되는 값이 기존 값을 덮어쓰게 됩니다. 따라서 새로운 element가 추가될 때 그 버킷 안의 모든 element에 대해 새로 추가될 element와 같은 것인지 검사를 합니다. 다시 말해 그 bucket의 모든 element에 대해 hashCode()가 호출되고, 추가될 element와는 == 연산이나 equals()를 통해 비교를 하게 됩니다.

4. 용량과 load factor

용량은 bucket의 수입니다. element의 수가 아닙니다. 기본값은 16입니다. 만약에 한 16만개 정도의 데이터를 16개의 bucket에 담는다면, get을 할 때 평균 1만개의 element와 비교를 해야 합니다. 굉장히 비효율적이죠. 그래서 상황에 따라 bucket의 수가 확장되어야 할 경우가 있습니다. 총 element의 수와 용량간에 어떤 연관성이 있어야 하는데, 그게 바로 load factor입니다. load factor= 총 수용가능한 element의 수 / 용량  으로 정의 됩니다.
HashMap 에는 총 수용가능 element의 수를 늘이는 메쏘드가 없습니다. put() 메쏘드 즉, element의 수를 증가시킬 수 있는 메쏘드가 실행될 때 알아서 수용가능 용량을 계산해서 이 값이 (load factor * 용량)을 넘어서게 되면, bucket 수를 대략 2배로 늘이고(즉, 용량이 2배로 늘어납니다.) 모든 element에 대해 다시 hashCode를 호출하여 어느 bucket으로 들어갈 것인지 다시 계산을 합니다. 이 과정을 rehashing이라 하며 부하가 굉장히 큽니다. element수를 감소 시키는 remove() 메쏘드는 rehashing을 하지 않습니다.
따라서 처음에 어느정도 용량이 들어갈 것인지 예측할 수 있다면, 처음부터 크기를 적절히 해서 rehashing이 가능한 한 적게 일어나도록 해야 합니다. HashMap(int initialCapacity) 생성자를 사용하면, 초기 용량이 16이 아닌 다른 값을 쓸 수 있습니다.

그 렇다고 초기 용량을 무조건 크게 잡는 것은 능사가 아닙니다. 지나치게 크게 잡을 경우 다음과 같은 문제가 생길 수 있습니다. 첫째, 메모리 낭비가 발생합니다. 둘째, key에 대한 iteration을 돌 때 부하가 커집니다. iteration의 부하는 (bucket의 수 + 실제 인스턴스의 크기) 에 비례합니다.

load factor가 크면  (즉, 한 bucket에 많은 element를 넣게 되면) 메모리 절약은 할 수 있으나, 검색이 힘들어 집니다. 반대로 너무 작으면(bucket의 수가 너무 많으면,) 검색은 빠르겠지만, 메모리 상의 낭비가 일어나게 됩니다. 그래서 가장 최적의 값은 일반적으로 0.75라고 합니다. HashMap은 load factor의 기본값을 이 값으로 하고 있지만,  HashMap(int initialCapacity, float loadFactor) 생성자를 통해 load factor를 변경시킬 수 있습니다. 메모리 좀 낭비해도 속도가 중요하다고 생각하면 load factor를 낮추면 됩니다.

5. 동기화되지 않음

처음에 말씀드렸다시피 HashMap은 동기화가 되지 않습니다. Hashtable과의 큰 차이점이죠. 단지 put, get에 대한 문제만은 아닙니다. 학생번호-몸무게 를 key-value로 가지는 HashMap 객체에 대해 학생의 몸무게 평균을 구하려고 하면, 학생의 리스트 즉, HashMap 객체의 keySet을 뽑아와야 합니다. 열심히 루프 돌면서 계산하는 와중에 다른 쓰레드에서 어떤 요소를 추가하거나 삭제하게 되면, 일이 난감해집니다. HashMap은 이런 상황에서 fail-fast 방식으로 처리합니다. (fail-fast: 어떤 에러나 또는 에러를 발생시킬 만한 상황에서 더 이상 정상적인 작업을 진행하지 않도록 해주는 거)
만약 동기화 과정이 필요하다면, Map m= Collections.synchronizedMap(new HashMap(...)); 와 같이 Collections.synchronizedMap() 을 이용하는 것이 좋습니다.

사족으로 알아도 몰라도 별로 달라질 게 없는 HashMap관련 지식 하나!

HashMap은 순서를 보장하지 않는다고 했습니다. 보장되지 않는 순서의 비밀을 파헤쳐봅시다!!
bucket은 Entry라는 내부 클래스의 array로 정의 됩니다.
각 bucket은 처음에 null로 세팅이 되어있고, 어떤 element가 들어오면 Entry 객체를 생성해서 대입합니다. bucket이 서랍이라고 설명한 것은 이해를 돕기 위한 것이고, 코드 상 정확히 말하면 bucket은 어떤 Entry를 말하는 겁니다. Entry는 key와 value 그리고 next 3가지의 멤버 변수로 구성이 됩니다. 여기서 next는 다음 Entry를 가질 수 있는 구조입니다. Linked List라는 거죠.
null이 아닌 bucket에 대해 어떤 element가 추가될 때는 그 bucket의 Entry 객체를 next로 세팅한 새로운 Entry 객체를 생성해서 bucket의 자리를 넣습니다. 뒤에 붙이는 것이 아니라 앞에 붙이는 구조가 되지요. (일반적인 Linked List는 뒤에 붙입니다.)

keySet() 얘기를 해보죠. bucket을 0번째부터 끝까지 루프를 돕니다. 즉, bucket 수만큼 루프를 돕니다. 어떤 bucket에 entry가 있으면, 그 entry의 key를 뽑아냅니다. 그리고그 entry의 next에 대해서 같은 작업을 합니다. next가 null일 때까지 루프돌고 null이면 다음 버킷으로 넘어갑니다. 즉,모든 bucket에 대해서 같은 작업을 하면 element의 수만큼 루프를 돌게 되겠지요. 결과적으로 keySet()의 비용은 (bucket의 수 + element의 수) 가 됩니다. 그리고 뽑히는 순서는 bucket 번호가 작은 놈이 먼저 나오고, 그 중에서는 나중에 들어간 놈이 먼저 나옵니다. 즉, 넣는 순서에 따라 순서가 달라질 수도 있다는 겁니다.

JAVA] java properties 사용법



출처 : http://umzzil.egloos.com/2175356


java.util.Properties 클래스를 사용하여 설정 파일을 제어하는 샘플이다.
import java.util.*;
import java.io.*;

public class PropertyTest {
    private String PROPERTIES_FILE = "C:\\globals.properties";
   

    /**
     * 특정 키값을 반환한다.
     */

    private String getProperty(String keyName) {
        String value = null;
 
        try {
            Properties props = new Properties();
            FileInputStream fis = new FileInputStream(PROPERTIES_FILE);
            props.load(new java.io.BufferedInputStream(fis));
            value = props.getProperty(keyName).trim();
            fis.close();
        } catch (java.lang.Exception e) {
            System.out.println(e.toString());
        }
            return value;
    }


    /**
     * 특정 키 이름으로 값을 설정한다.
     */

    private void setProperty(String keyName, String value) {
        try {
            Properties props = new Properties();
            FileInputStream fis  = new FileInputStream(PROPERTIES_FILE);
            props.load(new java.io.BufferedInputStream(fis));
            props.setProperty(keyName, value);
            props.store(new FileOutputStream(GLOBALS_PROPERTIES_FILE), "");
            fis.close();

        } catch(java.lang.Exception e) {
            System.out.println(e.toString());
        }
    }
 


    public static void main(String args[]) {
        PropertyTest o = null;
        if (args.length == 1) {
            o = new PropertyTest();
            System.out.println(args[0] + ":[" + o.getProperty(args[0]) + "]");
        } else if (args.length == 2) {
            o = new PropertyTest();
            o.setProperty(args[0], args[1]);
            System.out.println(args[0] + ":[" + o.getProperty(args[0]) + "]");
        } else {
            System.out.println("wrong argument");
        }
    }
}



======================================================================================================================
====================================      properties 파일 경로 쉽게 찾기     =======================================

java로 프로그래밍을 하다가 보면 몇가지 설정값을 외부에서 받아야 하는 경우가 있는데 이때 사용하는 것이 property 파일이다.

jdk에도 이 프로퍼티 파일을 다룰 수 있는 클래스가 마련되어 있다. java.util.Properties 클래스가 그 용도이다.

이 클래스를 사용하려면 load라는 메소드를 통해서 프로퍼티 파일일 읽어 와야 하는데 이때 전달되는 인자는 InputStream이다.

문제는 이 InputStream을 전달하려면 FileInputStream을 만들어서 전달해야 하는데 이 FileInputStream을 생성하려면 그 프로퍼티 파일의 경로를 알아야 한다는 것이다.



프로퍼티 파일의 경로를 알아오는 방법에 대해서 몇가지 생각해 보자

1. 프로그램 코드에 상수로 프로터피 파일의 경로를 둔다.

예를들면,

public staitc final String PATH = "/app/myapp/myprop.properties";

라고 두는 것이다. 뭐 이건 말 안해도 알겠지만 별로 좋지 않은 방법이다. 경로나 이름이 바뀌면 새로 컴파일 해야 하고, 뭐 이래저래 좋지 않은거 같다.


2. java 실행 옵션으로 세팅해서 프로그램에서 사용한다.

java 프로그램을 실행시킬 때 실행 옵션으로 프로퍼티 파일의 경로를 줘서 그 옵션값을 읽어서 경로로 사용하도록 하는 것이다.

String path = System.getProperty( "path" );

라는 형태로 사용하면 실행시 준 옵션값을 가져올 수 있다.

이 방법도 많이 사용하는 방법으로 나름대로 쓸만하다. 그렇지만 실행시 옵션을 설정한다는 것이 별로 마음에 안든다.


3. ClassLoader를 사용하여 가져온다.

혹 시 이거 신기하게 생각해 본 사람이 있을지 모르겠는데, log4j를 사용하다 보면 log4j.properties라는 파일을 생성해 두면 내가 특별히 경로를 세팅하지 않았는데도 log4j가 알아서 log4j.properties를 읽어서 사용한다. 나는 처음에 이게 무지 신기했다. log4j가 어떻게 알고 그 위치의 log4j.properties를 읽어 들이는 걸까?

해답은 ClassLoader 였다.

classloader의 주요 기능은 클래스를 로딩하는 것이다.(이름에서 알 수 있는 너무 당연한 이야긴가? ^^;)

하지만 기능이 한가지 더 있는데 바로 클래스 파일 뿐아니라 다른 리소스 파일도 읽어 주는 역할이다.
ClassLoader.getResource( String name )이 그 역할을 하는 메소드다(이 메소드 외에도 getResource... 메소드들이 몇가지 더 있다. 알아서 찾아 보시길...)

이 getResource는 클래스 패스내에서 해당 이름으로 된 파일을 찾아서 그 URL을 넘겨준다. 중요한 포인트는 바로 클래스 패스 내에 있는 파일이라는 것이다.

java 를 실행시킬때 -classpath라고 주는 바로 그 클래스 패스 말이다. 즉 classpath에 설정한 클래스 패스내에 프로퍼티 파일을 두면 ClassLoader를 통해서 프로퍼티 파일을 가져올 수 있는 것이다. 별거 아닌 기능 같지만 쓰다보면 상당히 편리하다.

실제 구현 내용을 간단히 살펴보면 다음과 같다.

        ClassLoader cl;
        cl = Thread.currentThread().getContextClassLoader();
        if( cl == null )
            cl = ClassLoader.getSystemClassLoader();
               
        URL url = cl.getResource( "myprop.properties" );

위 내용은 log4j의 소스에서 일부 참조한 것이다.

위 소스를 참조해서 쉽게 프로퍼티 파일을 다룰 수 있는 클래스를 만들어 보는 것도 좋을 듯 하다.

Java] InputStream 을 String으로 변환하기


 InputStream 을  String으로 변환하는 방법


 춮처 : http://www.kodejava.org/examples/266.html

package org.kodejava.example.io;

import java.io.InputStream;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class StreamToString {

    public static void main(String[] args) throws Exception {
        StreamToString sts = new StreamToString();

        /*
         * Get input stream of our data file. This file can be in the root of
         * you application folder or inside a jar file if the program is packed
         * as a jar.
         */
        InputStream is = sts.getClass().getResourceAsStream("/data.txt");

        /*
         * Call the method to convert the stream to string
         */
        System.out.println(sts.convertStreamToString(is));
    }

    public String convertStreamToString(InputStream is) throws IOException {
        /*
         * To convert the InputStream to String we use the BufferedReader.readLine()
         * method. We iterate until the BufferedReader return null which means
         * there's no more data to read. Each line will appended to a StringBuilder
         * and returned as String.
         */
        if (is != null) {
            StringBuilder sb = new StringBuilder();
            String line;

            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                while ((line = reader.readLine()) != null) {
                    sb.append(line).append("\n");
                }
            } finally {
                is.close();
            }
            return sb.toString();
        } else {      
            return "";
        }
    }
}

2012-10-26

Java] post 방식으로 header를 설정한 후 xml 데이터를 서버에 전달



apache http-client 3.x.jar필요.

출처 : http://danhobak.textcube.com/22



http post 방식으로 header를 설정한 후 xml 데이터를 서버에 전달 후

그 결과를 받는다.

첨부된 파일을 압축을 풀면 lib 디렉토리 안의 jar 파일들을

%CATALINA_HOME%\common\lib 에 위치시키거나

CALSSPASS를 잡아준 후 이용하면 된다.


<%@ page import="org.apache.commons.httpclient.HttpClient" %>
<%@ page import="org.apache.commons.httpclient.methods.PostMethod" %>
<%@ page import ="java.net.*" %>
<%@ page import ="java.io.*" %>

<%

    String orgMsg="abcdefg";
    String encMsg = null;
    String header1 = "header1";
    String header2 = "header2";
    String header3 = "header3";
    String ContentsType="text/xml";
  

    AES256 aes = new AES256();
    encMsg = aes.encrypt(msg);

      String xmldata = "<? xml version=\"1.0\" encoding=\"euc-kr\"?> "
                            +"<! DOCTYPE lgtpims:schema>"
                            +"<schema targetns=\"http://www.aaa.com\""
                    +"version=\"1.0\" xmlns=\"http://www.w3.org/2000/10/XMLSchema\">"
                        +"<parameter method=\"add\">"
                            +"<element-value name=\"addelement\">aaaaa</element-value>"
                            +"<element-value name=\"addelementtype\">bbbbb</element-value>"
                        +"</parameter>"
                    +"</schema>" ;

        String strURL = "http://www.aaa.com/aaa";
        PostMethod post = new PostMethod(strURL);
        post.setRequestHeader("Content-type", "text/xml; charset=ISO-8859-1");
        post.setRequestHeader("header1","header1");
        post.setRequestHeader("header2",header2);
        post.setRequestHeader("header3",header3");
        post.setRequestHeader("Content-Length",Integer.toString(xmldata.length()));
        post.setRequestBody(xmldata);

        HttpClient httpclient = new HttpClient();          

        try {
            int result = httpclient.executeMethod(post);
            // Display status code
            out.println("<br>Response status code: " + result);
            // Display response
             out.println("<br>Response header: "+post.getResponseHeader("Status-Line"));
            out.println("<br>Response body: ");
            out.println(post.getResponseBodyAsString());
        } finally {
            // Release current connection to the connection pool once you are done
            post.releaseConnection();
        }

%>

Java] file channel을 이용한 파일 복사, 파일 다운로드




// file channel 을 이용한 파일 복사

public void fileCopy(String src, String target) throws IOException {

FileInputStream inputStream = new FileInputStream(src);        

FileOutputStream outputStream = new FileOutputStream(target);



FileChannel fcin =  inputStream.getChannel();

FileChannel fcout = outputStream.getChannel();



long size = fcin.size();

fcin.transferTo(0, size, fcout);



fcout.close();

fcin.close();

outputStream.close();

inputStream.close();

}

// request, response 를 이용한 파일 다운로드 기능 구현...

// 출처 : http://hatssarjy.tistory.com/entry/Jsp-FileDownload

public void downloadExec(HttpServletRequest req,HttpServletResponse resp,

String fn) {

resp.setContentType("application/octet-stream");

String filename = fn;

String filename1;

try {

filename1 = new String(fn.getBytes("ISO-8859-1"),"euc-kr");

String filename2 = java.net.URLEncoder.encode(filename1, "UTF8");

LConfiguration conf = LConfiguration.getInstance();

String absPath = conf.getDevonHome().replaceAll("devonhome", "")+"/web/upload"; //  <=== context의 경로

resp.setHeader("Content-Disposition","attachment; filename=\""+filename2+"\";");

//File file = new File ("upload/"+filename);

File file = new File (absPath+"/"+filename);

byte[] bytestream = new byte[(int)file.length()];

FileInputStream filestream = new FileInputStream(file);

int i = 0, j = 0;

while((i = filestream.read()) != -1) {

bytestream[j] = (byte)i;

j++;

}

OutputStream outStream = resp.getOutputStream();

outStream.write(bytestream);                                        

outStream.close();

} catch (UnsupportedEncodingException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (DevonException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}



      // 위의 메소드를 개선한 메소드.

public void downloadExec2(HttpServletRequest req,HttpServletResponse resp,

String fn) {

LConfiguration conf;

try {

conf = LConfiguration.getInstance();

String absPath = conf.getDevonHome().replaceAll("devonhome", "")+"/web/upload"; //로컬경로

String change_name = StringUtils.defaultString(fn);

String real_name = StringUtils.defaultString(fn);

//실제 저장소의 파일명

String fileName = "/upload"+"/"+change_name;

// File file = new File(fileName);

File file = new File (absPath+"/"+real_name);

int fileSize = (int)file.length();

resp.setContentType("application/octet-stream");

resp.setHeader("Content-Disposition", "attachment;filename="+real_name+";");

resp.setContentLength(fileSize);

resp.setHeader("Content-Transfer-Encoding", "binary;");

resp.setHeader("Pragma", "no-cache;");

resp.setHeader("Expires", "-1;");

resp.setHeader("Cache-Control", "cache, must-revalidate");

if(fileSize >0 && file.isFile()){

BufferedInputStream fin;

//fin = new BufferedInputStream(new FileInputStream(fileName));

fin = new BufferedInputStream(new FileInputStream(file));

BufferedOutputStream outs = new BufferedOutputStream(resp.getOutputStream());

byte b[] = new byte[fileSize];

int read = 0;

try{

while((read=fin.read(b)) != -1){

outs.write(b,0,read);

}

}finally{

outs.close();

fin.close();

}

}

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (DevonException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}
;

Java] Date Format 사용하기



출처 : http://www.rgagnon.com/javadetails/java-0099.html


Using DateFormat

import java.text.*;



public class DateUtils {

  public static boolean isValidDateStr(String date) {

    try {

     DateFormat df =

       DateFormat.getDateInstance

         (DateFormat.SHORT); // YYYY-MM-DD

     df.setLenient(false);   // this is important!

     df.parse(date);

    }

    catch (ParseException e) {

     return false;

    }

    catch (IllegalArgumentException e) {

     return false;

    }

    return true;

  }

  

  public static void main(String[] args) {

    System.out.println(" 1900-12-13 valid ? " 

        + DateUtils.isValidDateStr("1900-12-13"));



    // "1990-12/13" throws a ParseException

    System.out.println(" 1900-12/13 valid ? " 

        + DateUtils.isValidDateStr("1900-12/13"));

    // "1990-13-12" throws a IllegalArgumentException

    System.out.println(" 1900-13-12 valid ? " 

        + DateUtils.isValidDateStr("1900-13-12"));

    /*

     * output :

     *  1900-12-13 valid ? true

     *  1900-12/13 valid ? false

     *  1900-13-12 valid ? false

     */

  }

}
Using SimpleDateFormat
package com.rgagnon.howto;



import java.text.*;



public class DateUtils {

  public static boolean isValidDateStr(String date, String format) {

    try {

      SimpleDateFormat sdf = new SimpleDateFormat(format);

      sdf.setLenient(false);

      sdf.parse(date);

    }

    catch (ParseException e) {

      return false;

    }

    catch (IllegalArgumentException e) {

      return false;

    }

    return true;

    }

  

  public static void main(String[] args) {

    System.out.println(" 1900-12-13 valid ? " 

        + DateUtils.isValidDateStr("1900-12-13","yyyy-MM-dd"));



    // "1990-12/13" throws a ParseException

    System.out.println(" 1900-12/13 valid ? " 

        + DateUtils.isValidDateStr("1900-12/13","yyyy-MM-dd"));

    // "1990-13-12" throws a IllegalArgumentException

    System.out.println(" 1900-13-12 valid ? " 

        + DateUtils.isValidDateStr("1900-13-12","yyyy-MM-dd"));

    /*

     * output :

     *  1900-12-13 valid ? true

     *  1900-12/13 valid ? false

     *  1900-13-12 valid ? false

     */

  }

}

Using GregorianCalendar

import java.util.*;



public class jtest {

    public static void main(String args[]) {

        try {

            GregorianCalendar gc = new GregorianCalendar();

            gc.setLenient(false);        // must do this

            gc.set(GregorianCalendar.YEAR, 2003);

            gc.set(GregorianCalendar.MONTH, 42);// invalid month

            gc.set(GregorianCalendar.DATE, 1);



            gc.getTime(); // exception thrown here

        }

        catch (Exception e) {

            e.printStackTrace();

        }

    }

}




출처 :  http://www.dreamincode.net/forums/topic/14886-date-validation-using-simpledateformat/


// date validation using SimpleDateFormat

// it will take a string and make sure it's in the proper 

// format as defined by you, and it will also make sure that

// it's a legal date



public boolean isValidDate(String date)

{

    // set date format, this can be changed to whatever format

    // you want, MM-dd-yyyy, MM.dd.yyyy, dd.MM.yyyy etc.

    // you can read more about it here:

    // http://java.sun.com/j2se/1.4.2/docs/api/index.html

    

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");

    

    // declare and initialize testDate variable, this is what will hold

    // our converted string

    

    Date testDate = null;



    // we will now try to parse the string into date form

    try

    {

      testDate = sdf.parse(date);

    }



    // if the format of the string provided doesn't match the format we 

    // declared in SimpleDateFormat() we will get an exception



    catch (ParseException e)

    {

      errorMessage = "the date you provided is in an invalid date" +

                              " format.";

      return false;

    }



    // dateformat.parse will accept any date as long as it's in the format

    // you defined, it simply rolls dates over, for example, december 32 

    // becomes jan 1 and december 0 becomes november 30

    // This statement will make sure that once the string 

    // has been checked for proper formatting that the date is still the 

    // date that was entered, if it's not, we assume that the date is invalid



    if (!sdf.format(testDate).equals(date)) 

    {

      errorMessage = "The date that you provided is invalid.";

      return false;

    }

    

    // if we make it to here without getting an error it is assumed that

    // the date was a valid one and that it's in the proper format



    return true;



} // end isValidDate

2012-10-14

Java] Java 파일 캐싱




출처 : http://www.ezslookingaround.com/blog/tech/?no=1414&category=


출처 : http://tripoverit.blogspot.com/2008/04/java-create-zip-file-in-memory.html



Java - Create Zip file in memory


 

I find myself writing and rewriting this piece of code whenever I want to zip a set of files (in memory) and return the zipped file back as an object in memory. I often use this when the user requests a download of multiple reports and the deployment environment doesn't allow for disk access.

I thought I'd post it here so that I could copy-paste it the next time I need it :) If you've stumbled upon this page, you're free to use the code below too!
  1. privatestaticbyte[] createZip(Map files) throws IOException {  
  2.     ByteArrayOutputStream bos = new ByteArrayOutputStream();  
  3.     ZipOutputStream zipfile = new ZipOutputStream(bos);  
  4.     Iterator i = files.keySet().iterator();  
  5.     String fileName = null;  
  6.     ZipEntry zipentry = null;  
  7.     while (i.hasNext()) {  
  8.         fileName = (String) i.next();  
  9.         zipentry = new ZipEntry(fileName);  
  10.         zipfile.putNextEntry(zipentry);  
  11.         zipfile.write((byte[]) files.get(fileName));  
  12.     }  
  13.     zipfile.close();  
  14.     return bos.toByteArray();  


Java 로 간단한 파일 캐싱을. ^^

출처 : http://ncanis.tistory.com/104

File Caching.
오늘의 2번째 글입니다.~ ^^

간단한 파일캐싱에 대하여 한번 써봤습니다.
별로 팁이란것도 아니지만 심심해서. ㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎㅎ

보통 어떤 flag나 환경설정 정보를 파일에 저장할때가 있습니다.
예를 들어, database url 이나, 로그인 정보, 아니면 구현 클래스 이름 등등.
자주바뀌어야 하는 정보들 말이죠 :)

자주 바뀌어야 하는 정보라면 로더 클래스가 이 환경설정 파일을 읽어 시스템에 적용하는게 보통이죠.
그렇게 하면 파일내의 정보가 바뀌더라도 재 컴파일을 안해도 되는 장점이 있습니다.

근데,
만약 항상 파일내의 데이터를 가져오는 부분에 복잡한 루틴이 걸려있으면 어떨까요.
시스템의 성능은 많이 떨어지게 됩니다.

워, 파일 내용이 바뀌지도 않았는데 계속 파일을 읽어서 확인하다죠 ㅡ.ㅡ;

이럴때는 파일 캐싱을 통해 가져오면 되지요.

평소에는 파일내용을 메모리에 올려놓다가,
파일 내용이 바뀌었다면 다시 로딩해서 메모리에 올려놓으면 됩니다.

ps. 대부분의 개발자분들은 잘하시만, 가끔가다보면 요청함수에, 파일로딩 해서 정보를 분석하는 로직을 그냥 넣어놓는것도 심심찮게 보게 된답니다.~ -0-


아래는 파일 캐싱 예제 소스 입니다.
구현은 간단합니다. 그저 파일이 변경됬는지만 확인하고,
변경이 됐으면 => 다시 로딩해 메모리에 올리고,
변경이 안됐으면 => 기존에 저장해놓은 정보를 리턴하는거죠.~~
package test;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Properties;

public class Caching {
    private long lastModified = 0L;
    private String value = null;
  
    // 키에 대한 value값을 가져온다.
    public String get(String key) throws IOException {
        URL url = this.getClass().getResource("/test/test.properties");
        File file = new File(url.getPath());
        // 파일이 수정되지 않았으면 기존에 로드된 정보를 리턴한다.
        if(file.lastModified()!=this.lastModified) {
            this.lastModified = file.lastModified();
            this.value = load(url,key);
        }
        return value;          
    }
    // test.properties 파일을 읽어 키의 value값을 읽어온다.
    public String load(URL url,String key) throws IOException {
        System.out.println("== 파일로부터 데이터 리로딩 ==");
        Properties p = new Properties();
        p.load(url.openStream());
        return p.getProperty(key);      
    }

    public static void main(String[] args) throws IOException {
        Caching c = new Caching();
        // 첫요청시에만 파일을 읽고, 나머지는 기존 정보를 가져오죠.~
        System.out.println("데이터로딩1 = "+c.get("message"));
        System.out.println("데이터로딩2 = "+c.get("message"));
        System.out.println("데이터로딩3 = "+c.get("message"));

    }

}

소스는 더럽지만 대충 개념은 나왔네용. ㅎㅎ
근데 한가지 주의 할 게 있습니다.
이런 설정정보를 File로 빼는것에 대한 주의점이.~
왜 몇년동안 바뀌지도 정보를 파일로 빼는지,
간단한 정보일 뿐인데 멋있다고(?) xml  로 설정정보를 만들어, 무거운 Parser를 돌리는 것인지. ㅡ.ㅡ;
이런거는 조심해야겠습니다.

무엇이든지 해당 프로젝트와 로직에 맞는 방법을 찾아 적용하는게 가장 중요하겠죠. :)
test.properties 내용.
message=ver_1.01

2012-08-29

centos]CentOS 4.4에서 Java설치하기



CentOS 4.4에서 Java설치하기

1.
Sun의 Downloads페이지에서 플랫폼에 맞는 파일(self-extracting file)을 다운로드받는다.
2.
jpackage-utils과 rpm-build패키지를 설치한다.
3.
jpackage-nonfree repository에서 java-1.5.0-sun패키지를 다운로드받는다.(yumdownloader 이용)
4.
다운받은 파일들을 /usr/src/redhat/SOURCES/ 로 옮기고, 패키지를 빌드한다.
setarch i586 rpmbuild –rebuild java-1.5.0-sun*
(플랫폼은 알아서 변경해주는 센스)
5.
설치한다.
만약 libXp 라이브러리가 없다는 에러가 발생하면 xorg-x11-deprecated-libs 패키지를 설치해준다.
ODBC관련 에러가 뜨면 unixODBC-devel 패키지를 설치해준다.
끝.
SUN에서 제공하는 RPM을 이용해도 되지만, 그 경우 패키지 업그레이드시 사라질 수도 있다고 한다.
믿거나 말거나. 속는셈치고 믿어보고 이렇게 설치했다. java-1.5.0-sun-compat 라는 패키지도
있던데 JPackage Java compatibility package for Sun’s JDK 라고 주석이 붙어있는걸 보니
SUN의 패키지를 설치하고 이걸 설치해도 될 것 같기는 함.