'01.JAVA/Java'에 해당되는 글 199건

  1. 2009.06.16 multipart form parser - http file upload, database 저장 java class 연재2
  2. 2009.06.16 multipart form parser - http file upload 기능 java class 연재1
  3. 2009.06.16 java 디렉토리 만들기 예제
  4. 2009.06.13 Teach Your Self Java Programming In 21 Days
  5. 2009.06.13 Java Performance Tuning 2000
  6. 2009.06.13 beginning-jsp-jsf-and-tomcat-web-development-from-novice-to-professional
  7. 2009.06.08 Java에서 HTML 태그를 제거하는 정규식 적용 1
  8. 2009.06.07 java enum - enum의 메쏘드
  9. 2009.06.04 tomcat 사용 : java.lang.OutOfMemoryError: Java heap space 2
  10. 2009.06.04 java.lang.OutOfMemoryError
  11. 2009.06.04 emctl start dbconsole / 오라클 em 안될때
  12. 2009.05.30 JAVA basic(scjp 1[1].5)
  13. 2009.04.28 java 파일 저장할때.. 중복이름 체크 2
  14. 2009.04.28 CLOB+MULTI UPLOAD
  15. 2009.04.24 [JAVA] Timer를 이용하여 일정시간에 작업수행하기(Schedule)
  16. 2009.04.14 TCP 네트워크로부터 읽고 쓰기
  17. 2009.04.07 자바에서 C/C++ 사용하기
  18. 2009.04.07 [String 비교하기] .equals()와 ==은 다른가요?
  19. 2009.04.06 query를 수행하는 두가지 방법
  20. 2009.04.06 자바스크립트 옆에는 <noscript>를 넣자
  21. 2009.04.06 [java]File에 이어쓰기
  22. 2009.04.06 클래스 PrintWriter 1
  23. 2009.04.01 윈도우즈 RDP 포트 변경하기 1
  24. 2009.03.23 java
  25. 2009.03.23 여러글자로 된 문자열 변환
  26. 2009.03.23 문자열 내의 특정한 문자열을 모두 지정한 다른 문자열로 변경 1
  27. 2009.02.25 Web Java Class Decompiler 이용 방법
  28. 2009.02.23 [JAVA] java환경변수 & Tomcat환경변수 & Servlet 설정
  29. 2009.02.23 'Development/Java'
  30. 2009.02.23 java transaction 처리
01.JAVA/Java2009. 6. 16. 20:16
반응형
multipart form parser - http file upload, database 저장 java class 연재2

이번글에서는 업로드된 파일을 저장할때 database에 record를 함께 insert 하는 기능에 대해서 
설명하겠습니다. 설명하기 전에 이전 글에서 대용량 파일 업로드 기능에 대해서 다시 한번 review하고
다시 자세히 설명하겠습니다.

1. 대용량 파일 업로드 기능 (1G 이상 파일 업로드에도 문제가 없는 기능)
2. 파일 업로드시 upload 진행 상황을 Internet Explorer에서 볼수 있을것 (다음번 글에서 올리겠습니다.)

WCPage.java : JSP page context와 request parameter를 저장하는 java class
WCMultipartFormParser.java : http request stream을 parsing하는 java class
WCMultipartFormElement.java : multipart form lement를 저장하는 java class

// form html 일부분 시작
<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>
// form html 일부분 끝

form을 javascript에서 서버로 submit하면 
아래와 같은 http request stream이 서버로 전달됩니다.

// http request stream 시작
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="_cmd"

uploadFile
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="file"; filename="C:\test.txt"
Content-Type: text/plain

test
-----------------------------7d82efc203cc--
// http request stream 끝

위의 request stream을 parsing하는 pseudo code 입니다.

// pseudo code 시작
JSP page
  -> WCPage.initCtrl
    -> WCPage.initCtrl
      -> WCPage.isMultipart()
      -> WCMultipartFormParser.init()
        -> WCMultipartFormParserparseContent(oRequest)
          -> WCMultipartFormParserparseContentEx(oRequest)
            -> WCMultipartFormParserfindBoundary() : -----------------------------7d82efc203cc 이 부분을 parsing합니다.
            -> WCMultipartFormParserfindHeader() : Content-Disposition: form-data; name="_cmd" 이 부분을 parsing 합니다.
              -> WCMultipartFormElement.setHeader : header 정보를 element에 저장합니다.
            -> WCMultipartFormParser.procContent() : content body를 parsing 합니다.
              -> 임시파일에 파일 저장 : content type이 file인경우
              -> parameter인경우 WCProperties m_rParam 에 parameter 이름과 value를 저장
      -> WCMultipartFormParser.saveFile(sDir)
        -> WCMultipartFormElement.saveFile(sPathFile)
// pseudo code 끝

대용량 파일을 서버에 업로드 하기 위해서는 업로드 되는 파일을 임시 directory에
임시 파일로 저장을 하고 다시 개발자가 원하는 디렉토리로 파일을 이동하는 방식을 
사용합니다. (임시로 저장하는 이유는 memory에 파일을 모두 load하고 있을 수 없기
때문입니다.)
위의 코드에서 procContent에서 파일 내용을 임시 디렉토리에 저장합니다.
WCMultipartFormParser.procContent

사용자가 파일을 임시 디렉토리에서 운영용 file directory로 이동하고자 하면
WCMultipartFormParser.saveFile(sDir) 을 호출합니다.

이 함수를 form에 있는 element들 중에서 file인 경우 이 파일을 사용자가 지정한 sDir로 
이동을 합니다.

// WCMultipartFormParser.saveFile code 시작
public void saveFile(String sDir)
{
    try
    {
        Vector vElement = this.getElements();
        int nCount = WCVector.size(vElement);
        for (int i=0;i<nCount;i++)
        {
            WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
            if (oElmt == null)
            {
                continue;
            }
            if (!oElmt.isFile())
            {
                continue;
            }
            String sTempFileName = oElmt.getCloneFileName();
            if (WCString.isEmpty(sTempFileName))
            {
                continue;
            }
            String sUserDirectoryFile = WCString.buildFilePath(sDir,sTempFileName,"/");
            oElmt.saveFile(sUserDirectoryFile);
        }
    }
    catch (Exception ex)
    {
        WCLog.getInstance().printLog("exception at WCMultipartFormParser.saveFile "+ex.toString());
    }
}        
// WCMultipartFormParser.saveFile code 끝

WCMultipartFormParser.saveFile 에서
WCMultipartFormElement.saveFile을 호출합니다.
WCMultipartFormElement.saveFile 함수는 임시로 저장된 file을 사용자가 지정한 path의 file로
copy한 다음 임시 파일을 삭제하는 코드입니다.

// WCMultipartFormElement.saveFile code 시작
public int saveFile(String sPathFile)
{
    try
    {
        if (sPathFile == null)
            return -1;
        String sDir = WCString.getPath(sPathFile);
        WCSystem oSys = WCSystem.getInstance();
        oSys.CreateDir(sDir);
        String sSaveFileName = sPathFile;
        setSaveFileName(sSaveFileName);
        File oSrcFile = new File(getTempFileName());
        File oDestinationFile = new File(sSaveFileName);
        FileInputStream oFIS = null;
        FileOutputStream oFOS = null;
        try
        {
            oFIS = new FileInputStream(oSrcFile);
            oFOS = new FileOutputStream(oDestinationFile);
            byte[] oBuffer = new byte[1024 * 4];
            int nRead = 0;
            while ((nRead = oFIS.read(oBuffer)) != -1) 
            {
                oFOS.write(oBuffer, 0, nRead);
            }
            oFIS.close();
            oFOS.close();
            oFIS = null;
            oFOS = null;
            oSrcFile.delete();
        }
        catch (Exception e) 
        {
            WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+e.toString());
            if (oFIS != null)
            {
                oFIS.close();
            }
            if (oFOS != null)
            {
                oFOS.close();
            }
            e.printStackTrace(); 
        }
    }
    catch(IOException ioe)
    {
        WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+ioe.toString());
        ioe.printStackTrace();
    }
    return 0;
}
// WCMultipartFormElement.saveFile code 시작

파일을 사용자가 원하는 디렉토리로 복사를 하면서 file 관련 정보를 database에 insert하기 위해서는
WCMultipartFormParser 로 부터 상속받은 class를 정의합니다.
그리고 saveFile method를 재 정의합니다.
그리고 아래와 같이 함수를 정의합니다.

// WCMultipartFormParser에서 상속받은 MyFormParser java class sample 시작
public class MyFormParser extends WCMultipartFormParser 
{
    public void saveFile(String sDir)
    {
        try
        {
            super.saveFile(sDir);
            
            Vector vElement = this.getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                {
                    continue;
                }
                if (!oElmt.isFile())
                {
                    continue;
                }
                String sPhyFile = oElmt.getSaveFileName();
                String sOrgName = oElmt.getName();
                WCStmt oStmt = new WCStmt();
                oStmt.executeUpdate("insert into tb_file (xxx) values(xxx,'"+sFile+"')",null,"WDLDatabasePool");
            }
        }
        catch (Exception ex)
        {
            WCLog.getInstance().printLog("exception at MyFormParser.saveFile "+ex.toString());
        }
    }
}
// WCMultipartFormParser에서 상속받은 MyFormParser java class sample 끝

물론 이와 같이 OOP의 inheritance와 overriding 기법을 사용하지 않고

// inheritance와 overriding 기법을 사용하지 않고 직접 호출방식으로 구현한 소스 일부분 시작
    WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
    oFormParser.setDebug(true);
    oFormParser.init();
    oFormParser.saveFile(sDir);
    
    Vector vElement = this.getElements();
    int nCount = WCVector.size(vElement);
    for (int i=0;i<nCount;i++)
    {
        WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
        if (oElmt == null)
            continue;
        if (oElmt.isFile())
        {
            String sName = oElmt.getName();
            String sPhyFileName = oElmt.getSaveFileName();
            WCStmt oStmt = new WCStmt();
            oStmt.executeQuery("insert into table(xxx,xxx) values(xxx,'"+sPhyFileName+"')",null,sDsn);
        }
    }
// inheritance와 overriding 기법을 사용하지 않고 직접 호출방식으로 구현한 소스 일부분 끝
    
이와 같이 직접 호출하는 방식을 사용해도 됩니다.

아래의 소스는 Web Development Library(http://www.webdevlib.net)에서 소스의 일부분만을 추출하여
재구성한 sample입니다. 첨부한 소스만으로도 어느정도 동작이 가능하지만 WCProperties,WCVector,WCLog,WCSystem,WCEnv
등의 파일은 http://www.webdevlib.net에서 다운받아 사용하십시요
소스의 일부분은 고의로 누락한 것은 아닙니다. 모든 소스를 설명하려니 너무 많기때문에
중요한 부분을 추출하여 sample로 구성하면서 최대한 이해가 쉽도록 재구성을 하였습니다.

제공하는 sample code는 3개의 파일로 구성됩니다

file_upload_progress1.jsp
WCMultipartFormParser.java
WCMultipartFormElement.java

아래의 sample에서 개발자는 WCMultipartFormParser.java 이부분에서 multipart form을 parsing하는 부분만을
참고하여 사용할 수도 있을 것입니다.

아무튼 개발자에게 유용한 코드가 되길 바랍니다.

// file_upload_progress1.jsp 소스 시작
<%@ page language="java" import="wdl.*,java.util.*,java.sql.*,java.lang.*,java.io.*,java.io.File " contentType="text/html; charset=EUC-KR"%>
<%
    WCPage oPage = new WCPage();
    if (oPage.initCtrl(pageContext) > 0)
    {
        return;
    }
%>
<%@ include file="/wdl/src/java/WCMultipartFormParser.java"%>
<%@ include file="/wdl/src/java/WCMultipartFormElement.java"%>
<%!
public class WCPage
{
    public int initCtrl(javax.servlet.jsp.PageContext oPageContext)
    {
        return initCtrl(
            (javax.servlet.http.HttpServletRequest)oPageContext.getRequest()
            ,(javax.servlet.http.HttpServletResponse)oPageContext.getResponse()
            ,(javax.servlet.jsp.JspWriter)oPageContext.getOut()
            ,(javax.servlet.http.HttpSession)oPageContext.getSession()
            ,(javax.servlet.ServletContext)oPageContext.getServletContext()
            ,oPageContext
            ,(javax.servlet.ServletConfig)oPageContext.getServletConfig()
            );
    }
    public int initCtrl(
        javax.servlet.http.HttpServletRequest oRequest
        ,javax.servlet.http.HttpServletResponse oResponse
        ,javax.servlet.jsp.JspWriter oOut
        ,javax.servlet.http.HttpSession oSession
        ,javax.servlet.ServletContext oApplication
        ,javax.servlet.jsp.PageContext oPageContext
        ,javax.servlet.ServletConfig oConfig)
    {
        try
        {
            m_request = oRequest;
            m_response = oResponse;
            m_out = oOut;
            m_session = oSession;
            m_application = oApplication;
            m_pageContext = oPageContext;
            m_config = oConfig;
            
            if (isMultipart())
            {
                WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
                oFormParser.setDebug(true);
                oFormParser.init();
                byte[] btDebugBuf = oFormParser.getDebugBuf();
                String sDebug = new String(btDebugBuf);
                this.printOut("<pre>");
                this.printOut(sDebug);
                this.printOut("</pre>");
                
                WCProperties rParam = oFormParser.getParam();
                this.printOut(rParam.serializeOut());

                String sDir = "c:/tmp3";
                oFormParser.saveFile(sDir);
                return 1;
            }
        }
        catch (Exception ex)
        {
        }
        return 0;
    }
    public javax.servlet.http.HttpServletRequest m_request = null; 
    public javax.servlet.http.HttpServletResponse m_response = null; 
    public javax.servlet.jsp.JspWriter m_out = null; 
    public javax.servlet.http.HttpSession m_session = null; 
    public javax.servlet.ServletContext m_application = null; 
    public javax.servlet.jsp.PageContext m_pageContext = null; 
    public javax.servlet.ServletConfig m_config = null; 
    
    public javax.servlet.http.HttpSession getSession()
    {
        return m_session;
    }
    public javax.servlet.http.HttpServletRequest getRequest()
    {
        return m_request;
    }
    public javax.servlet.jsp.PageContext getPageContext()
    {
        return m_pageContext;
    }

    public boolean isMultipart()
    {
        HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)m_request;
        String content_type = oRequest.getHeader("content-type");
        if (WCString.indexOf(WCString.toUpper(content_type),"MULTIPART") == 0)
        {
            return true;
        }
        return false;
    }
}
%>
<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>
<a href="javascript:uploadFile();">upload the file</a>
<iframe id="ifrmAction" name="ifrmAction" width="0" height="0"></iframe> 

<script>
function uploadFile()
{
    var fParam = window.document.fParam;
    fParam._cmd.value = "uploadFile";
    fParam.method = "post";
    fParam.target = "_blank";
    fParam.submit();
}
</script>
// file_upload_progress1.jsp 소스 끝



// WCMultipartFormParser.java 소스 시작
package wdl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
    public class WCMultipartFormParser 
    {
        public String m_sCharset;
        private HttpServletResponse resp;
        private ServletContext m_oApp;
        public Vector m_vElement = null;
        public WCProperties m_rParam = null;
        public WCPage m_oPage = new WCPage();
        public WCMultipartFormParser() 
        {
            refresh();
        }
        public WCMultipartFormParser(WCPage oPage) 
        {
            refresh();
            setPage(oPage);
        }
        public void init()
        {
            WCPage oPage = getPage();
            if (oPage == null)
                return;
            HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)oPage.getRequest();
            parseContent(oRequest);
        }
        public void init(WCPage oPage)
        {
            setPage(oPage);
            init();
        }
        public int m_nContentLength = 0;
        public byte[] m_btBuf = null;
        public int m_nBufIdx = 0;
        public int m_nBoundaryLen = 0;
        public byte m_btBoundary[] = null;
        public int m_nBufReadSize = 0;
        public int m_nBufAllocSize = 1024*64;
        public int m_nCurrentBuffer = 0; 
        public int m_nBufferCount = 0;
        public int m_nAccumRead = 0;
        public InputStream m_oInputStream = null;
        public int m_nAccumBufIdx = 0;
        public String getEnvValue(String sProp)
        {
            WCEnv env = WCEnv.getInstance();
            if (env != null)
            {
                WCProperties rcd = env.getProperties();
                if (rcd != null)
                {
                    String sVal = rcd.getStrValue(sProp);
                    return sVal;
                }
            }
            return "";
        }
        public void refresh()
        {
            m_vElement = new Vector();
            m_rParam = new WCProperties();
            String sSrcCharset = getEnvValue("charset"); 
            if (WCString.isEmpty(sSrcCharset))
            {
                sSrcCharset = "KSC5601"; 
            }
            m_sCharset = sSrcCharset;
            m_nContentLength = 0;
            m_btBuf = null;
            m_nBufIdx = 0;
            m_nBoundaryLen = 0;
            m_btBoundary = null;
            m_nBufReadSize = 0;
            m_nBufAllocSize = 1024*64;
            m_nCurrentBuffer = 0; 
            m_nAccumRead = 0;
            m_oInputStream = null;
            m_nAccumBufIdx = 0;
            m_nBufferCount = 0;
            m_nPrevAccumBufIdx = 0;
        }
        public byte[] setByte(byte btBuf[],int nIdx,byte btChar)
        {
            {
                int nSize = 0;
                if (btBuf != null)
                    nSize = btBuf.length;
                if (nIdx >= nSize)
                {
                    int nMax = nIdx+32;
                    byte btNew[] = new byte[nMax];
                    for (int i=0;i<nMax;i++)
                    {
                        btNew[i] = 0;
                    }
                    for (int i=0;i<nSize;i++)
                    {
                        btNew[i] = btBuf[i];
                    }
                    btNew[nIdx] = btChar;
                    btBuf = btNew;
                }
                else
                {
                    btBuf[nIdx] = btChar;
                }
                return btBuf;
            }
        }
        public byte[] m_btDebugBuf = null;
        public byte[] getDebugBuf()
        {
            return m_btDebugBuf;
        }
        public byte[] append(byte btBuf[],byte btAppend[],int nLen)
        {
            try
            {
                if (btAppend == null)
                    return null;
                if (btBuf == null)
                {
                    btBuf = new byte[nLen];
                }
                int nSize = btBuf.length;
                int nNewSize = nSize+nLen;
                byte btNew[] = new byte[nNewSize];
                for (int i=0;i<nNewSize;i++)
                {
                    btNew[i] = 0;
                }
                for (int i=0;i<nSize;i++)
                {
                    btNew[i] = btBuf[i];
                }
                for (int i=0;i<nLen;i++)
                {
                    btNew[i+nSize] = btAppend[i];
                }
                btBuf = btNew;
                return btBuf;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.append "+ex.toString());
            }
            return null;
        }
        public byte[] copyBytes(byte btSrc[],int nStartIdx,int nEndIdx)
        {
            try
            {
                int nLen = nEndIdx-nStartIdx;
                if (nLen <= 0)
                    return null;
                int nAlloc = nLen;
                byte btNew[] = new byte[nAlloc];
                for (int i=0;i<nAlloc;i++)
                {
                    btNew[i] = 0;
                }
                for (int i=0;i<nLen;i++)
                {
                    btNew[i] = btSrc[i+nStartIdx];
                }
                return btNew;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.copyBytes "+ex.toString());
            }
            return null;
        }
        public void parseContent(HttpServletRequest oRequest) 
        {
            try
            {
                Vector vDataHeader = parseContentEx(oRequest);
            }
            catch(Exception crfe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.parseContent "+crfe.toString());
                crfe.printStackTrace();
            }
        }
       
        public void setResponse(HttpServletResponse resp) 
        {
            this.resp = resp;
        }
        public void setContext(ServletContext oApp) 
        {
            this.m_oApp = oApp;
        }
        public boolean findBoundary()
        {
            try
            {
                m_btBoundary = null;
                m_nBoundaryLen = 0;
                int nLen = 0;
                m_btBoundary = setByte(m_btBoundary,nLen,(byte)13); 
                nLen ++;
                m_btBoundary = setByte(m_btBoundary,nLen,(byte)10); 
                nLen ++;
                boolean bBoundaryFound = false;
                while (isEof() != true)
                {
                    byte btByte = getByte();
                    if (btByte == 13)
                    {
                        bBoundaryFound = true;
                        m_nBoundaryLen = nLen;
                        getByte();
                        break;
                    }
                    m_btBoundary = setByte(m_btBoundary,nLen,btByte);
                    nLen ++;
                }
                if (bBoundaryFound == true)
                {
                    m_btBoundary = copyBytes(m_btBoundary,0,nLen);
                    return true;
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.findBoundary "+ex.toString());
            }
            return false;
        }
        public String findHeader()
        {
            try
            {
                int nLen = 0;
                byte btHeader[] = null;
                boolean bFound = false;
                byte btByte = 0;
                byte btByte2 = 0;
                while (isEof() != true)
                {
                    btByte = getByte();
                    btByte2 = getByte(); 
                    btByte2 = getByte(); 
                    putBackByte();
                    putBackByte();
                    if (btByte == 13 && btByte2 == 13) 
                    {
                        getByte();
                        getByte();
                        getByte(); 
                        bFound = true;
                        break;
                    }
                    btHeader = setByte(btHeader,nLen,btByte);
                    nLen ++;
                }
                btHeader = copyBytes(btHeader,0,nLen);
                String sDataHeader = new String(btHeader,m_sCharset); 
                return sDataHeader;    
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.findHeader "+ex.toString());
            }
            return null;
        }
        public boolean isBoundary()
        {
            try
            {
                int boundaryKeyPosition = 0;
                boundaryKeyPosition = 0;
                boolean binaryEndFound = false;
                binaryEndFound = false;
                byte btByte = (byte)0;
                int nLen = 0;
                while (isEof() != true)
                {
                    btByte = getByte();
                    nLen ++;
                    if (btByte == m_btBoundary[boundaryKeyPosition])
                    {
                        if (boundaryKeyPosition == m_nBoundaryLen-1 )
                        {
                            binaryEndFound = true;
                            getByte(); 
                            getByte(); 
                            break;
                        }
                        boundaryKeyPosition++;
                    }
                    else
                    {
                        for (int i=0;i<nLen;i++)
                        {
                            putBackByte();
                        }
                        break;
                    }
                }
                return binaryEndFound;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.isBoundary "+ex.toString());
            }
            return false;
        }
        public void putBackByte()
        {
            m_nBufIdx --;
            m_nAccumBufIdx --;
            if (m_nBufIdx < 0)
            {
                m_nCurrentBuffer --;
                if (m_nCurrentBuffer < 0)
                {
                }
                m_nBufIdx = (m_nBufAllocSize/2) - 1;
            }
        }
        public boolean m_bDebug = false;
        public void setDebug(boolean bDebug)
        {
            m_bDebug = bDebug;
        }
        public boolean isDebug()
        {
            return m_bDebug;
        }
        public boolean isEof()
        {
            if (m_nAccumBufIdx < m_nContentLength)
            {
                return false;
            }
            return true;
        }
        public byte getByte() throws Exception
        {
            byte btData = getByteEx();
            setProgress(m_nAccumBufIdx);
            return btData;
        }
        public byte getByteEx() throws Exception
        {
            try
            {
                if (m_oInputStream == null)
                {
                    m_oInputStream = m_oPage.getRequest().getInputStream();
                }
                if (m_btBuf == null)
                {
                    m_btBuf = new byte[m_nBufAllocSize+32];
                    if (m_btBuf == null)
                    {
                        return (byte)0;
                    }
                    for (int i=0;i<m_nBufAllocSize+32;i++)
                    {
                        m_btBuf[i] = (byte)0;
                    }
                }
                if (m_nBufIdx >= m_nBufReadSize && m_nAccumRead < m_nContentLength && m_nBufferCount == m_nCurrentBuffer)
                {
                    if (m_nBufReadSize == m_nBufAllocSize/2)
                    {
                        m_nBufReadSize = 0;
                        m_nCurrentBuffer ++;
                        m_nBufferCount ++;
                    }
                    int nMaxRead = m_nBufAllocSize/2 - m_nBufReadSize; 
                    if (nMaxRead > m_nContentLength-m_nAccumRead)
                    {
                        nMaxRead = m_nContentLength-m_nAccumRead;
                    }
                    int nRead = m_oInputStream.read(m_btBuf
                        ,(m_nCurrentBuffer%2)*(m_nBufAllocSize/2) + m_nBufReadSize
                        ,nMaxRead);
                    if (this.isDebug())
                    {
                        m_btDebugBuf = this.append(m_btDebugBuf,m_btBuf,nRead);
                    }
                    m_nBufReadSize += nRead;
                    m_nAccumRead += nRead;
                    if (m_nBufReadSize >= m_nBufAllocSize/2)
                    {
                    }
                    m_nBufIdx = m_nBufIdx % (m_nBufAllocSize/2);
                }
                byte btByte = m_btBuf[(m_nCurrentBuffer%2)*(m_nBufAllocSize/2) + m_nBufIdx];
                m_nBufIdx ++;
                if (m_nBufIdx == m_nBufAllocSize/2 && m_nCurrentBuffer < m_nBufferCount)
                {
                    m_nCurrentBuffer ++;
                    m_nBufIdx = 0;
                }
                m_nAccumBufIdx ++;
                return btByte;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.getByteEx "+ex.toString());
                setProgress(m_nContentLength);
                Exception oEx = new Exception("exception at getByte");
                throw oEx;
            }
        }
        public int procContent()
        {
            try
            {
                if (m_oCurElement.isFile())
                {
                    try
                    {
                        FileOutputStream oFileStream = m_oCurElement.createTempFile();
                        if (oFileStream == null)
                        {
                            return -1;
                        }
                        int nBufSize = 1024*4;
                        byte[] btBuf = new byte[nBufSize];
                        int nLen = 0;
                        byte btByte = 0;
                        while (isEof() != true)
                        {
                            btByte = getByte();
                            if (btByte == (byte)13) 
                            {
                                putBackByte();
                                if (isBoundary() == true)
                                {
                                    break;
                                }
                                btByte = getByte(); 
                            }
                            btBuf[nLen] = btByte;
                            nLen ++;
                            if (nLen >= nBufSize)
                            {
                                if (oFileStream != null)
                                {
                                    oFileStream.write(btBuf,0,nBufSize);
                                }
                                nLen = 0;
                            }
                        }
                        if (nLen > 0)
                        {
                            if (oFileStream != null)
                            {
                                oFileStream.write(btBuf,0,nLen);
                            }
                        }
                        m_oCurElement.closeTempFile();
                    }
                    catch (Exception ex)
                    {
                        WCLog.getInstance().printLog("exception at WCMultipartFormParser.procContent "+ex.toString());
                        m_oCurElement.closeTempFile();
                        m_oCurElement.deleteTempFile();
                        return -1;
                    }
                }
                else
                {
                    byte btContent[] = null;
                    int nLen = 0;
                    byte btByte = 0;
                    while (isEof() != true)
                    {
                        if (isBoundary() == true)
                            break;
                        btByte = getByte();
                        btContent = setByte(btContent,nLen,btByte);
                        nLen ++;
                    }
                    String sValue = null;
                    if (nLen > 0)
                    {
                        btContent = copyBytes(btContent,0,nLen);
                        sValue = new String(btContent,m_sCharset);
                    }
                    else
                    {
                        sValue = "";
                    }
                    String sProp = m_oCurElement.getFieldName();
                    if (btContent != null)
                    {
                    }
                    else
                    {
                    }
                    if (m_rParam == null)
                    {
                        m_rParam = new WCProperties();
                    }
                    m_rParam.addValue(sProp,sValue);
                    m_oCurElement.setValue(sValue);
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.procContent "+ex.toString());
                return -1;
            }
            return 0;
        }
        public WCMultipartFormElement m_oCurElement = null;
        public Vector parseContentEx(HttpServletRequest oRequest) 
        {
            int nLen = oRequest.getContentLength();
            setContentLength(nLen);
            m_nBufIdx = 0;
            m_btBoundary = null;
            m_nBoundaryLen = 0;
            int nState = 0; 
            try
            {
                m_nBufReadSize = 0;
                int nRead = 0;
                m_oInputStream = oRequest.getInputStream();
                while (isEof() != true)
                {
                    if (nState == 0)
                    {
                        findBoundary();
                        nState = 100;
                    }
                    else if (nState == 100)
                    {
                        String sHeader = findHeader();
                        if (sHeader != null)
                        {
                            nState = 200;
                            m_oCurElement = new WCMultipartFormElement(this);
                            m_oCurElement.setHeader(sHeader);
                            if (m_vElement == null)
                                m_vElement = new Vector();
                            m_vElement.addElement(m_oCurElement);
                        }
                        nState = 200;
                    }
                    else if (nState == 200)
                    {
                        int nRet = procContent();
                        if (nRet < 0)
                        {
                        }
                        nState = 100;
                    }
                }
            }
            catch(IOException ioe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.parseContentEx "+ioe.toString());
                ioe.printStackTrace();
            }
            setProgress(m_nAccumBufIdx);
            return m_vElement;
        }
        public Vector getElements()
        {
            return m_vElement;
        }
        public String getFileName()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    return oElmt.getName();
                }
            }
            return null;
        }
        public void deleteTempFile()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    oElmt.deleteTempFile();
                }
            }
        }
        public String getPathName()
        {
            Vector vElement = getElements();
            int nCount = WCVector.size(vElement);
            for (int i=0;i<nCount;i++)
            {
                WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                if (oElmt == null)
                    continue;
                if (oElmt.isFile())
                {
                    return oElmt.getPathName();
                }
            }
            return null;
        }
        
        public int getFileCount()
        {
            try
            {
                int nRet = 0;
                Vector vElement = getElements();
                int nCount = WCVector.size(vElement);
                for (int i=0;i<nCount;i++)
                {
                    WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                    if (oElmt == null)
                        continue;
                    if (oElmt.isFile())
                    {
                        nRet ++;
                    }
                }
                return nRet;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.getFileCount "+ex.toString());
            }
            return 0;
        }
        public void setCharset(String sCharset)
        {
            m_sCharset = sCharset;
        }        
        public String getCharset()
        {
            return m_sCharset;
        }
        public WCProperties getParam()
        {
            if (m_rParam == null)
                m_rParam = new WCProperties();
            return m_rParam;
        }
        public WCPage getPage()
        {
            return m_oPage;
        }
        public void setPage(WCPage oPage)
        {
            m_oPage = oPage;
        }
        public int getContentLength()
        {
            return m_nContentLength;
        }
        public int getRead()
        {
            return m_nAccumBufIdx;
        }
        public void setContentLength(int nLen)
        {
            m_nContentLength = nLen;
            if (m_oPage != null)
            {
                String sLen = new String(""+m_nContentLength);
                HttpSession oSession = m_oPage.getSession();
                if (oSession != null)
                {
                    oSession.putValue("wdl.WCMultipartFormParser.contentLength",sLen);
                }
            }
        }
        public int m_nPrevAccumBufIdx = 0;
        public void setProgress(int nParam)
        {
            int nRead = nParam;  
            m_nAccumBufIdx = nRead;
            if (m_nAccumBufIdx - m_nPrevAccumBufIdx < 1024 && (m_nAccumBufIdx < m_nContentLength))
            {
                return;
            }
            m_nPrevAccumBufIdx = m_nAccumBufIdx;
            if (m_oPage != null)
            {
                String sLen = new String(""+m_nAccumBufIdx);
                HttpSession oSession = m_oPage.getSession();
                if (oSession != null)
                {
                    oSession.putValue("wdl.WCMultipartFormParser.read",sLen);
                }
            }
        }        
        public void saveFile(String sDir)
        {
            try
            {
                Vector vElement = this.getElements();
                int nCount = WCVector.size(vElement);
                for (int i=0;i<nCount;i++)
                {
                    WCMultipartFormElement oElmt = (WCMultipartFormElement)WCVector.getObjAt(vElement,i);
                    if (oElmt == null)
                    {
                        continue;
                    }
                    if (!oElmt.isFile())
                    {
                        continue;
                    }
                    String sTempFileName = oElmt.getCloneFileName();
                    if (WCString.isEmpty(sTempFileName))
                    {
                        continue;
                    }
                    String sUserDirectoryFile = WCString.buildFilePath(sDir,sTempFileName,"/");
                    oElmt.saveFile(sUserDirectoryFile);
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormParser.saveFile "+ex.toString());
            }
        }        
    }
// WCMultipartFormParser.java 소스 끝

// WCMultipartFormElement.java 소스 시작
package wdl;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;
    public class WCMultipartFormElement 
    {
        private boolean m_bFile = false;
        private String fieldName = null;
        private String fullPathName = null;
        private String m_sFileName = null;
        private String fileExtension = null;
        private String pathName = null;
        private String contentType = null;
        private String contentDisposition = null;
        private String mimeType = null;
        private String mimeSubType = null;
        private String m_sValue = null;
        public WCMultipartFormParser m_oParser;
        public WCMultipartFormElement(WCMultipartFormParser oParser) 
        {
            setMultipartFormParser(oParser);
            m_sValue = null;
            m_rUserData = new WCProperties();
            m_oFileOutputStream = null;
        }
        public void setMultipartFormParser(WCMultipartFormParser oParser)
        {
            m_oParser = oParser;
        }
        public WCMultipartFormParser getMultipartFormParser()
        {
            return m_oParser;
        }
        public FileOutputStream createTempFile()
        {
            try
            {        
                String sSourceFileName = getFileName();
                if (WCString.isEmpty(sSourceFileName))
                {
                    return null;
                }
                java.io.File oFile = null;
                m_sTempFileName = getTempFile(sSourceFileName);
                oFile = new java.io.File(m_sTempFileName);
                m_oFileOutputStream = new FileOutputStream(oFile);
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.createTempFile "+ex.toString());
            }
            return m_oFileOutputStream;
        }
        public void closeTempFile()
        {
            try
            {
                if (m_oFileOutputStream != null)
                {
                    m_oFileOutputStream.close();
                }
                m_oFileOutputStream = null;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.closeTempFile "+ex.toString());
            }
        }
        public FileOutputStream getTempFileOutputStream()
        {
            FileOutputStream oRet = null;
            oRet = m_oFileOutputStream;
            return oRet;
        }    
        public void setHeader(String headerString) 
        {
            try
            {
                if (headerString == null)
                    return;
                this.m_bFile = headerString.indexOf("filename=\"") > 0;
                int startPosition = headerString.indexOf("name=\"") + "name=\"".length();
                int endPosition = headerString.indexOf("\"", startPosition);
                if( (startPosition > 0) && (endPosition > 0) )
                {
                    this.fieldName = headerString.substring(startPosition, endPosition);
                }
                if (this.isFile())
                {
                    startPosition = headerString.indexOf("filename=\"") + "filename=\"".length();
                    endPosition = headerString.indexOf("\"", startPosition);
                    if( (startPosition > 0) && (endPosition > 0) )
                    {
                        this.fullPathName = headerString.substring(startPosition, endPosition);
                    }
                    startPosition = headerString.indexOf("Content-Type: ") + "Content-Type: ".length();
                    if( startPosition > 0 )
                    {
                        this.contentType = headerString.substring(startPosition);
                    }
                    startPosition = headerString.indexOf("Content-Disposition: ") + "Content-Disposition: ".length();
                    endPosition = headerString.indexOf(";", startPosition);
                    this.contentDisposition = headerString.substring(startPosition, endPosition);
                    if ((startPosition = this.fullPathName.lastIndexOf(47)) > 0)
                    {
                        this.m_sFileName = this.fullPathName.substring(startPosition + 1);
                    }
                    else if((startPosition = this.fullPathName.lastIndexOf(92)) > 0)
                    {
                        this.m_sFileName = this.fullPathName.substring(startPosition + 1);
                    }
                    else 
                    {
                        this.m_sFileName = this.fullPathName;
                    }
                    if((startPosition = this.m_sFileName.lastIndexOf(46)) > 0 )
                    {
                    this.fileExtension = this.m_sFileName.substring(startPosition+1);
                    }
                    else
                    {
                    this.fileExtension = "";
                    }
                    if((startPosition = this.contentType.indexOf("/")) > 0)
                    {
                        this.mimeType = this.contentType.substring(0,startPosition);
                        this.mimeSubType = this.contentType.substring(startPosition+1);
                    }
                    else
                    {
                        this.mimeType = this.contentType;
                        this.mimeSubType = this.contentType;
                    }
                }
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.WCMultipartFormElement "+ex.toString());
            }
        }
        public boolean isFile() 
        {
            return this.m_bFile;
        }
        public boolean isValidFile()
        {
            if (this.m_bFile == true && !WCString.isEmpty(getName()))
            {
                return true;
            }
            return false;
        }
        public String getFieldName() 
        {
            return this.fieldName;
        }
        public String getFullPathName() 
        {
            return this.fullPathName;
        }
        public String getFileName() 
        {
            return this.m_sFileName;
        }
        public String getName()
        {
            return getFileName();
        }
        public String getPathName()
        {
            return this.pathName;
        }
        public String getFileExtension() 
        {
            return this.fileExtension;
        }
        public String getContentType() 
        {
            return this.contentType;
        }
        public String getContentDisposition() 
        {
            return this.contentDisposition;
        }
        public String getMimeType() 
        {
            return this.mimeType;
        }
        public String getMimeSubType() 
        {
            return this.mimeSubType;
        }
        public void setValue(String sValue)
        {
            m_sValue = sValue;
        }
        public String getValue()
        {
            return m_sValue;
        }
        private int size = 0;
        private byte [] contents;
        public WCProperties m_rUserData = new WCProperties();
       
        public String m_sTempDirectory = "";
        public void setTempDirectory(String sVal)
        {
            m_sTempDirectory = sVal;
        }
        public String getTempDirectory()
        {
            if (WCString.isEmpty(m_sTempDirectory))
            {
                m_sTempDirectory = WCString.nullCheck(getEnvValue("tempdir"),getEnvValue("wdl.tempdir"));
                if (WCString.isEmpty(m_sTempDirectory))
                {
                    String sPath = getHome();
                    m_sTempDirectory = WCString.buildFilePath(sPath,"wdl/tmp","/");
                }
            }
            return m_sTempDirectory;
        }
        public String getHome()
        {
            String sHome = WCString.trim(getEnvValue("wdl.home"));
            if (WCString.isEmpty(sHome))
            {
                sHome = WCString.left(WCEnv.getInstance().getEnvFile(),"/WEB-INF");
            }
            return sHome;
        }
        public String getTempName()
        {
            try
            {
                java.util.Date dat = new java.util.Date();
                java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat ("yyyy");
                String sYear = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("MM");
                String sMonth = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("dd");
                String sDate = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("HH");
                String sHour = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("mm");
                String sMin = formatter.format(dat);
                formatter = new java.text.SimpleDateFormat("ss");
                String sSec = formatter.format(dat);            
                int nRand0 = (int)(Math.random()*10000);
                int nRand1 = (int)(Math.random()*10000);
                int nRand2 = (int)(Math.random()*10000);
                String sName = sYear+sMonth+sDate+sHour+sMin+sSec+"_"+nRand0+"_"+nRand1+"_"+nRand2;
                return sName;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.getTempName "+ex.toString());
            }
            return "";
        }
        public String getTempFile(String sSourceFileName)
        {
            try
            {
                String sExt = WCString.nullCheck(WCString.getFileExt(sSourceFileName),"");
                String sName = getTempName();
                if (!WCString.isEmpty(sExt))
                {
                    sName += "."+sExt;
                }
                String sDir = getTempDirectory();
                WCSystem oSys = WCSystem.getInstance();
                oSys.CreateDir(sDir);            
                String sRet = WCString.buildFilePath(sDir,sName,"/");
                return sRet;
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.getTempFile "+ex.toString());
            }
            return null;
        }
        public String getEnvValue(String sProp)
        {
            WCEnv env = WCEnv.getInstance();
            if (env != null)
            {
                WCProperties rcd = env.getProperties();
                if (rcd != null)
                {
                    String sVal = rcd.getStrValue(sProp);
                    return sVal;
                }
            }
            return "";
        }
        public FileOutputStream m_oFileOutputStream = null;
        public String m_sTempFileName = null;
       
        public String getTempFileName()
        {
            return m_sTempFileName;
        }
        public int getSize() 
        {
            return this.size;
        }
           
        public void setSize(int size) 
        {
            this.size = size;
        }
           
        public byte [] getContents() 
        {
            return this.contents;
        }
           
        public byte getContentByte(int index) 
        {
            return this.contents[index];
        }
        public void setContents(byte[] contents) 
        {
            this.contents = contents;
        }
           
        public void setContentByte(int index, byte content) 
        {
            this.contents[index] = content;
        }
        public String m_sSaveFileName = null;
        public String getSaveFileName()
        {
            return m_sSaveFileName;
        }
        public void setSaveFileName(String sFileName)
        {
            m_sSaveFileName = sFileName;
        }
        public int saveFile(String sPathFile)
        {
            try
            {
                if (sPathFile == null)
                    return -1;
                String sDir = WCString.getPath(sPathFile);
                WCSystem oSys = WCSystem.getInstance();
                oSys.CreateDir(sDir);
                String sSaveFileName = sPathFile;
                setSaveFileName(sSaveFileName);
                File oSrcFile = new File(getTempFileName());
                File oDestinationFile = new File(sSaveFileName);
                FileInputStream oFIS = null;
                FileOutputStream oFOS = null;
                try
                {
                    oFIS = new FileInputStream(oSrcFile);
                    oFOS = new FileOutputStream(oDestinationFile);
                    byte[] oBuffer = new byte[1024 * 4];
                    int nRead = 0;
                    while ((nRead = oFIS.read(oBuffer)) != -1) 
                    {
                        oFOS.write(oBuffer, 0, nRead);
                    }
                    oFIS.close();
                    oFOS.close();
                    oFIS = null;
                    oFOS = null;
                    oSrcFile.delete();
                }
                catch (Exception e) 
                {
                    WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+e.toString());
                    if (oFIS != null)
                    {
                        oFIS.close();
                    }
                    if (oFOS != null)
                    {
                        oFOS.close();
                    }
                    e.printStackTrace(); 
                }
            }
            catch(IOException ioe)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.saveFile "+ioe.toString());
                ioe.printStackTrace();
            }
            return 0;
        }
        public WCProperties getUserData()
        {
            return m_rUserData;
        }
        public void setUserData(String sProp,String sValue)
        {
            if (m_rUserData == null)
                m_rUserData = new WCProperties();
            m_rUserData.setValue(sProp,sValue);
        }
        public void setUserData(String sProp,int nValue)
        {
            if (m_rUserData == null)
                m_rUserData = new WCProperties();
            m_rUserData.setValue(sProp,nValue);
        }
        public void deleteTempFile()
        {
            try
            {
                File oFile = new File(m_sTempFileName);
                boolean bSucc = oFile.delete(); 
            }
            catch (Exception ex)
            {
                WCLog.getInstance().printLog("exception at WCMultipartFormElement.deleteTempFile "+ex.toString());
            }
        }
        public String getCloneFileName()
        {
            String sFullPathName = this.getFullPathName();
            if (WCString.isEmpty(sFullPathName))
        {
            return null;
        }
        String sExt = WCString.getFileExt(sFullPathName);
            String sTempName = this.getTempName();
            String sTempFileName = sTempName+"."+sExt;
            return sTempFileName;
        }
        public long m_nFileSize = -1;
        public long getFileSize()
        {
            if (m_nFileSize > (long)0)
                return m_nFileSize;
            String sFileName = getSaveFileName();
            try
            {
                File oFile = new File(sFileName);
                if (oFile != null)
                {
                    m_nFileSize = oFile.length();
                    return m_nFileSize;
                }
            }
            catch (Exception ex)
            {
            }
            sFileName = m_sTempFileName;
            try
            {
                File oFile = new File(sFileName);
                if (oFile != null)
                {
                    m_nFileSize = oFile.length();
                    return m_nFileSize;
                }
            }
            catch (Exception ex)
            {
            }
            return 0;
        }
    }
// WCMultipartFormElement.java 소스 끝

첨부파일 : file_upload_progress1.zip

file_upload_progress1.jsp
WCMultipartFormParser.java
WCMultipartFormElement.java

출처 : 고급 웹 UI 개발 라이브러리 Web Development Library 소스공개 : http://www.webdevlib.net
첨부파일 :  
multipart_form_parser2.zip   [7 KB]   다운로드 횟수 28 회
Posted by 1010
01.JAVA/Java2009. 6. 16. 20:15
반응형
출처 : http://www.javanuri.net/devforum/boardView.jsp?pg=4&menuId=12&Id=305711&gb=qna

multipart form parser - http file upload 기능 java class 연재1

다음과 같은 기능의 file upload 프로그램을 java code를 소개하겠습니다.

1. 대용량 파일 업로그 기능 (1G 이상 파일 업로드에도 문제가 없는 기능)
2. 파일 업로드시 upload 진행 상황을 Internet Explorer에서 볼수 있을것

위의 기능 중에서 이번 글에서는 1번 기능에 대해서 설명을 하겠습니다.
2번 기능은 AJAX 기능을 이요하여 구현이 가능하며 이후 글에서 차차 설명하겠습니다.
첨부하는 소스코드는 실제 프로젝트에서 사용하는데 무리가 없는 소스입니다.
(많은 시스템에서 실제 운영중인 코드 입니다.)

ActiveX를 제외한 일반적인 파일 업로드 프로그램은 클라이언트에서 서버로 전달된
multipart form 형식의 input stream을 parsing하여 어떤 값이 파일이고 어떤 값이
form의 input 값인지를 결정하여 파일은 file system에 저장하는 방식입니다.

다음과 같은 html form을 submit하겠습니다.
선택한 파일은 c:\test.txt 파일입니다.

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

서버에 전달되는 stream은 다음과 같습니다.

-----------------------------7d82efc203cc
Content-Disposition: form-data; name="_cmd"

uploadFile
-----------------------------7d82efc203cc
Content-Disposition: form-data; name="file"; filename="C:\test.txt"
Content-Type: text/plain

test
-----------------------------7d82efc203cc--

이와 같은 stream을 parsing하는 java class인
WCMultipartFormParser,WCMultipartFormElement를 소개합니다.
위와 같은 stream을 parsing하면 form element가 2개이고 하나는 
parameter(_cmd)이고 하나는 파일(c:\test.txt)입니다.

WCMultipartFormParser
  -> WCMultipartFormElement : _cmd=uploadFile
  -> WCMultipartFormElement : file c:\test.txt

WCMultipartFormParser(parser라고 간략히 부르겠습니다.)
WCMultipartFormElement(element라고 간략히 부르겠습니다.)
의 구조를 설명하겠습니다.

대용량 파일을 서버에 업로드 하려면 input stream으로 부터 전달된 file의 data를
memory에 모두 loading하면 안됩니다. 만약 5G file을 uploading한다면 이를 memory에 올릴 수가 
없기때문입니다. 따라서 upload된 내용을 parsing하면서 임시 directory에 저장을 합니다.

다음과 같은 순서로 설명을 하겠습니다.

1. input stream을 buffering하는 방법
2. parser에서 호출되는 순서
3. file을 임시파일로 저장(다음번 글에서 설명)
4. 임시로 저장된 파일을 사용자가 정의하는 directory로 복사(다음번 글에서 설명)

parser는 input stream으로부터 읽어들인 내용을 double buffering하여 관리합니다.
double buffering에 대해서 간단히 설명드리겠습니다.
하나의 buffer를 반으로 나누고 한쪽 부분에 input stream에서 읽은 내용을 임시로 저장합니다.
그리고 이 내용을 parsing을 합니다.
한쪽 부분 buffer를 모두 parsing을 하면 buffer의 나머지 반쪽에 다시 input stream에서 읽은
내용을 임시로 저장합니다.
이렇게 double buffering을 하는 이유는 한쪽의 buffer를 parsing하다가 parsing이 잘못되어
rollback을 하는 경우 한쪽 buffer에서만 rollback해서 안되는 경우가 있습니다.
예를 들어 보이겠습니다.
buffer size = 20이고 반으로 나눈 한쪽 버퍼는 10 size가 됩니다.
1234567890 1234567890
abcdefghij kl
아래와 같이 kl까지 parsing을 했는제 잘못 parsing을 해서 rollback 즉 gh부터 parsing을 다시
해야 하는 경우 double buffering 기법을 사용합니다.
그러면 buffer size를 크게 하면 되지않느냐 라고 질문 할 수 있습니다. 그렇지 않습니다.
buffer size가 아무리 커도 rollback에 대한 여분을 충분히 확보할 수가 없습니다.
즉 이전에 사용하던 buffer를 지우지 말고 보유하고 있어야 충분한 rollback을 확보할 수 있습니다.
첨부한 source 코드에서 getByte는 하나의 input stream에서 1 byte 씩 읽어들입니다.
getByte에서 호출하는 getByteEx에서 double buffering 처리를 합니다.

public byte getByte() throws Exception

input stream을 parsing 하는 부분에서는 이제 byte단위로 parsing하다가 문제가 있으면
rollback을 할 수 있습니다.
위에서 sample로 보여드린 form 즉 _cmd,file을 parsing하는 방법에 대해 설명하겠습니다.

WCMultipartFormParser.init()
  -> parseContent(oRequest)
    -> parseContentEx(oRequest)
      -> findBoundary() : -----------------------------7d82efc203cc 이 부분을 parsing합니다.
      -> findHeader() : Content-Disposition: form-data; name="_cmd" 이 부분을 parsing 합니다.
        -> WCMultipartFormElement.setHeader : header 정보를 element에 저장합니다.
      -> procContent() : content body를 parsing 합니다.
        -> 임시파일에 파일 저장 : content type이 file인경우
        -> parameter인경우 WCProperties m_rParam 에 parameter 이름과 value를 저장

위와 같은 구조로 form을 parsing합니다.

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

이 form을 submit할때 request parameter 값은 WCMultipartFormParser.getParam()을 호출하면
parsing되어 저장된 request parameter값을 얻어올 수 있습니다.
그리고 아래의 소스에서 WCMultipartFormParser.saveFile(sDir)을 호출하여 임시 저장된
file들을 개발자가 원하는 directory로 이동을 합니다.

다음번 글에서는 file을 저장하는 구조에 대해서 설명하겠습니다.

아래의 소스 코드는 JSP 에서 WCPage의 object를 생성하고 WCMultipartFormParser의 기능을 호출하여
multipart form을  parsing하고 파일을 저장하는 sample code입니다.

WCPage.initCtrl
  -> WCPage.initCtrl
    -> WCPage.isMultipart : file을 submit한 겨우인지를 검사
      -> WCMultipartFormParser.init()

if (isMultipart())
{
    WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
    oFormParser.setDebug(true);
    oFormParser.init();
    byte[] btDebugBuf = oFormParser.getDebugBuf();
    String sDebug = new String(btDebugBuf);
    this.printOut("<pre>");
    this.printOut(sDebug);
    this.printOut("</pre>");
    
    WCProperties rParam = oFormParser.getParam();
    this.printOut(rParam.serializeOut());

    String sDir = "c:/tmp3";
    oFormParser.saveFile(sDir);
    return 1;
}
      
여기서 잠깐 WCPage에 대해서 설명하겠습니다.
WCPage는 JSP 혹은 Servlet에 대한 정보를 저장하고 있는 Object입니다.
WCMultipartFormParser 혹은 WCMultipartFormElement에서 request 혹은 response object를 access할때
WCPage를 통하여 access할 수 있습니다.
WCPage.initCtrl에서 pageContext를 넘김으로 WCPage에서 JSP 관련 context를 모두 저장하고
또한 page로 전달된 parameter를 WCPage가 모두 저장하고 있습니다.
여기서 sample로 제공하는 WCPage java class는 WDL(Web Development Library)에서 제공하는 WCPage.java에서
필요한 부분만 추출하여 새로 구성한 sample입니다.
(개발자들이 이해를 쉽게 하기 위해서 일부러 추출을 하였습니다. http://www.webdevlib.net 에서 
모든 소스코드는 무료로 다운로드 받을 수 있습니다.)

첨부한 소스만으로도 어느정도 동작이 가능하지만 WCProperties,WCVector,WCLog,WCSystem,WCEnv
등의 파일은 http://www.webdevlib.net에서 다운받아 사용하십시요
소스의 일부분은 고의로 누락한 것은 아닙니다. 모든 소스를 설명하려니 너무 많기때문에
중요한 부분을 추출하여 sample로 구성하면서 최대한 이해가 쉽도록 재구성을 하였습니다.

첨부파일에는 3개의 파일이 zip으로 묶여있습니다.

WCMultipartFormParser.java
WCMultipartFormElement.java
file_upload_progress1.jsp

-- file_upload_progress1.jsp 소스 시작
<%@ page language="java" import="wdl.*,java.util.*,java.sql.*,java.lang.*,java.io.*,java.io.File " contentType="text/html; charset=EUC-KR"%>
<%
    WCPage oPage = new WCPage();
    if (oPage.initCtrl(pageContext) > 0)
    {
        return;
    }
%>
<%@ include file="/wdl/src/java/WCMultipartFormParser.java"%>
<%@ include file="/wdl/src/java/WCMultipartFormElement.java"%>
<%!
public class WCPage
{
    public int initCtrl(javax.servlet.jsp.PageContext oPageContext)
    {
        return initCtrl(
            (javax.servlet.http.HttpServletRequest)oPageContext.getRequest()
            ,(javax.servlet.http.HttpServletResponse)oPageContext.getResponse()
            ,(javax.servlet.jsp.JspWriter)oPageContext.getOut()
            ,(javax.servlet.http.HttpSession)oPageContext.getSession()
            ,(javax.servlet.ServletContext)oPageContext.getServletContext()
            ,oPageContext
            ,(javax.servlet.ServletConfig)oPageContext.getServletConfig()
            );
    }
    public int initCtrl(
        javax.servlet.http.HttpServletRequest oRequest
        ,javax.servlet.http.HttpServletResponse oResponse
        ,javax.servlet.jsp.JspWriter oOut
        ,javax.servlet.http.HttpSession oSession
        ,javax.servlet.ServletContext oApplication
        ,javax.servlet.jsp.PageContext oPageContext
        ,javax.servlet.ServletConfig oConfig)
    {
        try
        {
            m_request = oRequest;
            m_response = oResponse;
            m_out = oOut;
            m_session = oSession;
            m_application = oApplication;
            m_pageContext = oPageContext;
            m_config = oConfig;
            
            if (isMultipart())
            {
                WCMultipartFormParser oFormParser = new WCMultipartFormParser(this);
                oFormParser.setDebug(true);
                oFormParser.init();
                byte[] btDebugBuf = oFormParser.getDebugBuf();
                String sDebug = new String(btDebugBuf);
                this.printOut("<pre>");
                this.printOut(sDebug);
                this.printOut("</pre>");
                
                WCProperties rParam = oFormParser.getParam();
                this.printOut(rParam.serializeOut());

                String sDir = "c:/tmp3";
                oFormParser.saveFile(sDir);
                return 1;
            }
        }
        catch (Exception ex)
        {
        }
        return 0;
    }
    public javax.servlet.http.HttpServletRequest m_request = null; 
    public javax.servlet.http.HttpServletResponse m_response = null; 
    public javax.servlet.jsp.JspWriter m_out = null; 
    public javax.servlet.http.HttpSession m_session = null; 
    public javax.servlet.ServletContext m_application = null; 
    public javax.servlet.jsp.PageContext m_pageContext = null; 
    public javax.servlet.ServletConfig m_config = null; 
    
    public javax.servlet.http.HttpSession getSession()
    {
        return m_session;
    }
    public javax.servlet.http.HttpServletRequest getRequest()
    {
        return m_request;
    }
    public javax.servlet.jsp.PageContext getPageContext()
    {
        return m_pageContext;
    }

    public boolean isMultipart()
    {
        HttpServletRequest oRequest = (javax.servlet.http.HttpServletRequest)m_request;
        String content_type = oRequest.getHeader("content-type");
        if (WCString.indexOf(WCString.toUpper(content_type),"MULTIPART") == 0)
        {
            return true;
        }
        return false;
    }
}
%>

<form name="fParam" encType="multipart/form-data">
<input type="hidden" name="_cmd" value="file_data">
<input type="file" name="file">
</form>

<a href="javascript:uploadFile();">upload the file</a>

<iframe id="ifrmAction" name="ifrmAction" width="0" height="0"></iframe> 

<script>
function uploadFile()
{
    var fParam = window.document.fParam;
    fParam._cmd.value = "uploadFile";
    fParam.method = "post";
    fParam.target = "_blank";
    fParam.submit();
}
</script>
-- file_upload_progress1.jsp 소스 끝

출처 : 고급 웹 UI 개발 라이브러리 Web Development Library 소스공개 : http://www.webdevlib.net

첨부파일 : multipart_form_parser1.zip
첨부파일 :  
multipart_form_parser1.zip   [7 KB]   다운로드 횟수 72 회
Posted by 1010
01.JAVA/Java2009. 6. 16. 19:59
반응형
mkdirs() 라는 메서드(함수)로, 디렉토리(폴더)를 만들 수 있습니다.

mkdirs() 는 디렉토리 생성에 성공하면 true 를 반환하기에, 실패시 에러를 출력하려면 if문 속에서 느낌표를 붙여, 논리값을 반전시켜 주어야 합니다.

같은 이름의 디렉토리가 이미 있을 때나

디렉토리명에 허용되지 않는 문자(*, ? 등)가 있을 때

에는 아래 예제의 경우, "디렉토리 생성 실패"라는 메시지가 출력됩니다.

여러 개의 중첩된 폴더를 한꺼번에 생성하려면 슬래시(/) 기호로 패스를 구분해 줍니다.

mkdir() 이라는 단수형 이름의 메소드로도 디렉토리를 만들 수 있지만, 여러개를 한꺼번에 만들 수는 없습니다.

디렉토리 만들기 예제


소스 파일명: Example.java
import java.io.*;

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

    // MY_TEST_DIR 이라는 하위 폴더 만들기

    File f = new File("MY_TEST_DIR");
    if (!f.mkdirs())
      System.err.println("디렉토리 생성 실패");




    // MY_TEST_DIR 이라는 하위 폴더 밑에
    // 333 이라는 하위 폴더 또 만들기
    // 즉, MY_TEST_DIR/333 이렇게 중첩된 폴더 한꺼번에 생성

    f = new File("MY_TEST_DIR/333");
    if (!f.mkdirs())
      System.err.println("디렉토리 생성 실패");


  }
}


위의 자바 코드를 실행하면, 현재 디렉토리에 MY_TEST_DIR 이라는 폴더가 생기고, 그 안에 333 이라는 폴더가 또 들어 있을 것입니다.


▶▶ Java/자바] 파일 지우기, 디렉토리 삭제 방법; Delete File, Erase Directory

▶▶ Java 자바, 현재 날짜로 디렉토리 생성 예제; Current Date Directory Name

Posted by 1010
01.JAVA/Java2009. 6. 13. 16:42
반응형
Posted by 1010
01.JAVA/Java2009. 6. 13. 16:20
반응형
Java Performance Tuning 2000
Posted by 1010
01.JAVA/Java2009. 6. 13. 16:12
반응형



beginning-jsp-jsf-and-tomcat-web-development-from-novice-to-professional
Posted by 1010
01.JAVA/Java2009. 6. 8. 18:03
반응형

Java에서 HTML 태그를 제거하는 정규식 적용

  1. private String getText(String content) {  
  2.     Pattern SCRIPTS = Pattern.compile("<(no)?script[^>]*>.*?</(no)?script>",Pattern.DOTALL);  
  3.     Pattern STYLE = Pattern.compile("<style[^>]*>.*</style>",Pattern.DOTALL);  
  4.     Pattern TAGS = Pattern.compile("<(\"[^\"]*\"|\'[^\']*\'|[^\'\">])*>");  
  5.     Pattern nTAGS = Pattern.compile("<\\w+\\s+[^<]*\\s*>");  
  6.     Pattern ENTITY_REFS = Pattern.compile("&[^;]+;");  
  7.     Pattern WHITESPACE = Pattern.compile("\\s\\s+");  
  8.       
  9.     Matcher m;  
  10.       
  11.     m = SCRIPTS.matcher(content);  
  12.     content = m.replaceAll("");  
  13.     m = STYLE.matcher(content);  
  14.     content = m.replaceAll("");  
  15.     m = TAGS.matcher(content);  
  16.     content = m.replaceAll("");  
  17.     m = ENTITY_REFS.matcher(content);  
  18.     content = m.replaceAll("");  
  19.     m = WHITESPACE.matcher(content);  
  20.     content = m.replaceAll(" ");          
  21.       
  22.     return content;  
  23. }  
정규식을 6개 정도 적용하고 있는 간단한 소스입니다.
각각 HTML의 스크립트 태그와 내용, 스타일 및 내용, 태그들, 엔터티, 공백문자들을 제거하는 정규식 표현입니다.

관심있는 분들은 한번씩 테스트 해보시기 바랍니다. ^^

아마도 곧 간단한 기능을 하는 것을 오픈해서 보여드릴건데요..
URL을 지정하면 해당 텍스트를 분석해서 자동으로 태깅 정보를 제공하는 겁니다.
마무리 단계이니 완료되는 대로 이 사이트를 통해서 보여드릴께요..

그럼.. 좋은 하루 되세요~~ from 미니(xmlmanager@gmail.com)
Posted by 1010
01.JAVA/Java2009. 6. 7. 01:08
반응형

java enum - enum의 메쏘드

모든 예제는 지난 글에서 썼던 Gender를 그대로 사용합니다. 코드는 아래와 같습니다.

public enum Gender {
    MALE, FEMAIL
}

Static Methods

기본으로 정의되는 static method는 모두 3가집니다.

1. valueOf(String arg)

String 으로 넘긴 값을 기준으로 enum의 원소를 가져 옵니다. 즉, Gender.MALE 과 Gender.valueOf("MALE")은 같습니다.


2. valueOf(Class<T> class, String arg)

클래스를 넘겨서 받습니다. 즉, Gender.MALE 와 Gender.valueOf(Gender.class, "MALE"); 는 같습니다. 사실 valueOf(String arg)는 내부적으로 이 메쏘드를 호출합니다.


3. values()

이건 지난 시간에 설명한 그대로 enum의 요소들을 enum 타입의 배열로 리턴합니다. Gender.values() 는
new Gender[]{Gender.MALE, Gender.FEMALE} 와 같은 값을 가집니다.



Static이 아닌 Method

1. name()
호출된 값의 이름을 리턴합니다.
Gender.MALE.name() 은 "MALE" 이라는 String 값을 가져옵니다.

2. ordinal()
정의된 순서를 리턴합니다. 0부터 시작합니다.
즉, Gender.MALE.ordinal() 은 0을 Gender.FEMALE.ordinal()은 1을 리턴합니다.

3. compareTo(E o)
E는 자기 자신입니다. 예제로 쓴 Gender의 경우는 Gender가 될 겁니다.
이는 ordinal()을 호출해서 비교합니다. 요소들 간에 어떤 순서가 있을 때 쓰면 됩니다.(요일이 좋은 예가 되겠습니다.)
모든 enum은 Comparable을 구현하고 있습니다. Comparable 인터페이스에는 정의된 compareTo 메쏘드를 구현한 것입니다. 더 자세한 것은 다음 글에서 다루겠습니다.

기타 다른 메쏘드들은 java.lang.Object에 정의된 메쏘드들이거나 java.lang.Class에서 따온 메쏘드들이므로 설명하지 않겠습니다.


enum의 확장

Gender 별로 웃음 소리를 저장하려고 합니다. Gender를 다음과 같이 변경시킵니다.

public enum Gender {
    MALE("하하")
    , FEMAIL("호호");
   
    private String sound;
    Gender(String arg){
        this.sound = arg;
    }
    String getSound(){
        return sound;
    }

}

일반적인 class의 생성자나 메쏘드를 만들 듯이 만들면 됩니다.
위의 코드의 경우 Gender.MALE.getSound()는 "하하"를 리턴합니다
Posted by 1010
01.JAVA/Java2009. 6. 4. 18:06
반응형

Tomcat을 사용하다가 java application 실행 시
java.lang.OutOfMemoryError: Java heap space 에러 생겼을 때 해결방법.


생기는 경우의 수가 많이 있을 것 같지만, 이번에 아래의 스크립트로 해겼되었으므로 적어놔야 겠다.

----

이번 경우는 Confluence Wiki 설치 중, 어느 부분에서 페이지가 넘어가지 못하고 먹통이 되었다가 결국 아래의 에러가 발생했다. 

java.lang.OutOfMemoryError: Java heap space

Confluence Wiki와 같은 Java 어플리케이션은 JVM에서 구동된다. 따라서 시작 시 JVM에서 일정량의 메모리를 할당하여 어플리케이션에서 사용된다. 기본적으로 Java 가상머신은 서버에 얼마나 많은 물리적인 메모리가 설치되있더라도 오직 64MB의 메모리만을 할당된다고 한다.
따라서 Confluence Wiki같은 중간규모 이상의 어플리케이션은 늘리필요가 있다고 한다.

늘리는 방법을 찾느냐 조금 시간이 걸렸다.
Linux, Java, Tomcat에 능통한 사람이면 금방 찾을 수 있지만, 전혀 찾을 수 없었다.
그래서 여기저기 해결방법을 짜집기 하다가 힌트를 얻었고 스크립트를 작성하였다.

** tomcat 5.5 기준임 **

/usr/local/tomcat/bin 에 tomcat.sh를 하나 만들자. (/usr/local/ 는 사람마다 다를 수 있슴)

> cd  /usr/local/tomcat/bin
> vi tomcat5.sh

tomcat5.sh 파일내용

#!/bin/sh
# file:tomcat.sh
CLASSPATH=/usr/java/jdk1.5.0_15/lib
JAVA_HOME=/usr/java/jdk1.5.0_15
CATALINA_OPTS="-Djava.awt.headless=true"
JAVA_OPTS="-Xms512m -Xmx512m"

export CLASSPATH
export JAVA_HOME
export CATALINA_OPTS
export JAVA_OPTS

case "$1" in
start)
echo "Starting tomcat5..."
/usr/local/tomcat/bin/startup.sh
;;
stop)
echo "Stopping tomcat5..."
/usr/local/tomcat/bin/shutdown.sh
;;
*)
echo "Usage tomcat.sh start/stop"
exit 1;;
esac

tomcat 시작

> tomcat.sh stop
> tomcat.sh start
 
Posted by 1010
01.JAVA/Java2009. 6. 4. 18:04
반응형

java.lang.OutOfMemoryError: PermGen space

요즘 들어 부쩍 java.lang.OutOfMemoryErorr로 인해 이클립스가 뻗어버리는 일이 많이 발생했었다. 하지만 Heap Monitor를 보면 200M 조차 사용하지 않는다. 이런 경우, 대부분은 PermGen 영역이 모자란 것이 원인일 수 있다.

{workspace}/.metadata/.log를 확인해보면 PermGen space라고 기록되어 있을 것이다.

Eclipse를 사용할 때는 JVM에 -Xmx 옵션은 대부분은 넣어서 사용하리라 생각한다. 하지만 Java는 메모리 영역을 사실상 두 부분으로 구분하여 사용한다. 일반 Java Heap space와 클래스와 같이 Permenant Generation 대상 데이터를 두기 위한 PermGen space이다.

대부분의 자바 애플리케이션에서는 기본 PermGen Size로 충분하겠지만 이클립스의 경우 클래스가 꽤 많아지면서 모자란 경우가 있는듯 하다. javanese의 경우 Callisto를 깔아놓고 JDT, CDT를 왔다갔다 하면서 사용하다보니 Heap은 별로 쓰지도 않는데 PermGen space가 종종 모자라는 경우가 있다. 아마 Web관련 Tool을 많이 사용하는 분도 같은 현상이 나타날 수 있을 것이다.

PermGen space는 -XX:MaxPermSize 옵션으로 설정할 수 있다.

eclipse -vm /usr/lib/jvm/java-1.5.0-sun/bin/java -vmargs -XX:MaxPermSize=128m -Xms128m -Xmx512m

OutOfMemory 에러가 발생한다면 -Xmx만 늘려주지말고 PermSize도 확인해보라.

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

java.lang.OutOfMemoryError 

                     2005-05-31     송학렬    ㈜아이티플러스 기술지원부

이 문서는 기술지원 또는 개발 시 java.lang.OutOfMemoryError 를 만났을 때 원인 파악 및 해결방안 입니다.

java.lang.OutOfMemoryError 에는 크게 2가지 패턴이 있다고 볼 수 있습니다.(전적으로 개인적인 생각이지만..^^)

Java heap 메모리가 정말로 Full 되서 나는 종류가 있고 그렇지 않은데도 나는 종류가 있습니다.

그 둘 중에 어는 것 인지부터 가려내는 것이 가장 먼저 선행되어야 합니다.

Java 가상머신에는 메모리 구조가 여러단계로 나뉘어 져 있으므로 어느 영역에 의해 java.lang.OutOfMemoryError 가 나는지 알기 위해 JAVA OPTION으로 싸이트가 안정화 되기 전까진 verbosegc 또는 -XX:+PrintGCDetails  옵션을 추가해 놓는 것이 java.lang.OutOfMemoryError 났을 때를 대비해 좋은 습관이라 할 수 있습니다.

-verbosegc 또는  -XX:+PrintGCDetails  옵션으로 로그에 남는 heap 메모리 정보를 본 후 java.lang.OutOfMemoryError 가 날 때 heap이 꽉 차서 나는 것인지 아닌지 부터 판단합니다.

1.     Heap Memory Full 차지 않았을 때 1)     Perm 영역이 full 되는 경우

Permanent generation is full…

increase MaxPermSize (current capacity is set to: 134217728 bytes)

[Full GC[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor31282]

 810207K->802132K(1013632K), 8.3480617 secs]

<GC: 2 4  2465625.831280 10348 0 31 113802808 105534632 286326784 0 0 35782656 715849728 715848840 715849728 134217720 134023296 134217728 8.348677 8.348677 >

Passwd Check =============

<2005. 5. 19. 오전 9 32 23 KST> <Error> <HTTP> <BEA-101017> <[ServletContext(id=2536415,name=/,context-path=)] Root cause of ServletException.

java.lang.OutOfMemoryError

위와 같은 case 인 경우네는 Java 가상머신중에 Perm 영역이 full 차는 경우 입니다. 

Perm 영역에는 class object 및 관련된 meta data가 로드되는 곳인데 싸이트가 매우 많은 수의 class를 사용하는 경우 늘려줘야 하는 case도 있습니다.

얼마가 적정한 사이즈란 정답이 없는 것 같고 max가 계속 늘어나지 않고 일정한 사이즈를 유지 하면 됩니다.

             위 에러가 났을때는 -XX:MaxPermSize=256m  옵션으로 사이즈를 적당하게 늘려주는게 방

             법이며 늘려주었는데도 불구하고 Full 차는 시간만 늘어날 뿐 계속 사이즈가 늘어난다면 이 영역은 일반 비즈니스 프로그램으로 핸들링 할 수 없는 영역이므로 WAS 제품의 버그 및 jdk 버그로 보는 것이 일반적입니다.

       

2)     MAXDSIZ 사이즈 관련

  - Exception in thread “CompileThread0″ java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate

Possible causes:

         - not enough swap space left, or

         - kernel parameter MAXDSIZ is very small.

-          java.lang.OutOfMemoryError: unable to create new native thread

 

위 두 에러가 나는 이유는 Data 사이즈가 Full 차서 더 이상 메모리 할당을 할 수 없다는 java.lang.OutOfMemoryError 입니다.

Jdk도 내부적으로 c 라이브러리를 쓰고 jni를 통해서 c프로그램을 호출할 수 도 있는 환경에서 Data 영역이상으로 메모리 사용 시 위 에러를 만날 수 있습니다.

Heap 영역에는 java heap C heap이 있는데 C heap Data 메모리 영역에 영향을 미치는 것으로 보이며 보통 C의 전역 변수들이 잡히는 영역입니다.

위 현상을 만났을 때는 hp os MAXDSIZ가 너무 작게 잡혀있지 않은지 확인 후 적당한 크기로 늘려 줘야 합니다.

Glance 에서 shift+m 을 누른 후 jvm pid를 누르면 java가 사용하는 Data 사이즈를 모니터링 할 수 있습니다.

모니터링을 통해 적정한 사이즈로 MAXDSIZ를 늘려주어야 하며 만일 늘려 준게 에러 발생의 시간만 지연 시킬 뿐 계속 사용량이 늘어난다면 이는 사용하는 c라이브러리 쪽에 메모리 릭 버그가 있는 것이므로 c라이브러리를 체크 하셔야 합니다.

java.lang.OutOfMemoryError: unable to create new native thread

이 경우는 프로그램에서 Thread pool 프로그램 실수로 필요이상으로 쓰레드가 생성되는 경우도 과도하게 메모리를 사용할 수 있으므로 jvm 쓰레드 덤프를 통해 과도한 쓰레드가 생성되지 않았는지도 확인해 보셔야 합니다.

2.     Heap Full 찾을 때

이 경우는 java가 사용하는 heap 영역이 Full 되서 java.lang.OutOfMemoryError 가 나는 경우 인데 두 가지 패턴이 있습니다.

순간적으로 대량의 데이터를 메모리에 올리는 프로그램이 실행되어 문제를 야기 할수 있으며 다른 한 가지는 조금씩 메모리 릭이 발생하여 점차적으로 메모리가 쌓여 가는 경우 입니다.

두 가지 중에  어느 것인지 구별하는 것이 중요하며 이를 위해서도 마찬가지로 -verbosegc 또는  -XX:+PrintGCDetails  로그를 통해 순간적으로 메모리가 차는 것인지 조금씩 메모리가 차는 것인지를 확인하셔야 합니다.

1) 특정 프로그램의 특정시점의 과도한 메모리 사용에 의한 경우

                특정 프로그램이 과도하게 heap 메모리 이상 메모리를 사용하면서

java.lang.OutOfMemoryError가 발생하는 경우는 이 에러가 발생하는 시점의 쓰레드 덤프를 통해 어느 프로그램인지 쉽게 찾을 수 있습니다.

쓰레드 덤프에 메모리를 쓸만한 프로그램은 어느 정도의 자바프로그램 경험이 있으면 찾을 수 있습니다.

Ex)

“ExecuteThread: ‘36′ for queue: ‘default’” daemon prio=10 tid=0×0048e7b0 nid=48 lwp_id=4139729 runnable [0x23f32000..0x23f30500]

          at java.net.SocketInputStream.socketRead(Native Method)

          at java.net.SocketInputStream.read(Unknown Source)

          at oracle.net.ns.Packet.receive(Unknown Source)

          at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source)

          at oracle.net.ns.NetInputStream.read(Unknown Source)

          at oracle.net.ns.NetInputStream.read(Unknown Source)

          at oracle.net.ns.NetInputStream.read(Unknown Source)

          at oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:718)

          at oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:690)

          at oracle.jdbc.ttc7.Oall7.receive(Oall7.java:373)

          at oracle.jdbc.ttc7.TTC7Protocol.doOall7(TTC7Protocol.java:1405)

          at oracle.jdbc.ttc7.TTC7Protocol.fetch(TTC7Protocol.java:889)

          - locked <0×35e8e3b0> (a oracle.jdbc.ttc7.TTC7Protocol)

          at oracle.jdbc.driver.OracleResultSetImpl.next(OracleResultSetImpl.java:242)

          - locked <0×36f66c98> (a oracle.jdbc.driver.OracleResultSetImpl)

          at weblogic.jdbc.pool.ResultSet.next(ResultSet.java:180)

          at Dcard.AAA.ejb.monitor.member.wbbb.WACBean.getInfoList(WACBean.java:5789)

java.lang.OutOfMemoryError 가 날 상황에 쓰레드 덤프를 두 세번 떠서 같은 쓰레드 번호로 위 같은 로직이 오래 결려있다면 이는 프로그램에서 while(rs.next()) 를 오랜 기간 돌면서 메모리에 DB로부터 읽어서 올리고 있다는 것을 의미 합니다 대량 데이터 조회가 일어나는 경우인 것 입니다.

이런 식으로 특정 프로그램의 특정 시점에 과도한 메모리 사용으로 인한 java.lang.OutOfMemoryError 에러는 쓰레드 덤프를 통해 찾을 수 있습니다.

물론 2번에서 설명 할 heap dump를 통해서도 찾을 수 있습니다.

2) 메모리 릭에 의해 조금씩 메모리가 쌓인 경우

JVM위 에서 실행중인 프로그램중에 어떤 것이 GC 대상에서 제외되는 영역에 data를 조금씩 쌓고 있다는 얘기입니다.

GC 대상에서 제외되는 영역은 다음과 같은 곳이 있습니다.

- Http Session에 넣는 데이터..(세션 타임아웃 또는 invilidate 씨 까지 제외됨)

- Static 변수

- 서블릿 또는 jsp의 멤버변수 ( WAS 기동 후 최초 호출 시 인스턴스 화 되어 WAS가 내려 갈 때 까지 사라지지 않음 )

- EJB의 멤버변수( pool안에서 객체가 존재하는 한 GC대상에서 제외)

          위 같은 영역에 프로그램에서 data add 하는 구조를 메모리 릭 이라고 할 수 있습니다.

           IBM 또는 SUN JDK 인 경우에는 heapdump를 통해서 분석하여 어느 데이터가 메모리를 많이 잡고 있는지를 알 수 있습니다.

           Heapdump 사용법 및 분석 법은 다음을 참조 하시면 됩니다.

 http://www.alphaworks.ibm.com/aw.nsf/FAQs/heaproots

http://www-1.ibm.com/support/docview.wss?uid=swg21190476

http://www-1.ibm.com/support/docview.wss?rs=180&context=SSEQTP&q1=heapdump+solaris&uid=swg21190608&loc=en_US&cs=utf-8&lang=en

http://www.skywayradio.com/tech/WAS51/IBMHeapDump/

출처 : http://www.javaservice.net/~java/bbs/read.cgi?m=etc&b=jdk&c=r_p&n=1117521098&p=1&s=t#1117521098

var viewer_image_url = “http://blogimgs.naver.com/blog20/blog/layout_photo/viewer/”; var photo = new PhotoLayer(parent.parent.parent); photo.Initialized(); window.onunload = function() { photo.oPhotoFrame.doFrameMainClose(); }.bind(this);

Posted by 1010
01.JAVA/Java2009. 6. 4. 14:44
반응형
C:\Documents and Settings\Administrator>emctl start dbconsole
Environment variable ORACLE_SID not defined. Please define it.

C:\Documents and Settings\Administrator>set ORACLE_SID=orcl

C:\Documents and Settings\Administrator>emctl start dbconsole
OC4J Configuration issue. C:\oracle\product\10.2.0\db_1/oc4j/j2ee/OC4J_DBConsole
_192.168.1.66_orcl not found.

C:\Documents and Settings\Administrator>emctl start dbconsole
EM Configuration issue. C:\oracle\product\10.2.0\db_1/192.168.1.66_orcl not foun
d.

C:\Documents and Settings\Administrator>emctl start dbconsole
Oracle Enterprise Manager 10g Database Control Release 10.2.0.1.0
Copyright (c) 1996, 2005 Oracle Corporation. All rights reserved.
http://ts:1158/em/console/aboutApplication
Starting Oracle Enterprise Manager 10g Database Control ...OracleDBConsoleorcl
서비스를 시작합니다..
OracleDBConsoleorcl 서비스를 시작할 수 없습니다.

시스템 오류가 발생했습니다.

시스템 오류 3이(가) 생겼습니다.

지정된 경로를 찾을 수 없습니다.


C:\Documents and Settings\Administrator>emctl start dbconsole
Oracle Enterprise Manager 10g Database Control Release 10.2.0.1.0
Copyright (c) 1996, 2005 Oracle Corporation. All rights reserved.
http://ts:1158/em/console/aboutApplication
Starting Oracle Enterprise Manager 10g Database Control ...OracleDBConsoleorcl
서비스를 시작합니다.................
OracleDBConsoleorcl 서비스가 잘 시작되었습니다.


C:\Documents and Settings\Administrator>


해결방법

C:\WINDOWS\system32\drivers\etc

의 host화일을 수정한다

현재 사용중인 pc 의 이름과 ip를 매칭시켜주면된다.


192.168.1.66 ts

이런식으로 추가하여준다.
Posted by 1010
01.JAVA/Java2009. 5. 30. 14:03
반응형
JAVA basic(scjp 1[1].5)
Posted by 1010
01.JAVA/Java2009. 4. 28. 16:10
반응형

package struts02.util;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import org.apache.struts.upload.FormFile;

public class BoardUtil {


 public static String saveFile(FormFile uploadFile) {
  String physicalFileName=null;
  InputStream is;
  try {
   is = uploadFile.getInputStream();
   String uploadFileName = uploadFile.getFileName();
   physicalFileName = getPhysicalFileName( uploadFileName );
   String filePath = "F:/Struts_And_iBatis/workspace/struts-board-02/WebContent/upload/";
   OutputStream os = new FileOutputStream(filePath + physicalFileName);

   int byteRead = 0;
   byte[] buf = new byte[8192];
   while ((byteRead = is.read(buf)) != -1) {
    os.write(buf, 0, byteRead);
   }
   os.close();
   is.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return physicalFileName;
 }//end saveFile()

 private static String getPhysicalFileName(String uploadFileName) {
  String systemTime=new Date().getTime()+"";//
  if( uploadFileName.indexOf(".") == -1 ){ //파일이름에 .이 없으면
   return uploadFileName+"_"+systemTime;
  }else{
   int index = uploadFileName.lastIndexOf(".");
   //확장자를뺀파일명
   String _tmpFileName = uploadFileName.substring(0, index);
   // Extension
   String _extName = uploadFileName.substring( index );
   return _tmpFileName + "_"+systemTime+_extName;
  }
 }

}

Posted by 1010
01.JAVA/Java2009. 4. 28. 15:40
반응형
oracle 의 clob 타입으로 jsp에서 select,insert,update 방법을 예제로 만들어 봤습니다.

참고하시기 바랍니다.
Posted by 1010
01.JAVA/Java2009. 4. 24. 13:25
반응형

일주일에 한번, 하루에 한번 작업을 수행하는 프로세스를 실행하고 싶을 때가 있을 껍니다.
한가한 시간에 자동으로 배치작업을 실행하는 등의 작업을 자바에서 수행할 수 있습니다.
Timer라는 클래스에다가 시작날짜, 시간을 설정한 뒤, TimerTask클래스를 상속받은 클래스에서 run메소드를 구현하게 되면 설정된 시간에 run메소드가 자동으로 수행되게 됩니다.

코드를 보도록 합시다.


package com.mudchobo.scheduler;

import java.util.TimerTask;

public class WeeklySearch extends TimerTask {

 @Override
 public void run() {
  System.out.println("WeeklySearch!");
 }
}

TimerTask를 상속받아서 run메소드를 구현했습니다. run메소드는 간단히 WeeklySearch라고 보여주는군요.

그럼 메인을 보도록 합시다.

package com.mudchobo.scheduler;

import java.util.Calendar;
import java.util.Timer;

public class Scheduler {

 public static void main(String[] args) {
  WeeklySearch weeklySearch = new WeeklySearch();
  
  Timer timer = new Timer();
  Calendar date = Calendar.getInstance();
  date.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
  date.set(Calendar.AM_PM, Calendar.PM);
  date.set(Calendar.HOUR, 11);
  date.set(Calendar.MINUTE, 29);
  date.set(Calendar.SECOND, 0);
  date.set(Calendar.MILLISECOND, 0);
  
  timer.scheduleAtFixedRate(weeklySearch, date.getTime(), 
    1000 * 60 * 60 * 24 * 7);
 }
}

Timer객체, Calendar객체를 선언합니다. Calendar객체에는 이 스케쥴이 시작될 시간을 설정해서 넣습니다. 그 뒤에 timer에 있는 scheduleAtFixedRate메소드에 첫번째 인자는 맨 위에서 생성한 TimerTask객체를 넣으면 되구요. 두번째는 이 스케쥴이 시작될 시간을 설정해서 넣으면 되구요. 3번째는 얼마만큼의 주기로 실행될 지 기간을 설정하게 됩니다.
밀리초여서 1000밀리초 * 60초 * 60분 * 24시간 * 7일 하게 되면 저것은 1주일에 한번 실행되게 됩니다.

이상입니다!


출처 : http://mudchobo.tomeii.com/tt/category/자바(Java)?page=5
Posted by 1010
01.JAVA/Java2009. 4. 14. 11:55
반응형

자바에서는 파일을 복사하는 것은 그리 어렵지 않습니다.

자바에는 풍부한 I/O 클래스가 많기 때문에 유연성있게 사용할 I/O 객체가 많습니다.

만약 특정파일을 디스크에서 디스크로 복사하는 것이 아니라 네트워크를 이용해서 파일을

다른 컴퓨터로 복사하다면 어떨까요?

자바에서는 이 또한 그리 어렵지 않습니다.

 

TCP 네트워크 Socket 객체를 얻기만 한다면 Socket에서 InputStream, OutputStream

얻을 수 있고, 자바 I/O 객체를 이용해서 InputStream에서 읽고 OutputStream으로 쓰기만

하면 네트워크에서 읽고 쓰기가 되는 것이니까요.

 

자바 I/O 객체를 이용해서 파일을 복사하는 경우할 때 복사할 원본 파일을 읽는 프로그램이

결국 대상 파일을 만듭니다. 파일을 읽는 것, 파일을 쓰는 것이 같은 버추얼 머신에 의해서

실행됩니다. 하지만 네트워크를 이용해서 복사를 하는 경우에는 파일을 읽어서

네트워크로 보내는 프로그램(클라이언트)과 네트워크로부터 데이터를 읽어서 파일에 쓰기를

하는 프로그램(서버)으로 나눌 수 있을 것입니다.

그럼 이와 같이 네트워크를 통해서 파일을 복사하는 프로그램을 만들어 보겠습니다.

TCP 네트워크 프로그램에서는 네트워크에 참여하는 참여자가 항상 둘인데 거의 대부분

클라이언트, 서버의 서비스 구조입니다.

 

 

package tcp;

 

import java.io.*;

import java.net.*;

 

/**

* 스트림 복사를 합니다.

*/

public interface Zerox {

            /**

            * InputStream로 부터 읽은 데이터를 OutputStream으로 보냅니다.

            * @param is         InputStream

            * @param os                      OutputStream

            * @exception        IOException

            */

            public void copy(InputStream is, OutputStream os)

                          throws IOException;

}

예제 11 - 3 Zerox.java

 

Zerox 인터페이스는 public void copy(InputStream, OutputStream) 메소드를 하나 선언

했는데, 그 이름에서 짐작하듯이 InputStream으로부터 데이터를 읽고,그 읽은 데이터를

OutputStream으로 씁니다. 복사의 기본이 읽은 것을 읽은 그대로 쓰는 것이기 때문입니다.

 

먼저 TCP 네트워크 서버를 살펴보겠습니다.

 

package tcp;

 

import java.io.*;

import java.net.*;

 

/**

* 스트림 복사를 합니다.

*/

public class CopyServer implements Zerox{

 

            /**

            * InputStream로 부터 읽은 데이터를 OutputStream으로 보냅니다.

            * @param is         InputStream

            * @param os                      OutputStream

            * @exception        IOException

            */

            public void copy(InputStream is, OutputStream os)

                          throws IOException {

                          int c = -1;

                          while((c = is.read()) != -1) {

                                        os.write(c);

                          }

                          os.flush();

            }

           

            public static void main(String[] args) throws Exception {

                          /*

                          데이타 Copy를 위해서 네트워크 InputStream 생성

                          */

                          ServerSocket ss = new ServerSocket(8989);                 

                          Socket s = ss.accept();                               

                          InputStream is = s.getInputStream();                             

                         

                          /*

                          데이타 Copy를 위한 파일 OutputStream 생성

                          */                                                 

                          OutputStream os = new FileOutputStream(new File(args[0]));     

 

                          /*

                          데이타 Copy를 위한 Zerox 생성

                          */

                          Zerox zerox = new CopyServer();                               

                          /*

                          데이타 Copy - InputStream 데이타를 OutputStream으로 복사                

                          */                       

                          zerox.copy(is,os);             

 

                          /* 네트워크 자원 해제 */

                          os.close();                                                                                                                                 

                          is.close();                                                                                                                                 

                          s.close();                                                                                                                                   

            }

}

예제 11 - 4 CopyServer.java

 

CopyServer는 우선 Zerox 인터페이스를 구현했습니다.

CopyServer가 구현한 public void copy(InputStream, OutputStream)을 살펴보면

InputStread에서 한 바이트를 읽고 읽은 바이트를 그대로 OutputStream으로 쓰는데,

이러한 행동을 InputStream으로부터 더 이상 읽을 데이터가 없을 때 까지 계속 반복하고

있습니다.InputStream은 복사할 원래의 데이터소스로부터 만들어진 것이니,

InputStream의 마지막에 이를 때까지 읽고,쓰기를 반복하면 결국엔 OutputStream으로는

원래의 데이터소스에 있던 모든 데이터가 씌여지는 셈입니다.복사의 기본입니다.

InputStream으로부터 데이타를 모두 읽은후에는 버퍼에 있을지 모를 데이터를

flush() 메소드를 호출해서 강제적으로 OutputStream으로 씁니다.

 

CopyServer public static void main(String[])CopyServerTCP 서버로 동작하도록

환경을 설정합니다.

우선 TCP 8989포트로 ServerSocket을 만들고 있습니다. 그리고 클라이언트가 TCP 연결을

하기를 기다리고 있습니다. 클라이언트가 TCP 연결을 한다면 public Socket accept()

메소드가 Socket을 리턴합니다. CopyServer는 대부분의 삶을 public Socket accept()에서

머물러 있습니다. 일단 Socket이 만들어졌다는 것은 TCP 연결이 된 것입니다.

Socket으로부터 InputStreamOutputStream을 얻습니다.

물론 이제부터는 자바의 I/O객체를 이용해서 마음껏 읽고 쓸수 있습니다. 

CopyServer는 복사할 대상 파일의 OutputStreamFileOutputStream으로 합니다.

InputStream OutputStream은 복사를 담당하는 Zeroxcopy(InputStream,OutputStream)

메소드의 인자로 쓰여집니다.

Zerox는 그 원래 만들어진 것이 오로지 InputStream으로 읽은 데이터를 OutputStream으로

쓰기만 하므로 , 결국 여기서는 네트워크 스트림으로부터 데이터를 읽어서 파일을 의미하는

OutputStream으로 쓰는 행동을 합니다.

CopyServer는 다 사용한 시스템자원(네트워크 자원)을 해제하는데,TCP 네트워크 연결과

같은 시스템 자원은 열린 자원(Open Resources)라고 해서 사용한 후에는 반드시 정리해

주는 습관을 같져야 합니다. 자바의 가비지 컬렉터(Garbage Collector)는 열린 자원에 대해

서는 청소를 하지 않기 때문입니다.

열린 자원은 프로그래머가 명시적으로 정리하지 않으면 시스템 자원이 물 새듯 새나가고,

언젠가는 큰 낭패를 당합니다.

 

 

이젠 TCP 네트워크 클라이언트를 살펴보겠습니다.

 

package tcp;

 

import java.io.*;

import java.net.*;

/**

* 스트림 복사를 합니다.

*/

public class CopyClient implements Zerox{

 

            /**

            * InputStream로 부터 읽은 데이터를 OutputStream으로 보냅니다.

            * @param is         InputStream

            * @param os                      OutputStream

            * @exception        IOException

            */

            public void copy(InputStream is, OutputStream os)

                          throws IOException {

                          int c = -1;

                          /*

                           InputStream is로 부터 EOF일때까지 데이타를  읽고,

                           읽은 데이타를 OutputStream os로 보냅니다.

                          */

                          while((c = is.read()) != -1) {

                                        os.write(c);

                          }

                          os.flush();            // OutputStream 버퍼에 있을 수 있는 데이타를 강제 출력

            }

           

            public static void main(String[] args) throws Exception {

 

                          /*

                          데이타 Copy를 위해서 파일 InputStream 생성

                          */                       

                          InputStream is = new FileInputStream(new File(args[0]));           

                         

                          /*

                          데이타 Copy를 위해서 네트워크 OutputStream 생성

                          */                       

                          Socket s = new Socket("localhost",8989);                                                           

                          OutputStream os = s.getOutputStream();                                                                           

 

                          /*

                          데이타 Copy를 위한 Zerox 생성

                          */

                          Zerox zerox = new CopyClient();                   

                          /*

                          데이타 Copy - InputStream 데이타를 OutputStream으로 복사                

                          */                                                                                                     

                          zerox.copy(is,os);                                                                                                                                   

 

                          /*

                          네트워크 자원 해제

                          */

                          is.close();                                                                                                                                                                         

                          os.close();                                                                                                                                                         

                          s.close();                                                                                           

            }

}

예제 11 - 5 CopyClient.java

 

CopyClient 역시 CopyServer와 마찬가지로 TCP기반의 Socket 객체를 사용하고 있는터라

tcp 패키지에 속하게 했습니다.

 

CopyClient에서 눈여겨 볼 것은 Socket 객체의 생성자에 사용된 두개의 인자인 “localhost”

8989의 값입니다.

localhost TCP 네트워크 연결을 하고자한는 서버가 위치한 컴퓨터의 IP 주소를

말합니다. 8989는 서버가 서비스하는 포트를 의미합니다.

 

CopyClient가 서비스를 받으려하는 CopyServerTCP 8989로 서비스하고 있으므로

클라이언트는 TCP 포트 8989로 네트워크 연결을 해야합니다.

localhost “127.0.0.1”IP 주소에 대한 또 다른 이름이며, "127.0.0.1"Loopback

주소로 자기자신의 IP주소와 같다고 컴퓨터입니다.

예제 11 - 5CopyClient가 서버의 IP 주소를 "localhost"라고 한 것은 CopyServer

CopyClient를 실행하는 컴퓨터에서 Listen하면서 서비스를 제공하고 있기 때문입니다.

 

CopyClient역시 Zerox이므로 Zeroxpublic void copy(InputStream, OutputStream)

이용합니다. FileInputStream에서 데이타를 읽어서 TCP 네트워크에서 만들어진

OutputStream으로 데이터를 쓰습니다. 여기서 TCP 트워크 반대쪽에서는 서버가 열심히

정보를 데이터를 읽고 있을 것입니다.

CopyClient 역시 사용한 시스템 자원을 정리하고 있습니다.

Zerox 인터페이스를 보면 마치 로컬에서 파일을 복사하는 형태를 가지지만

CopyServer, CopyClient는 가장 기본적인 TCP 네트워크로부터 읽고,쓰기를 보여줍니다.


 

 

  

 

그림 11 - 6TCP 네트워크 서버인 tcp.CopyServer를 실행시킨 모습입니다.

그리고 아래 그림 11 - 7tcp.CopyClient를 실행시킨 모습이구요.

src 폴더아래의 Zerox.java 를 현재 폴더 Zerox.copy로 복사하는 내용입니다.

 


 

사용자 삽입 이미지

 

 

Posted by 1010
01.JAVA/Java2009. 4. 7. 11:08
반응형

출처 : http://sinuk.egloos.com/2676307

1. JNI (Java Native Interface) 란 ?

- 자바가 다른 언어로 만들어진 어플리케이션과 상호 작용할 수 있는 인터페이스를 제공한다.

- 자바가상머신(JVM)이 원시 메소드(native method)를 적재(locate)하고 수행(invoke)할 수 있도록 한다

- JNI가 자바가상머신내에 포함됨으로써, 자바가상머신이 호스트 운영체제상의 입출력, 그래픽스, 네트워킹, 그리고 스레드와 같은 기능들을 작동하기 위한 로컬시스템호출(local system calls)을 수행할 수 있도록 한다.

* 쉽게 말해 Java와 다른 언어를 연동하는 솔루션입니다.


[그림1] C로 만들어진 Library와 JAVA를 연결해주는 JNI




2. Why do you need JNI ?


자 바 네이티브 메쏘드(Java Native method, 이하 JNI)는 다른 언어로 작성된 코드를 자바에서 호출하도록 만들어진 규약이다. 현재는 C/C++에 대한 호출만을 정확하게 지원한다. 어떻게 보면 JNI는 자바가 만들어진 철학과 정반대되는 것이다.


그러나. Java에도 한계가 있다.


1. 속도 문제가 있는 계산 루틴
 > 자바가 Native Code(플랫폼에 종속적인 기계어 코드)에 비해 느리다.

2. 자바에서 하드웨어 제어

3. 자바에서 지원되지 않은 특정 운영체제 서비스
 > 자바의 클래스 라이브러리는 방대하고 다양한 서비스를 제공하지만, 특정 플랫폼에서 제공하는 고유의 서비스의 기능을 모두 포함할 수는 없다. 특히, 특수한 목적으로 제작된 하드웨어를 자바에서 제어해야 할 필요가 있다고 한다면, 자바만으로 해결하기는 힘들다.

4. 기존의 프로그램에서 자바가 제공하는 서비스를 이용
 > 기존에 작성된 프로그램이나 기존의 시스템(legacy)과의 연계 문제


∴ JNI를 써서 해결해보자.



3. C를 이용한 JNI 예제

VC++을 이용해 C문법으로 작성되어 만들어진 DLL을 로딩하여 Java에서 사용해보겠습니다.


1단계 : Native Method를 선언하는 자바 클래스 작성
2단계 : 1단계에서 작성한 클래스 컴파일
3단계 : javah를 사용해서 Native Method가 사용할 헤더 파일 생성
4단계 : C언어로 Native Method 실제 구현
5단계 : C 코드와 헤더 파일을 컴파일
6단계 : 자바 프로그램 실행


 

1단계 : Native Method를 선언하는 자바 클래스 작성

Java 소스 파일 : HelloJni_Jsource.java


import java.util.*;

class HelloJniClass {
   native void Hello();

  static {  System.loadLibrary("Hello_DLL");   }

  public static void main(String args[]) {   
      HelloJniClass myJNI=new HelloJniClass();
      myJNI.Hello();
   }
}


// 아래는 좀 위의 내용 보충 그림





2단계 : 1단계에서 작성한 클래스 컴파일



* 컴파일시에는 일반 java 컴파일때와 마찬가지로 환경변수 셋팅이 되어 있어야 합니다.
 -> Path가 JDK의 Javac.exe가 있는 폴더에 설정되어 있어야 합니다.



3단계 : javah를 사용해서 Native Method가 사용할 헤더 파일 생성


HelloJniClass.h을 열어보면

JNIEXPORT void JNICALL Java_HelloJniClass_Hello  (JNIEnv *, jobject);
위의 함수를 Implement만 해서 DLL을 만들면 됩니다. (4단계)


4단계 : C언어로 Native Method 실제 구현(1)

1) VC++ 프로젝트 만들기 : Win32용 DLL 프로젝트로 만듭니다.
New - Projects : Win32 Dynamic-Link Library

2) Add Files Projects : HelloJniClass.h 파일 추가

3) Projects Setings(Alt+F7)
   - Link탭에 Output file Name : 1단계의 2. 라이브러리 적재시 작성한 DLL파일명(Hello_DLL.dll)
   - C/C++탭 Preprocessor 카테고리의 Additional Include directories
       JDK의 Include폴더와 Include폴더 밑의 win32폴더

          예) C:\Program Files\Java\jdk1.5.0_03\include\,
             C:\Program Files\Java\jdk1.5.0_03\include\win32




 


4. 값의 전달과 리턴

 

1단계 : Java 소스 파일 StringPass_Jsource.java
* 일반 자바 메쏘드 선언과 동일합니다.

class JNI_Message {
   native byte[] Message(String input);

  // 라이브러리 적재(Load the library) 

  static {
    System.loadLibrary("Msg_DLL");
  }


  public static void main(String args[]) {   
 byte buf[];

    // 클래스 인스턴스 생성(Create class instance)
    JNI_Message myJNI=new JNI_Message();

    // 원시 메소드에 값을 주고 받음
    buf = myJNI.Message("Apple");
 
 System.out.print(buf); // 받은값 출력
 }
}



2단계 : 컴파일
 javac StringPass_Jsource.java


3단계 : header파일 생성
 javah JNI_Message


4단계 : method구현 : StringJNIDLLSource.c

#include <stdio.h>
#include <jni.h>
#include <string.h>
#include "JNI_Message.h"

JNIEXPORT jbyteArray JNICALL Java_JNI_1Message_Message (JNIEnv * env, jobject jobj, jstring input)
{
    jbyteArray jb;
    jboolean iscopy;
    char* buf;
    static char outputbuf[20];

    buf=(*env)->GetStringUTFChars(env, input, &iscopy);  // 입력 String 읽어오는 함수
    printf ("\nDLL receive Data from JAVA : %s\n",buf);   // 입력받은 내용을 출력
    strcpy(outputbuf,"Delicious !!\n");
    jb=(*env)->NewStringUTF(env, outputbuf);  // 출력할 내용의 java버퍼에 output버퍼값을 셋팅

   return(jb); // java버퍼 리턴
}



(*env)->함수명 형태로, JAVA의 메쏘드를 C에서 이용할수 있습니다.
* JAVA는 C로 문자열을 넘겨줄때 UTF-8형태를 사용합니다.



5단계 : 실행

C:\test\C_JNI\Paramerter Pass>java JNI_Message

DLL receive Data from JAVA : Apple
Delicious !!





5. KVM ? KNI ?

KVM은 J2ME의 일부로서 작고 자원이 한정된 기계장치를 위해 설계된 소형 JVM.
JVM에서는 JNI가 KVM의 KNI가 있다.


 

6. 기타프로그래밍 이슈들
참고 URL :http://www.javastudy.co.kr/docs/jhan/javaadvance/jni.html

언어적 이슈(Language Issues)
메소드 호출(Calling Methods)
필드의 참조(Accessing Fields)
스레드와 동기화(Threads and Synchronization)
메모리 이슈(Memory Issues)
수행(Invocation)
스레드 연결(Attaching Threads)

Posted by 1010
01.JAVA/Java2009. 4. 7. 11:05
반응형
우리는 코딩을 하면서 String을 비교할 때 무의식적으로 아래와 같이 코딩을 합니다.
  1.  
  2. aString.equals(bString)  


 하지만 왜 String을 비교할 때만 이렇게 비교하는지 우리는 알고 코딩을 하고 있는 것일까? int, boolean, long 등은 == 로 비교를 하면서 String은 왜 다를까?

 지금부터  String을 비교할 때 .equals()와 == 이 어떻게 다른지 알아보자.

 일단 코드를 실행해보고 결과를 보면서 진행하겠습니다. 저는 백문이불여일견이라는 말을 좋아하거든요.^^
  1. public class Test {  
  2.  
  3.     /**  
  4.      * @param args  
  5.      */ 
  6.     public static void main(String[] args) {  
  7.         // TODO Auto-generated method stub  
  8.         new Test().testString();  
  9.     }  
  10.  
  11.     public void testString() {  
  12.         String a = "TEST";  
  13.         String b = "TEST";  
  14.         String c = new String("TEST");  
  15.         String d = new String("TEST");  
  16.         System.out.println("1:"+System.identityHashCode(a));  
  17.         System.out.println("2:"+System.identityHashCode(b));  
  18.         System.out.println("3:"+System.identityHashCode(c));  
  19.         System.out.println("4:"+System.identityHashCode(d));  
  20.         System.out.println("5:"+(a == b));  
  21.         System.out.println("6:"+a.equals(b));  
  22.         System.out.println("7:"+(c == d));  
  23.         System.out.println("8:"+c.equals(d));  
  24.     }  
  25. }  


위 코드를 실행해 보면 결과는 다음과 같이 나옵니다.

사용자 삽입 이미지

결과를 보면 a,b는 hashcode값이 같지만 c,d는 값이 다른 것이 보입니다.
그럼 이번엔 비교한 결과를 볼까요? a,b는 equals()로 비교를 하거나 ==로 비교를 해도 결과는 항상 true 입니다. 하지만 c,d는 equals() 비교를 하면 트루지만 ==로 비교를 하면 false죠.

왜 이런 결과가 나올까요?

 이런 결과가 나오는 이유는 equals()는 비교대상의 문자열 리터럴(값)을 비교하고 ==는 대상 객체를 비교하기 때문입니다. 또한 자바에서는 a,b처럼 같은 값을 가지면 하나의 메모리 주소를 참조하게 됩니다. 즉, a,b의 "TEST"라는 문자열 리터럴은 컴파일되면 String 객체가 되는데 a,b는 같은 메모리 주소를 가지게 됩니다. 하지만 c,d는 처음부터 별도의 String 객체로 생성되었기 때문에 동일한 "TEST"라는 문자열 리터럴을 가지지만 서로 다른 객체가 됩니다.
 무슨말인지 모르시겠다구요? 그럼 그림으로 한번 볼까요?
사용자 삽입 이미지
간단하게 정리하자면 a,b는 문자열 리터럴이 컴파일시에 자동으로 하나의 String 객체가 되고 b,c는 별도의 객체가되어서 문자열 리터럴(값)으로 비교를 하면 a,b,c,d 모두 같지만 객체로 비교를 하게 되면 (a,b),c,d의 3개의 객체가 되는 것입니다.

 여기서 이어지는 또다른 의문점... 프리미티브 타입과 Wrapper 클래스의 비교는 어떻게 될까요?
아래 코드를 한번 돌려 보세요. 8번까지는 위 내용과 비슷하지만 9번 결과는 어떻게 나올까요?
 다음에는 프리미티브 타입과 Wrapper 클래스, 자동 Boxing, 자동 UnBoxing에 대해서 알아 보도록 하겠습니다.

  1. package net.westzero;  
  2.  
  3. public class Test {  
  4.  
  5.     /**  
  6.      * @param args  
  7.      */ 
  8.     public static void main(String[] args) {  
  9.         // TODO Auto-generated method stub  
  10.         new Test().testInteger();  
  11.     }  
  12.      
  13.     public void testInteger() {  
  14.         int a = 1;  
  15.         int b = 1;  
  16.         Integer c = new Integer(1);  
  17.         Integer d = new Integer(1);  
  18.         System.out.println("1:"+System.identityHashCode(a));  
  19.         System.out.println("2:"+System.identityHashCode(b));  
  20.         System.out.println("3:"+System.identityHashCode(c));  
  21.         System.out.println("4:"+System.identityHashCode(d));  
  22.         System.out.println("5:"+(a == b));  
  23. //        System.out.println("6:"+a.equals(b));  
  24.         System.out.println("7:"+(c == d));  
  25.         System.out.println("8:"+c.equals(d));  
  26.         System.out.println("9:"+(a == c));  
  27.     }  
  28. }  




출처 : http://westzero.net/21?category=6
Posted by 1010
01.JAVA/Java2009. 4. 6. 15:02
반응형

PreparedStatement 를 이용

<%@ page import = "java.sql.PreparedStatement" %>


<%

String query = "select ? from table_name where x = ?";

PreparedStatement pstmt = conn.prepareStatement(query);

pstmt.setString(1, value_1);

pstmt.setString(2, value_2);


pstmt.close();

>%



Statement를 이용

<%@ page import = "java.sql.Statement" %>


<%


String query = "select ? from table_name where x = ?";

Statement stmt = conn.createStatement();

stmt.executeUpdate(query);

stmt.close();

%>

Posted by 1010
01.JAVA/Java2009. 4. 6. 14:47
반응형

<noscript> 태그는 브라우저에서 <script> 태그가 작동하지 않을 때 대신 내보낼 내용을 담기 위해 쓰인다.

즉, 방문객이 브라우저에서 자바스크립트가 실행되도록 설정해 두었다면 자바스크립트는 실행되고 <noscript> 태그 안의 내용은 나오지 않는다. 하지만 자바스크립트 기능을 꺼두고 있다면 자바스크립트가 실행되지 않는 대신에 <noscript> 태그 안의 내용이 출력된다.


<script type="text/javascript">
document.write('안녕하십니까?')
</script>
<noscript><p>자바스크립트를 꺼두셨군요.</p></noscript>

위의 예에서, 보통은 자바스크립트가 실행되기 때문에 화면에는 다음 문장이 나올 것이다.

안녕하십니까?

하지만 자바스크립트가 실행되지 않는다면 화면에는 다음 문장이 나오게 된다.

자바스크립트를 꺼두셨군요.

브라우저에서 자바스크립트 기능을 꺼두고 쓰는 사람도 있기 때문에 자바스크립트를 쓴 곳에는 <noscript> 태그를 써서 자바스크립트가 필요하다는 걸 알려주는 게 좋다.


<p><a href="#" onclick="window.open('photo.html'; return false">사진 보기</a></p>
<noscript><p>사진 보기를 하려면 자바스크립트가 필요합니다.</p></noscript>

위 예에서는 자바스크립트를 써서 사진 보기 창을 뜨도록 하고 있으므로, 자바스크립트를 꺼두면 새 창을 뜨게 할 수 없기 때문에 사진을 볼 수 없다. 만약 <noscript> 태그를 쓰지 않는다면 모르는 사람은 왜 사진 보기가 안 되는 걸까 의아해 할지도 모른다. 하지만 <noscript> 태그를 써서, 위와 같이 사진을 보기 위해서는 자바스크립트가 필요하다는 걸 알려준다면 자바스크립트 기능을 꺼두었기 때문에 사진 보기가 안 된다는 걸 알고 사진을 보기 위해 자바스크립트 기능을 켜게 될 것이다.

위 코드의 결과는 다음과 같다. 브라우저에서 자바스크립트 기능을 꺼서 어떻게 보이는지 직접 확인해 보기 바란다.

사진 보기

참고로 photo.html 파일은 만들지 않았으므로 사진 보기를 눌러도 새 창은 뜨지 않을 것이며, <noscript> 태그 안의 글씨는 현재 이곳의 CSS 설정에 따라 크기나 색깔이 다르게 보일 수도 있다.

<noscript> 태그 안의 내용은 웹 문서의 내용과는 상관 없는 것이므로 웹 문서의 내용과는 다르게 보이도록 하는 게 좋다. 예를 들어, CSS에서 설정을 다음과 같이 해 두면 <noscript> 태그 안의 글씨는 돋움 글꼴에 본문 글씨보다 작게 녹색으로 보이게 되므로 웹 문서에 쓰인 글씨가 검은 색이면 서로 구별될 것이다.


noscript { font-family: 돋움, Dotum; 
           font-size: 75%; 
           color: green; }

끝으로 한 가지 주의사항은, <noscript> 태그는 <p> 태그를 감쌀 수 있지만 그 반대는 되지 않고, <noscript> 태그 안에 들어 있는 글씨를 <p> 같은 형님 태그로 감싸주지 않으면 웹 표준 검사에서 오류가 난다는 것이다.

Posted by 1010
01.JAVA/Java2009. 4. 6. 14:47
반응형
public void makeLog(){
               
        String filePath = "D:/SQLException.log";       
        try {
            PrintWriter pw= new PrintWriter(new FileWriter(filePath, true));
            pw.write(getLogTime());
            pw.write(" : SQLException");
            pw.write("\n");
            pw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }              
    }

값이 true일 경우는 File이어쓰기
값이 false일 경우는 File새로쓰기

File이 없는 경우 자동으로 생성도 해준다.
Posted by 1010
01.JAVA/Java2009. 4. 6. 14:44
반응형

java.io
클래스 PrintWriter

java.lang.Object 
  상위를 확장 java.io.Writer 
      상위를 확장 java.io.PrintWriter
모든 구현된 인터페이스:
Closeable , Flushable , Appendable

객체의 서식 첨부 표현을 텍스트 출력 스트림에 출력합니다. 이 클래스는,PrintStream 에 있는 print 메소드를 모두 구현합니다. 다만, raw 바이트를 기입하는 메소드는 포함되지 않습니다. raw 바이트에 대해서는, encode되어 있지 않은 바이트 스트림을 프로그램으로 사용해 주세요.

PrintStream 클래스와는 달라, 자동 플래시가 유효한 경우는, 개행 문자가 출력될 때는 아니고,println,printf,format 의 몇개의 메소드가 불려 갔을 때에 마셔 실행됩니다. 이러한 메소드는, 개행 문자는 아니고, 플랫폼에 고유의 행 단락의 표기를 사용합니다.

이 클래스의 메소드는, 생성자 의 일부를 제외해, 입출력 예외를 throw 할 것은 없습니다. 클라이언트는,checkError() 를 호출하는 것에 의해, 에러가 발생했는지의 여부를 조회할 수 있습니다.

도입된 버젼:
JDK1. 1

필드의 개요
protected  Writer out
          이 PrintWriter 의 기본이 되는 문자 출력 스트림입니다.
 
클래스 java.io. Writer 로부터 상속된 필드
lock
 
생성자 의 개요
PrintWriter (File  file)
          행의 자동 플래시는 실시하지 않고 , 지정된 파일로 새로운 PrintWriter 를 작성합니다.
PrintWriter (File  file, String  csn)
          행의 자동 플래시는 실시하지 않고 , 지정된 파일과 캐릭터 세트로 새로운 PrintWriter 를 작성합니다.
PrintWriter (OutputStream  out)
          행의 자동 플래시는 실시하지 않고 , 기존의 OutputStream 로부터 새로운 PrintWriter 를 작성합니다.
PrintWriter (OutputStream  out, boolean autoFlush)
          기존의 OutputStream 로부터 새로운 PrintWriter 를 작성합니다.
PrintWriter (String  fileName)
          행의 자동 플래시는 실시하지 않고 , 지정된 파일명으로 새로운 PrintWriter 를 작성합니다.
PrintWriter (String  fileName, String  csn)
          행의 자동 플래시는 실시하지 않고 , 지정된 파일명과 캐릭터 세트로 새로운 PrintWriter 를 작성합니다.
PrintWriter (Writer  out)
          행의 자동 플래시는 실시하지 않고 , 새로운 PrintWriter 를 작성합니다.
PrintWriter (Writer  out, boolean autoFlush)
          새로운 PrintWriter 를 작성합니다.
 
메소드의 개요
 PrintWriter append (char c)
          지정된 문자를 이 라이터에 추가합니다.
 PrintWriter append (CharSequence  csq)
          지정된 문자 순서를 이 라이터에 추가합니다.
 PrintWriter append (CharSequence  csq, int start, int end)
          지정된 문자 순서의 서브 순서를 이 라이터에 추가합니다.
 boolean checkError ()
          스트림이 닫혀지지 않은 경우는, 그 스트림을 플래시 해, 에러 상태를 체크합니다.
protected  void clearError ()
          이 스트림의 에러 상태를 해제합니다.
 void close ()
          스트림을 닫아, 거기에 관련하는 모든 system resource를 해제합니다.
 void flush ()
          스트림을 플래시 합니다.
 PrintWriter format (Locale  l, String  format, Object ... args)
          지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입합니다.
 PrintWriter format (String  format, Object ... args)
          지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입합니다.
 void print (boolean b)
          boolean 형의 값을 출력합니다.
 void print (char c)
          문자를 출력합니다.
 void print (char[] s)
          문자의 배열을 출력합니다.
 void print (double d)
          배정밀도의 부동 소수점수(실수)를 출력합니다.
 void print (float f)
          부동 소수점수(실수)를 출력합니다.
 void print (int i)
          정수를 출력합니다.
 void print (long l)
          long 정수를 출력합니다.
 void print (Object  obj)
          객체를 출력합니다.
 void print (String  s)
          캐릭터 라인을 출력합니다.
 PrintWriter printf (Locale  l, String  format, Object ... args)
          지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입하는 편리한 메소드입니다.
 PrintWriter printf (String  format, Object ... args)
          지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입하는 편리한 메소드입니다.
 void println ()
          행의 단락 캐릭터 라인을 기입하는 것으로, 현재의 행을 종료시킵니다.
 void println (boolean x)
          boolean 치를 출력해, 행을 종료시킵니다.
 void println (char x)
          문자를 출력해, 행을 종료시킵니다.
 void println (char[] x)
          문자의 배열을 출력해, 행을 종료시킵니다.
 void println (double x)
          배정밀도 부동 소수점수(실수)를 출력해, 행을 종료시킵니다.
 void println (float x)
          부동 소수점수(실수)를 출력해, 행을 종료시킵니다.
 void println (int x)
          정수를 출력해, 행을 종료시킵니다.
 void println (long x)
          long 형의 정수치를 출력해, 행을 종료시킵니다.
 void println (Object  x)
          Object 를 출력해, 행을 종료시킵니다.
 void println (String  x)
          캐릭터 라인을 출력해, 행을 종료시킵니다.
protected  void setError ()
          에러가 발생한 것을 나타냅니다.
 void write (char[] buf)
          문자의 배열을 기입합니다.
 void write (char[] buf, int off, int len)
          문자의 배열의 일부를 기입합니다.
 void write (int c)
          단일의 문자를 기입합니다.
 void write (String  s)
          캐릭터 라인을 기입합니다.
 void write (String  s, int off, int len)
          캐릭터 라인의 일부를 기입합니다.
 
클래스 java.lang. Object 로부터 상속된 메소드
clone , equals , finalize , getClass , hashCode , notify , notifyAll , toString , wait , wait , wait
 

필드의 상세

out

protected Writer  out
PrintWriter 의 기본이 되는 문자 출력 스트림입니다.

도입된 버젼:
1.2
생성자 의 상세

PrintWriter

public PrintWriter(Writer  out)
행의 자동 플래시는 실시하지 않고 , 새로운 PrintWriter 를 작성합니다.

파라미터:
out - 문자 출력 스트림

PrintWriter

public PrintWriter(Writer  out,
                   boolean autoFlush)
새로운 PrintWriter 를 작성합니다.

파라미터:
out - 문자 출력 스트림
autoFlush - boolean 치. true 의 경우,println 메소드,printf 메소드, 또는 format 메소드는 출력 버퍼를 플래시 한다

PrintWriter

public PrintWriter(OutputStream  out)
행의 자동 플래시는 실시하지 않고 , 기존의 OutputStream 로부터 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간의 OutputStreamWriter 를 작성합니다. 이것은, 디폴트의 문자 인코딩을 사용해 문자를 바이트로 변환합니다.

파라미터:
out - 출력 스트림
관련 항목:
OutputStreamWriter.OutputStreamWriter(java.io.OutputStream)

PrintWriter

public PrintWriter(OutputStream  out,
                   boolean autoFlush)
기존의 OutputStream 로부터 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간의 OutputStreamWriter 를 작성합니다. 이것은, 디폴트의 문자 인코딩을 사용해 문자를 바이트로 변환합니다.

파라미터:
out - 출력 스트림
autoFlush - boolean 치. true 의 경우,println 메소드,printf 메소드, 또는 format 메소드는 출력 버퍼를 플래시 하는
관련 항목:
OutputStreamWriter.OutputStreamWriter(java.io.OutputStream)

PrintWriter

public PrintWriter(String  fileName)
            throws FileNotFoundException 
행의 자동 플래시는 실시하지 않고 , 지정된 파일명으로 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간 OutputStreamWriter 를 작성합니다. 이것은, 이 Java 가상 머신 인스턴스의디폴트 캐릭터 세트를 사용해, 문자를 encode 합니다.

파라미터:
fileName - 이 라이터의 행선지로서 사용되는 파일의 이름. 파일이 존재하는 경우는, 사이즈 0 에 절약할 수 있다. 그렇지 않은 경우는, 신규 파일이 작성된다. 출력은 파일에 기입해져 버퍼에 넣어진다
예외:
FileNotFoundException - 지정된 캐릭터 라인이 기존의 파일을 나타내지 않는 경우, 기입해 가능한 일반적으로 파일 및 신규의 일반적으로 파일이 그 이름으로 작성할 수 없는 경우, 또는 파일의 오픈 또는 작성중에 그 외의 에러가 발생했을 경우
SecurityException - 시큐리티 매니저가 존재해,checkWrite(fileName) 가 파일에의 기입해 액세스를 거부했을 경우
도입된 버젼:
1.5

PrintWriter

public PrintWriter(String  fileName,
                   String  csn)
            throws FileNotFoundException ,
                   UnsupportedEncodingException 
행의 자동 플래시는 실시하지 않고 , 지정된 파일명과 캐릭터 세트로 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간 OutputStreamWriter 를 작성합니다. 이것은, 제공된 캐릭터 세트를 사용해 문자를 encode 합니다.

파라미터:
fileName - 이 라이터의 행선지로서 사용되는 파일의 이름. 파일이 존재하는 경우는, 사이즈 0 에 절약할 수 있다. 그렇지 않은 경우는, 신규 파일이 작성된다. 출력은 파일에 기입해져 버퍼에 넣어지는
csn - 지원하는 charset 의 이름
예외:
FileNotFoundException - 지정된 캐릭터 라인이 기존의 파일을 나타내지 않는 경우, 기입해 가능한 일반적으로 파일 및 신규의 일반적으로 파일이 그 이름으로 작성할 수 없는 경우, 또는 파일의 오픈 또는 작성중에 그 외의 에러가 발생했을 경우
SecurityException - 시큐리티 매니저가 존재해,checkWrite(fileName) 가 파일에의 기입해 액세스를 거부했을 경우
UnsupportedEncodingException - 지정된 캐릭터 세트가 지원되어 있지 않은 경우
도입된 버젼:
1.5

PrintWriter

public PrintWriter(File  file)
            throws FileNotFoundException 
행의 자동 플래시는 실시하지 않고 , 지정된 파일로 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간 OutputStreamWriter 를 작성합니다. 이것은, 이 Java 가상 머신 인스턴스의디폴트 캐릭터 세트를 사용해, 문자를 encode 합니다.

파라미터:
file - 이 라이터의 행선지로서 사용되는 파일. 파일이 존재하는 경우는, 사이즈 0 에 절약할 수 있다. 그렇지 않은 경우는, 신규 파일이 작성된다. 출력은 파일에 기입해져 버퍼에 넣어진다
예외:
FileNotFoundException - 지정된 파일 객체가 기존의 파일을 나타내지 않는 경우, 기입해 가능한 일반적으로의 파일 및 신규의 일반적으로 파일이 그 이름으로 작성할 수 없는 경우, 또는 파일의 오픈 또는 작성중에 그 외의 에러가 발생했을 경우
SecurityException - 시큐리티 매니저가 존재해,checkWrite(file.getPath()) 가 파일에의 기입해 액세스를 거부했을 경우
도입된 버젼:
1.5

PrintWriter

public PrintWriter(File  file,
                   String  csn)
            throws FileNotFoundException ,
                   UnsupportedEncodingException 
행의 자동 플래시는 실시하지 않고 , 지정된 파일과 캐릭터 세트로 새로운 PrintWriter 를 작성합니다. 이 간이 생성자 은, 필요한 중간 OutputStreamWriter 를 작성합니다. 이것은, 제공된 캐릭터 세트를 사용해 문자를 encode 합니다.

파라미터:
file - 이 라이터의 행선지로서 사용되는 파일. 파일이 존재하는 경우는, 사이즈 0 에 절약할 수 있다. 그렇지 않은 경우는, 신규 파일이 작성된다. 출력은 파일에 기입해져 버퍼에 넣어지는
csn - 지원하는 charset 의 이름
예외:
FileNotFoundException - 지정된 파일 객체가 기존의 파일을 나타내지 않는 경우, 기입해 가능한 일반적으로의 파일 및 신규의 일반적으로 파일이 그 이름으로 작성할 수 없는 경우, 또는 파일의 오픈 또는 작성중에 그 외의 에러가 발생했을 경우
SecurityException - 시큐리티 매니저가 존재해,checkWrite(file.getPath()) 가 파일에의 기입해 액세스를 거부했을 경우
UnsupportedEncodingException - 지정된 캐릭터 세트가 지원되어 있지 않은 경우
도입된 버젼:
1.5
메소드의 상세

flush

public void flush()
스트림을 플래시 합니다.
정의:
인터페이스 Flushable 내의 flush
정의:
클래스 Writer 내의 flush
관련 항목:
checkError()

close

public void close()
스트림을 닫아, 거기에 관련하는 모든 system resource를 해제합니다. 벌써 닫혀지고 있는 스트림을 닫아도, 무슨 영향도 없습니다.
정의:
인터페이스 Closeable 내의 close
정의:
클래스 Writer 내의 close
관련 항목:
checkError()

checkError

public boolean checkError()
스트림이 닫혀지지 않은 경우는, 그 스트림을 플래시 해, 에러 상태를 체크합니다.
반환값:
기본이 되는 출력 스트림상 또는 형식 변환중에, 출력 스트림로 에러가 검출되었을 경우는 true

setError

protected void setError()
에러가 발생한 것을 나타냅니다.

이 메소드를 사용하면(자),clearError() 가 불려 갈 때까지,checkError() 가 계속해 불려 가 true 가 돌려주어집니다.


clearError

protected void clearError()
이 스트림의 에러 상태를 해제합니다.

이 메소드를 사용하면(자), 다른 기입 처리가 실패해,setError() 가 불려 갈 때까지,checkError() 가 계속해 불려 가 false 가 돌려주어집니다.

도입된 버젼:
1.6

write

public void write(int c)
단일의 문자를 기입합니다.
오버라이드(override):
클래스 Writer 내의 write
파라미터:
c - 기입하는 문자를 지정하는 int

write

public void write(char[] buf,
                  int off,
                  int len)
문자의 배열의 일부를 기입합니다.
정의:
클래스 Writer 내의 write
파라미터:
buf - 문자의 배열
off - 문자의 기입 개시 오프셋(offset)
len - 기입하는 문자수

write

public void write(char[] buf)
문자의 배열을 기입합니다. 입출력 예외를 억제해야 하기 때문에, 이 메소드를 Writer 클래스로부터 상속할 수 없습니다.
오버라이드(override):
클래스 Writer 내의 write
파라미터:
buf - 기입하는 문자의 배열

write

public void write(String  s,
                  int off,
                  int len)
캐릭터 라인의 일부를 기입합니다.
오버라이드(override):
클래스 Writer 내의 write
파라미터:
s - 캐릭터 라인
off - 문자의 기입 개시 오프셋(offset)
len - 기입하는 문자수

write

public void write(String  s)
캐릭터 라인을 기입합니다. 입출력 예외를 억제해야 하기 때문에, 이 메소드를 Writer 클래스로부터 상속할 수 없습니다.
오버라이드(override):
클래스 Writer 내의 write
파라미터:
s - 기입해지는 캐릭터 라인

print

public void print(boolean b)
boolean 형의 값을 출력합니다. String.valueOf(boolean) 에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
b - 출력되는 boolean

print

public void print(char c)
문자를 출력합니다. 문자는 플랫폼의 디폴트의 문자 인코딩에 따라 1 개 이상의 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
c - 출력되는 char

print

public void print(int i)
정수를 출력합니다. String.valueOf(int) 에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
i - 출력되는 int
관련 항목:
Integer.toString(int)

print

public void print(long l)
long 정수를 출력합니다. String.valueOf(long) 에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
l - 출력되는 long
관련 항목:
Long.toString(long)

print

public void print(float f)
부동 소수점수(실수)를 출력합니다. String.valueOf(float) 에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
f - 출력되는 float
관련 항목:
Float.toString(float)

print

public void print(double d)
배정밀도의 부동 소수점수(실수)를 출력합니다. String.valueOf(double) 에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
d - 출력되는 double
관련 항목:
Double.toString(double)

print

public void print(char[] s)
문자의 배열을 출력합니다. 문자는 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
s - 출력되는 char 의 배열
예외:
NullPointerException - snull 의 경우

print

public void print(String  s)
캐릭터 라인을 출력합니다. 인수가 null 의 경우는, 캐릭터 라인 「null」가 출력됩니다. 그렇지 않은 경우, 캐릭터 라인의 문자는 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
s - 출력되는 String

print

public void print(Object  obj)
객체를 출력합니다. String.valueOf(Object) 메소드에 의해 작성된 캐릭터 라인은, 플랫폼의 디폴트의 문자 인코딩에 따라 바이트에 변환되어 이러한 바이트는 write(int) 메소드와 완전히 같은 방법으로 기입해집니다.
파라미터:
obj - 출력되는 Object
관련 항목:
Object.toString()

println

public void println()
행의 단락 캐릭터 라인을 기입하는 것으로, 현재의 행을 종료시킵니다. 행의 단락 캐릭터 라인은, 시스템 프로퍼티 line.separator 로 정의되어 반드시 단일의 개행 문자 ('\n')이다고는 할 수 없습니다.

println

public void println(boolean x)
boolean 치를 출력해, 행을 종료시킵니다. 이 메소드는,print(boolean) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 boolean

println

public void println(char x)
문자를 출력해, 행을 종료시킵니다. 이 메소드는,print(char) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 char

println

public void println(int x)
정수를 출력해, 행을 종료시킵니다. 이 메소드는,print(int) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 int

println

public void println(long x)
long 형의 정수치를 출력해, 행을 종료시킵니다. 이 메소드는,print(long) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 long

println

public void println(float x)
부동 소수점수(실수)를 출력해, 행을 종료시킵니다. 이 메소드는,print(float) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 float

println

public void println(double x)
배정밀도 부동 소수점수(실수)를 출력해, 행을 종료시킵니다. 이 메소드는,print(double) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 double

println

public void println(char[] x)
문자의 배열을 출력해, 행을 종료시킵니다. 이 메소드는,print(char[]) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 char 치의 배열

println

public void println(String  x)
캐릭터 라인을 출력해, 행을 종료시킵니다. 이 메소드는,print(String) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 String

println

public void println(Object  x)
Object 를 출력해, 행을 종료시킵니다. 이 메소드는, 최초로 String.valueOf(x)를 호출해, 출력된 객체의 캐릭터 라인치를 가져옵니다. 다음에,print(String) 를 호출하고 나서 println() 를 호출하는 것과 같이 동작합니다.
파라미터:
x - 출력되는 Object

printf

public PrintWriter  printf(String  format,
                          Object ... args)
지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입하는 편리한 메소드입니다. 자동 플래시가 유효한 경우는, 이 메소드를 호출하면(자) 출력 버퍼가 플래시 됩니다.

이 메소드를 out.printf(format, args) 의 형식에서 호출하면(자), 다음의 호출과 같은 결과가 됩니다.

out.format(format, args) 
파라미터:
format - 「서식 캐릭터 라인의 구문」으로 설명한 서식 캐릭터 라인
args - 서식 캐릭터 라인내의 서식 지시자에 의해 참조되는 인수. 서식 지시자 이외에도 인수가 존재하는 경우, 여분의 인수는 무시된다. 인수의 수는 변동해, 제로의 경우도 있다. 인수의 최대수는,Java 가상 머신 스펙으로 정의된 Java 배열의 최대 사이즈의 제한을 받는다. 인수가 null 의 경우, 동작은변환에 응해 다르다
반환값:
이 라이터
예외:
IllegalFormatException - 서식 캐릭터 라인에 부정한 구문, 지정된 인수와 호환성이 없는 서식 지시자, 인수의 지정이 불충분한 서식 캐릭터 라인, 또는 다른 부정한 조건이 포함되는 경우. 가능성이 있는 서식 에러 모든 자세한 것은, Formatter 클래스 스펙의「상세」섹션을 참조
NullPointerException - formatnull 의 경우
도입된 버젼:
1.5

printf

public PrintWriter  printf(Locale  l,
                          String  format,
                          Object ... args)
지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입하는 편리한 메소드입니다. 자동 플래시가 유효한 경우는, 이 메소드를 호출하면(자) 출력 버퍼가 플래시 됩니다.

이 메소드를 out.printf(l, format, args) 의 형식에서 호출하면(자), 다음의 호출과 같은 결과가 됩니다.

out.format(l, format, args) 
파라미터:
l - 서식 설정시에 적용하는로케일 . lnull 의 경우, 로컬라이제이션은 적용되지 않는
format - 「서식 캐릭터 라인의 구문」으로 설명한 서식 캐릭터 라인
args - 서식 캐릭터 라인내의 서식 지시자에 의해 참조되는 인수. 서식 지시자 이외에도 인수가 존재하는 경우, 여분의 인수는 무시된다. 인수의 수는 변동해, 제로의 경우도 있다. 인수의 최대수는,Java 가상 머신 스펙으로 정의된 Java 배열의 최대 사이즈의 제한을 받는다. 인수가 null 의 경우, 동작은변환에 응해 다르다
반환값:
이 라이터
예외:
IllegalFormatException - 서식 캐릭터 라인에 부정한 구문, 지정된 인수와 호환성이 없는 서식 지시자, 인수의 지정이 불충분한 서식 캐릭터 라인, 또는 다른 부정한 조건이 포함되는 경우. 가능성이 있는 서식 에러 모든 자세한 것은, Formatter 클래스 스펙의「상세」섹션을 참조
NullPointerException - formatnull 의 경우
도입된 버젼:
1.5

format

public PrintWriter  format(String  format,
                          Object ... args)
지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입합니다. 자동 플래시가 유효한 경우는, 이 메소드를 호출하면(자) 출력 버퍼가 플래시 됩니다.

이 객체에 대해서 다른 서식 설정 메소드가 먼저 불려 가고 있었는지 어떠했는지에 관계없이,Locale.getDefault() 에 의해 반환되는 로케일이 항상 사용됩니다.

파라미터:
format - 「서식 캐릭터 라인의 구문」으로 설명한 서식 캐릭터 라인
args - 서식 캐릭터 라인내의 서식 지시자에 의해 참조되는 인수. 서식 지시자 이외에도 인수가 존재하는 경우, 여분의 인수는 무시된다. 인수의 수는 변동해, 제로의 경우도 있다. 인수의 최대수는,Java 가상 머신 스펙으로 정의된 Java 배열의 최대 사이즈의 제한을 받는다. 인수가 null 의 경우, 동작은변환에 응해 다르다
반환값:
이 라이터
예외:
IllegalFormatException - 서식 캐릭터 라인에 부정한 구문, 지정된 인수와 호환성이 없는 서식 지시자, 인수의 지정이 불충분한 서식 캐릭터 라인, 또는 다른 부정한 조건이 포함되는 경우. 가능성이 있는 서식 에러 모든 자세한 것은, Formatter 클래스 스펙의「상세」섹션을 참조
NullPointerException - formatnull 의 경우
도입된 버젼:
1.5

format

public PrintWriter  format(Locale  l,
                          String  format,
                          Object ... args)
지정된 서식 캐릭터 라인 및 인수를 사용해, 서식 첨부 캐릭터 라인을 이 라이터에 기입합니다. 자동 플래시가 유효한 경우는, 이 메소드를 호출하면(자) 출력 버퍼가 플래시 됩니다.
파라미터:
l - 서식 설정시에 적용하는로케일 . lnull 의 경우, 로컬라이제이션은 적용되지 않는
format - 「서식 캐릭터 라인의 구문」으로 설명한 서식 캐릭터 라인
args - 서식 캐릭터 라인내의 서식 지시자에 의해 참조되는 인수. 서식 지시자 이외에도 인수가 존재하는 경우, 여분의 인수는 무시된다. 인수의 수는 변동해, 제로의 경우도 있다. 인수의 최대수는,Java 가상 머신 스펙으로 정의된 Java 배열의 최대 사이즈의 제한을 받는다. 인수가 null 의 경우, 동작은변환에 응해 다르다
반환값:
이 라이터
예외:
IllegalFormatException - 서식 캐릭터 라인에 부정한 구문, 지정된 인수와 호환성이 없는 서식 지시자, 인수의 지정이 불충분한 서식 캐릭터 라인, 또는 다른 부정한 조건이 포함되는 경우. 가능성이 있는 서식 에러 모든 자세한 것은, Formatter 클래스 스펙의「상세」섹션을 참조
NullPointerException - formatnull 의 경우
도입된 버젼:
1.5

append

public PrintWriter  append(CharSequence  csq)
지정된 문자 순서를 이 라이터에 추가합니다.

이 메소드를 out.append(csq) 의 형식에서 호출했을 경우, 다음의 호출과 같은 결과를 얻을 수 있습니다.

out.write(csq.toString()) 

문자 순서 csqtoString 의 스펙에 따라서는, 그 순서 전체가 추가되지 않을 가능성도 있습니다. 예를 들어, 문자 버퍼의 toString 메소드를 호출했을 경우, 그 버퍼의 위치와 리밋트에 의해 정해지는 내용을 가지는 서브 순서가 돌려주어집니다.

정의:
인터페이스 Appendable 내의 append
오버라이드(override):
클래스 Writer 내의 append
파라미터:
csq - 추가되는 문자 순서. csqnull 의 경우는, 이 라이터에 「null」라고 하는 4 문자가 추가된다
반환값:
이 라이터
도입된 버젼:
1.5

append

public PrintWriter  append(CharSequence  csq,
                          int start,
                          int end)
지정된 문자 순서의 서브 순서를 이 라이터에 추가합니다.

이 메소드를 out.append(csq, start, end) (csqnull 가 아니다)의 형식에서 호출했을 경우, 다음의 호출과 같은 결과를 얻을 수 있습니다.

out.write(csq.subSequence(start, end). toString()) 
정의:
인터페이스 Appendable 내의 append
오버라이드(override):
클래스 Writer 내의 append
파라미터:
csq - 문자 서브 순서의 추가원이 되는 문자 순서. csqnull 의 경우,csq 에 「null」의 4 문자가 포함되는것 같이 문자가 추가되는
start - 문자 서브 순서의 최초의 문자의 인덱스
end - 문자 서브 순서의 마지막 문자에 계속되는 문자의 인덱스
반환값:
이 라이터
예외:
IndexOutOfBoundsException - start 또는 end 가 0 보다 작은 값의 경우,startend 보다 큰 경우, 또는 endcsq.length() 보다 큰 경우
도입된 버젼:
1.5

append

public PrintWriter  append(char c)
지정된 문자를 이 라이터에 추가합니다.

이 메소드를 out.append(c) 의 형식에서 호출했을 경우, 다음의 호출과 같은 결과를 얻을 수 있습니다.

out.write(c) 
정의:
인터페이스 Appendable 내의 append
오버라이드(override):
클래스 Writer 내의 append
파라미터:
c - 추가하는 16 비트 문자
반환값:
이 라이터
도입된 버젼:
1.5
Posted by 1010
01.JAVA/Java2009. 4. 1. 17:36
반응형

윈도우즈 RDP 포트 변경하기

Source : http://blog.khaddar.net/814

 

지금까지 여러가지 원격 솔루션을 사용해 봤는데, 윈도우용으로는 LogMeIn이 제일 나은 듯 했으나, 역시 속도면에서는 "원격 데스크톱 연결"을 따라갈 수가 없다. Terminal Service 혹은 RDP라 불리는 이 서비스는 윈도우 XP Professional이상에는 기본으로 제공되며, 간혹 매우 유용하게 사용되는 경우가 많다.
그런데 이 RDP 서비스는 기본적으로 3389번 포트를 사용하는데, 이 포트가 막혀있는 경우가 많이 있다. 이럴 때 위에서 설명한 LogMeIn등을 사용해도 되지만, 터미널서비스의 포트 자체를 변경하는 것도 좋은 방법이 되는 경우가 많다.
포트를 변경하기 위해서는 regedit등의 레지스트리 에디터를 사용하여 다음 키들을 변경하면 된다.

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\Wds\rdpwd\Tds\tcp\PortNumber
기본값: 0×00000d3d   변경값: 원하는 포트번호
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\PortNumber
기본값: 0×00000d3d   변경값: 원하는 포트번호

주1) 각 키값을 변경할 때 표시형식을 10진수로 변경하여 edit하면 보다 편리하게 값을 바꿀 수 있다.
주2) 키값을 변경한 후에는 재부팅을 하거나 서비스에서 Terminal Service를 재시작시켜주면 된다.

Posted in Win32.

Leave a Reply

Posted by 1010
01.JAVA/Java2009. 3. 23. 12:10
반응형
getJava 사이트 방문하기 http://my.dreamwiz.com/conbox/
     아래 문서의 소유권은 getJava에 있으며, 리포스팅에 대한 문의는 getJava로 하시기 바랍니다.

For Beginner :::::


Basic Lecture :::::

  1. 데이터 형과 연산자
  2. 제어문과 배열
  3. 클래스의 기본
  4. 클래스의 고급
  5. 주요 키워드와 클래스 종류
  6. 중요 클래스
  7. AWT와 배치
  8. 이벤트 처리
  9. 애플릿
  10. 쓰레드
  11. 예외처리
  12. 입출력(java.io)
  13. 네트워크
  14. JDBC
  15. 객체직렬화

Deep Lecture :::::

  1. Swing
  2. 분산 네트워킹(java.rmi)
  3. New I/O(java.nio)

Posted by 1010
01.JAVA/Java2009. 3. 23. 11:37
반응형

package jspData.util;

import java.io.UnsupportedEncodingException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class MyUtil {
 // 문자열의 내용중 원하는 문자열을 다른 문자열로 변환
 // String str = replaceAll(str, "\r\n", "<br>"); // 엔터를 <br>로 변환
 public String replaceAll(String str, String oldStr, String newStr) throws Exception {
  if(str == null)
   return "";

        Pattern p = Pattern.compile(oldStr);

        // 입력 문자열과 함께 매쳐 클래스 생성
        Matcher m = p.matcher(str);

        StringBuffer sb = new StringBuffer();
        boolean result = m.find();

        // 패턴과 일치하는 문자열을 newStr 로 교체해가며 새로운 문자열을 만든다.
        while(result) {
            m.appendReplacement(sb, newStr);
            result = m.find();
        }

        // 나머지 부분을 새로운 문자열 끝에 덫 붙인다.
        m.appendTail(sb);

  return sb.toString();
 }

 

//////////////////////////////////////////////////////////////////////////////

 

실제 jsp 적용로직(엑셀 다운로드시 /가 파일이름으로 적합하지 않아 오류가 남)

이때 /을 -로 바꿔주며 저장되게 함. class이용이 아니라 jsp자체에서 바로 적용

 

 //made in LCS  /로 된 문자열 -로 변환   /-> 이문자가 파일이름으로 적합하지 않음.
 String prjNms = reqInfo.getString("prjNm");
 int prjnum = prjNms.indexOf("/");
 if( prjnum >= 0){
  try{
    Pattern p = Pattern.compile("/");
         // 입력 문자열과 함께 매쳐 클래스 생성
         Matcher m = p.matcher(prjNms);

         StringBuffer sb = new StringBuffer();
         boolean result = m.find();

         // 패턴과 일치하는 문자열을 newStr 로 교체해가며 새로운 문자열을 만든다.
         while(result) {
             m.appendReplacement(sb, "-");
             result = m.find();
         }

         // 나머지 부분을 새로운 문자열 끝에 덫 붙인다.
         m.appendTail(sb);
   prjNms = sb.toString();
   //out.print("prjNmsprjNmsprjNmsprjNmsprjNmsprjNmsprjNmsprjNms"+prjNms);
 
  response.setHeader("Content-Disposition", "attachment; filename="+new String(prjNms.getBytes(),"8859_1")+"("+new java.text.SimpleDateFormat("yyyyMMdd").format(new java.util.Date())+").xls");
  }catch(Exception e){}
 }else{
  prjNms = reqInfo.getString("prjNm");
  //out.print("*************************************"+prjNms);
  //out.print("********************"+prjNms.indexOf("/"));
  response.setHeader("Content-Disposition", "attachment; filename="+new String(prjNms.getBytes(),"8859_1")+"("+new java.text.SimpleDateFormat("yyyyMMdd").format(new java.util.Date())+").xls");
 }

Posted by 1010
01.JAVA/Java2009. 3. 23. 11:15
반응형
<!--StartFragment-->/**
    * 문자열 내의 특정한 문자열을 모두 지정한 다른 문자열로 바꾼다.
    * 원본 String 이 null 일 경우에는 null 을 반환한다.
    * StringBuffer 를 이용하였으므로 이전의 String 을 이용한 것 보다
    * 월등히 속도가 빠르다. (약 50 ~ 60 배)
    *
    * 사용 예: <BR>
    *
    *   1. 게시판에서 HTML 태그가 안 먹히게 할려면
    *
    *      String str = "<TD>HTML Tag Free Test</TD>";
    *      str = replace(str, "&", "&amp;");
    *      str = replace(str, "<", "&lt;");
    *
    *   2. ' 가 포한된 글을 DB 에 넣을려면
    *
    *      String str2 = "I don't know.";
    *      str2 = replace(str2, "'", "''");
    *
    * @param   String src       원본 String
    * @param   String oldstr    원본 String 내의 바꾸기 전 문자열
    * @param   String newstr    바꾼 후 문자열
    * @return  String           치환이 끝난 문자열
    *
    * @date    2000/06/30
    * @author  김필호 (Kim, Pilho) [phkim@cluecom.co.kr]
    */
   public static String replace(String src, String oldstr, String newstr)
   {
       if (src == null)
           return null;

       StringBuffer dest = new StringBuffer("");
       int  len = oldstr.length();
       int  srclen = src.length();
       int  pos = 0;
       int  oldpos = 0;

       while ((pos = src.indexOf(oldstr, oldpos)) >= 0) {
           dest.append(src.substring(oldpos, pos));
           dest.append(newstr);
           oldpos = pos + len;
       }

       if (oldpos < srclen)
           dest.append(src.substring(oldpos, srclen));

       return dest.toString();
   }
Posted by 1010
01.JAVA/Java2009. 2. 25. 15:35
반응형
Web Java Class Decompiler 이용 방법
  • 이 유틸리티는 Java Class파일을 디컴파일하여 java소스로 변환하여 줍니다.
  • 디컴파일한 소스를 표시하는 방법에는 화면 출력과 소스 다운로드 두가지가 있습니다. (현재 화면 출력만 지원)
출력 방법 : 화면 출력 소스 출력
소스 파일 : (2MB 이내 파일) 파일의 캐릭터셋
지금까지 총 679번의 Java Class Decompiling 작업을 수행했습니다. (Since 2008-11-26)
Posted by 1010
01.JAVA/Java2009. 2. 23. 18:16
반응형
내 컴퓨터 -> 속성 -> 고급 -> 환경변수 -> 시스템 변수

1.JAVA_HOME 새로만들기클릭
      변수이름 : JAVA_HOME
      변수값 : 자바 jdk 를 설치한 위치를 지정 예) C:\Program Files\Java\jdk1.5.0_09

2.CLASSPATH 새로만들기클릭
      변수이름 : CLASSPATH
     변수값 : .;%JAVA_HOME%\lib\tools.jar


3.PATH 기존변수수정
      변수이름 : Path
     변수값 : java 가 설치된 디렉토리 밑의 bin 디렉토리 예) C:\Program Files\Java\jdk1.5.0_09\bin;

다 했으면 확인을 누르고 창을 닫자.

이제 설정이 잘 되었는지 확인할 차례

윈도우키+ R 을 누르면 "실행" 다이얼로그가 뜬다.
cmd를 타이핑 하고 엔터.
까만바탕의 커멘드 콘솔이 뜬다.

path를 입력해보자.
조금전에 수정한 path가 뜨면 일단 제대로 설정은 된것.
java를 입력해보자.
뭐라고 주루룩 뜨면 성공.

이제 준비는 끝났다.

시스템변수(S)에서 설정
1. 변수값    : path(맨끝에)    : 수정
   변수값    : ;%JAVA_HOME%\bin

2. 변수이름    : CLASSPATH    : 생성
   변수값    : .;%JAVA_HOME%\lib\tools.jar
   ※ 앞에 .; <= 주의할것 빼먹지말것

3. 변수이름    : JAVA_HOME    : 생성
   변수값    : C:\Program Files\Java\jdk1.5.0_15

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

TOMCAT 환경변수 설정 (tomcat은 설치하는거 없이 압축풀면 설치끝)

시스템변수(S)에서 설정

   변수이름    : CATALINA_HOME    - 생성
   변수값        : d:\www\apache-tomcat-5.5.26
   톰캣Start    : apache-tomcat-5.5.26\bin\startup.bat
   톰캣Shutdown    : apache-tomcat-5.5.26\bin\shutdown.bat

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Servlet 설정 (web.xml 수정)

   Tomcat이 설치된 폴더 => \conf\web.xml
     ex> apache-tomcat-5.5.26\conf\web.xml
   ※ 기본적으로 보안상 Servlet은 막혀있으므로 Servlet개발을 위해서
       주석을 제거하여 사용 환경을 만든다.

  1. "invoker" 찾기

########################################################
# <!--                                #
#    <servlet>                            #
#       <servlet-name>invoker</servlet-name>                #
#       <servlet-class>                        #
#           org.apache.catalina.servlets.InvokerServlet            #
#          </servlet-class>                        #
#          <init-param>                        #
#             <param-name>debug</param-name>                #
#             <param-value>0</param-value>                #
#       </init-param>                        #
#       <load-on-startup>2</load-on-startup>                #
#    </servlet>                            #
# -->                                #
########################################################
        [▲ 이부분을 찾는다]
  2. 주석제거 <!--, --> 이것만 삭제할것
########################################################
#    <servlet>                            #
#       <servlet-name>invoker</servlet-name>                #
#       <servlet-class>                        #
#           org.apache.catalina.servlets.InvokerServlet            #
#          </servlet-class>                        #
#          <init-param>                        #
#             <param-name>debug</param-name>                #
#             <param-value>0</param-value>                #
#       </init-param>                        #
#       <load-on-startup>2</load-on-startup>                #
#    </servlet>                            #
########################################################
        [▲ 이렇게 만들면 됨]
  3. Servlet Mapping의 주석도 제거("invoker" 찾기)

########################################################
#    <!-- The mapping for the invoker servlet -->            #
# <!--                                #
#    <servlet-mapping>                        #
#       <servlet-name>invoker</servlet-name>                #
#       <url-pattern>/servlet/*</url-pattern>                #
#    </servlet-mapping>                        #
# -->                                #
########################################################
     [▲ 이부분을 찾아서 주석제거,  ▼ 이렇게 만든다]
########################################################
#    <!-- The mapping for the invoker servlet -->            #
#                                #
#    <servlet-mapping>                        #
#       <servlet-name>invoker</servlet-name>                #
#       <url-pattern>/servlet/*</url-pattern>                #
#    </servlet-mapping>                        #
#                                #
########################################################
  4. web.xml을 저장하고 닫는다.
   ※ Servlet를 작성하기위해 API를 연결한다.
      여기서는 Tomcat에 있는 servlet-api.jar파일을 이용한다.
      EJB를 개발한다면 JavaEE를 설치하는게 좋다.
  5. tomcat\common\lib\
     위의 경로에서 servlet-api.jar파일을 복사하여
     Program Files/Java/jdk/lib/
     위의 lib폴더에 복사

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Servlet 환경변수 설정

시스템변수(S)에서 설정
1. 변수값    : CLASSPATH        : 지금까지 설정되있는것
   변수값    : .;%JAVA_HOME%\lib\tools.jar

2. jar파일 복사
    원본파일 : 톰캣경로\common\lib\servlet-api.jar (복사)
    사본파일 : C:\Program Files\Java\jdk1.5.0_16\lib\servlet-api.jar (여기에 복사할것)

3. 변수값    : CLASSPATH(맨끝에)    : 수정
   변수값    : .;%JAVA_HOME%\lib\tools.jar;C:\Program Files\Java\jdk1.5.0_15\lib\servlet-api.jar
   위치 : 톰캣경로\common\lib\servlet-api.jar

   ※ 뒤에 servlet-api파일의 경로만 넣어주면된다.
      ;C:\Program Files\Java\jdk1.5.0_15\lib\servlet-api.jar

   ※ tomcat이설치된 경로\webaps\ROOT\WEB-INF\
      classes란 폴더를 만든다. (WEB-INF 폴더아래에)

   ※ Servlet은 웹 어플리케이션 폴더 아래에
      WEB-INF\classes폴더가 존재해야함

   ※ sevlet가 잘돌아가는지 확인하는것은
      classes폴더에 servlet파일을 넣고
      웹브라우저에 http://127.0.0.1/servlet/서블릿파일(확장자빼고)
      실행되는지 볼것 ( servlet도 java기반이기때문에 대소문자 구분.. 조심!! )

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Eclipse 설치

http://www.eclipse.org/downloads
Posted by 1010
01.JAVA/Java2009. 2. 23. 15:37
반응형
  • 2008/04/11 Locale class의 getLanguage() 메소드가 리턴하는 각국 언어코드
  • 2008/02/29 SimpleDateFormat 로 24시/12시 표현하기
  • 2008/02/19 java.lang.ClassNotFoundException: org.apache.taglibs.standard.tlv.JstlFmtTLV
  • 2008/02/12 SiteMesh 설치하기
  • 2008/02/11 Struts2 Framework 설치하기
  • 2008/02/11 Spring Framework 설치하기
  • 2008/01/16 자바개발환경 구성하기 - 4.IDE
  • 2008/01/16 자바개발환경 구성하기 - 3.WAS
  • 2008/01/09 자바개발환경 구성하기 - 2.Database
  • 2008/01/09 자바개발환경 구성하기 - 1.JDK 설치
  • 2008/01/09 자바개발환경 구성하기 - 목차
  • 2007/12/13 Struts 2 Tutorial - 15.스트럿츠2에서의 클라이언트측 검증
  • 2007/12/13 Struts 2 Tutorial - 14.실행 및 테스트
  • 2007/12/13 Struts 2 Tutorial - 13.로그인 어플리케이션에 Validation 추가
  • 2007/12/12 Struts 2 Tutorial - 12.Login 어플리케이션 개발
  • 2007/12/12 Struts 2 Tutorial - 11.Struts 2 Redirect Action
  • 2007/12/11 Struts 2 Tutorial - 10.Struts 2 Action 소개
  • 2007/11/29 Struts 2 Tutorial - 09.Struts 2 xml 환경설정파일
  • 2007/11/28 Struts 2 Tutorial - 08.JSP, Java, 환경설정파일 작성하기
  • 2007/11/28 Struts 2 Tutorial - 07.폴더구조
  • 2007/11/28 Struts 2 Tutorial - 06.Struts 2 다운로드 및 설치 (2)
  • 2007/11/27 Struts 2 Tutorial - 05.Struts 1 과 Struts 2 비교
  • 2007/11/27 Struts 2 Tutorial - 04.Struts 2를 사용해야만 하는 이유
  • 2007/11/27 Struts 2 Tutorial - 03.Struts 2 아키텍쳐
  • 2007/11/26 Struts 2 Tutorial - 02.Struts 2 역사
  • 2007/11/26 Struts 2 Tutorial - 01.Struts 2 특징
  • 2007/11/26 Struts 2 Tutorial - 00.목차
  • Posted by 1010
    01.JAVA/Java2009. 2. 23. 14:40
    반응형
    http://java.sun.com/developer/EJTechTips/2005/tt0125.html#1






       try {           
            Connection con = makeDatabaseConnection();
            con.setAutoCommit(false);          
            //  Do whatever database transaction functionality
            //  is necessary          
            con.commit();         
        } catch (Exception ex) {
            try {
                con.rollback();
            } catch (SQLException sqx) {
                throw new EJBException("Rollback failed: " +
                    sqx.getMessage());
            }
        } finally {
            releaseDatabaseConnection();
        }
    Posted by 1010

    분류 전체보기 (2491)
    hadoop (1)
    spring boot (10)
    PostgreSQL (3)
    AngularJS (10)
    00.scala (49)
    00.Flex,Flash,Action.. (131)
    01.JAVA (214)
    Java (199)
    J2me (12)
    02.Oracle (248)
    03.HTML 4.X, HTML5, .. (234)
    04.Anddoid (49)
    05.JSP (65)
    06.Ajax (20)
    07.JavaScript, jQuer.. (73)
    50.Spring 2.X,3.0, M.. (35)
    51.Struts2 (25)
    52.Apache Project &... (118)
    53.jasper&ireport (23)
    54.iBATIS, MyBatis (36)
    55.jrebel (3)
    56. Eclipse Etc... (70)
    57.EgovFrameWork (1)
    60.Unix (89)
    61.Linux (89)
    62.solaris (2)
    80.모바일 웹앱 (4)
    81.웹취약점&해결방안 (10)
    82.웹접근성을고려한웹개발 (41)
    90.개발관련문서 (73)
    91..개발관련프로그램 (98)
    98..Etc (370)
    99.유용한정보 (68)
    00.[비밀]정보 (0)

    공지사항

    최근에 올라온 글

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함

    달력

    « » 2024.5
    1 2 3 4
    5 6 7 8 9 10 11
    12 13 14 15 16 17 18
    19 20 21 22 23 24 25
    26 27 28 29 30 31