2012-10-31
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" );
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 "";
}
}
}
라벨:
자바,
inputStream,
java,
programing,
String
Java] Ibatis 다중링크 사용
출처 : http://mimul.com/pebble/default/2008/02/24/1203779580000.html
웹 어플리케이션에서 하나 이상의 데이터 베이스에 접근하여 어플리케이션이 실행되는 환경들이 많을 것입니다.
iBatis에서 어떻게 활용되는 지 사용방법을 공유합니다.
사용환경은 iBatis와 DBCP입니다.
- database.properties
driver=oracle.jdbc.driver.OracleDriver
jdbc.url1=jdbc:oracle:thin:@mimuluserdb:1521:mimuluser
username1=mimuluser
password1=mimuluser
jdbc.url2=jdbc:oracle:thin:@pepsiuserdb:1521:pepsiuser
username2=pepsiuser
password2=pepsiuser - sqlmap1.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource="com/mimul/dwr/app/
resource/database.properties"/>
<settings
cacheModelsEnabled="true"
enhancementEnabled="true"
lazyLoadingEnabled="true"
maxRequests="40"
maxSessions="20"
maxTransactions="5"
useStatementNamespaces="false"
/>
<transactionManager type="JDBC">
<dataSource type="DBCP">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${jdbc.url1}"/>
<property name="username" value="${username1}"/>
<property name="password" value="${password1}"/>
<!-- OPTIONAL PROPERTIES BELOW -->
<property name="initialSize" value="5"/>
<property name="maxActive" value="30"/>
<property name="maxIdle" value="20"/>
<property name="maxWait" value="60000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="validationQuery" value="select 0 from dual"/>
<property name="testOnBorrow" value="true"/>
<property name="maximumActiveConnections" value="10"/>
<property name="maximumIdleConnections" value="5"/>
<property name="maximumWait" value="60000"/>
<property name="logAbandoned" value="false"/>
<property name="removeAbandoned" value="false"/>
<property name="removeAbandonedTimeout" value="50000"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/mimul/dwr/app/sql/Mimul.xml"/>
</sqlMapConfig> - sqlmap2.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<properties resource="com/mimul/dwr/app/resource/database.properties"/>
<settings
cacheModelsEnabled="true"
enhancementEnabled="true"
lazyLoadingEnabled="true"
maxRequests="40"
maxSessions="20"
maxTransactions="5"
useStatementNamespaces="false"
/>
<transactionManager type="JDBC">
<dataSource type="DBCP">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${jdbc.url2}"/>
<property name="username" value="${username2}"/>
<property name="password" value="${password2}"/>
<!-- OPTIONAL PROPERTIES BELOW -->
<property name="initialSize" value="5"/>
<property name="maxActive" value="30"/>
<property name="maxIdle" value="20"/>
<property name="maxWait" value="60000"/>
<property name="poolPreparedStatements" value="true"/>
<property name="validationQuery" value="select 0 from dual"/>
<property name="testOnBorrow" value="true"/>
<property name="maximumActiveConnections" value="10"/>
<property name="maximumIdleConnections" value="5"/>
<property name="maximumWait" value="60000"/>
<property name="logAbandoned" value="false"/>
<property name="removeAbandoned" value="false"/>
<property name="removeAbandonedTimeout" value="50000"/>
</dataSource>
</transactionManager>
<sqlMap resource="com/mimul/dwr/app/sql/Pepsi.xml"/>
</sqlMapConfig>
- SqlConfig.java
import java.io.File;
import java.io.Reader;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.jaeminara.common.log.LogPool;
public class SqlConfig {
private static SqlMapClient sqlMap1 = null;
private static SqlMapClient sqlMap2 = null;
private static SqlConfig instance_ = null;
private SqlConfig() throws Exception
{
Reader reader = null;
String resource = null;
try {
if (sqlMap == null) {
resource = "sqlmap1.xml";
reader = Resources.getResourceAsReader(resource);
sqlMap1 = SqlMapClientBuilder.buildSqlMapClient(reader);
resource = "sqlmap2.xml";
reader = Resources.getResourceAsReader(resource);
sqlMap2 = SqlMapClientBuilder.buildSqlMapClient(reader);
reader.close();
}
} catch (Exception e) {
System.out.println(e);
throw e;
} finally {
if (reader != null)
reader.close();
reader = null;
rsc = null;
}
}
public static SqlConfig instance()
{
try {
if (instance_ == null) {
synchronized (SqlConfig.class) {
if (instance_ == null)
instance_ = new SqlConfig();
}
}
} catch (Exception e) {
System.out.println(e);
}
return instance_;
}
/**
* Return SqlMapClient for SDP schema
*
* @return
*/
public static SqlMapClient getSqlMap1Instance()
{
return sqlMap1;
}
/**
* Return SqlMapClient for SDP schema
*
* @return
*/
public static SqlMapClient getSqlMap2Instance()
{
return sqlMap2;
}
}
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();
}
%>
라벨:
자바,
http-client,
java,
post,
xml
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();
}
}
;
라벨:
자바,
파일 다운로드,
파일 복사,
file channel,
file copy,
file download,
java
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 */ } }
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
라벨:
자바,
date format,
DateUtils,
java,
valid date
피드 구독하기:
글 (Atom)