2010년 12월 3일 금요일

Javascript String 관련 자주사용하는 Prototype

// 문자의 좌, 우 공백 제거
// @return : String
//-----------------------------------------------------------------------------
String.prototype.trim = function() {
    return this.replace(/(^\s*)|(\s*$)/g, "");
}
//-----------------------------------------------------------------------------
// 문자의 좌 공백 제거
// @return : String
//-----------------------------------------------------------------------------
String.prototype.ltrim = function() {
    return this.replace(/(^\s*)/, "");
}
//-----------------------------------------------------------------------------
// 문자의 우 공백 제거
// @return : String
//-----------------------------------------------------------------------------
String.prototype.rtrim = function() {
    return this.replace(/(\s*$)/, "");   
}
//-----------------------------------------------------------------------------
// 문자열의 byte 길이 반환
// @return : int
//-----------------------------------------------------------------------------
String.prototype.byte = function() {
    var cnt = 0;
    for (var i = 0; i < this.length; i++) {
        if (this.charCodeAt(i) > 127)
            cnt += 2;
        else
            cnt++;
    }
    return cnt;
}
//-----------------------------------------------------------------------------
// 정수형으로 변환
// @return : String
//-----------------------------------------------------------------------------
String.prototype.int = function() {
    if(!isNaN(this)) {
        return parseInt(this);
    }
    else {
        return null;   
    }
}
//-----------------------------------------------------------------------------
// 숫자만 가져 오기
// @return : String
//-----------------------------------------------------------------------------
String.prototype.num = function() {
    return (this.trim().replace(/[^0-9]/g, ""));
}
//-----------------------------------------------------------------------------
// 숫자에 3자리마다 , 를 찍어서 반환
// @return : String
//-----------------------------------------------------------------------------
String.prototype.money = function() {
    var num = this.trim();
    while((/(-?[0-9]+)([0-9]{3})/).test(num)) {
        num = num.replace((/(-?[0-9]+)([0-9]{3})/), "$1,$2");
    }
    return num;
}
//-----------------------------------------------------------------------------
// 숫자의 자리수(cnt)에 맞도록 반환
// @return : String
//-----------------------------------------------------------------------------
String.prototype.digits = function(cnt) {
    var digit = "";
    if (this.length < cnt) {
        for(var i = 0; i < cnt - this.length; i++) {
            digit += "0";
        }
    }
    return digit + this;
}
//-----------------------------------------------------------------------------
// " -> &#34; ' -> &#39;로 바꾸어서 반환
// @return : String
//-----------------------------------------------------------------------------
String.prototype.quota = function() {
    return this.replace(/"/g, "&#34;").replace(/'/g, "&#39;");
}
//-----------------------------------------------------------------------------
// 파일 확장자만 가져오기
// @return : String
//-----------------------------------------------------------------------------
String.prototype.ext = function() {
    return (this.indexOf(".") < 0) ? "" : this.substring(this.lastIndexOf(".") + 1, this.length);   
}
//-----------------------------------------------------------------------------
// URL에서 파라메터 제거한 순수한 url 얻기
// @return : String
//-----------------------------------------------------------------------------   
String.prototype.uri = function() {
    var arr = this.split("?");
    arr = arr[0].split("#");
    return arr[0];   
}
/*---------------------------------------------------------------------------------*\
*  각종 체크 함수들
\*---------------------------------------------------------------------------------*/
//-----------------------------------------------------------------------------
// 정규식에 쓰이는 특수문자를 찾아서 이스케이프 한다.
// @return : String
//-----------------------------------------------------------------------------
String.prototype.meta = function() {
    var str = this;
    var result = ""
    for(var i = 0; i < str.length; i++) {
        if((/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|]{1})/).test(str.charAt(i))) {
            result += str.charAt(i).replace((/([\$\(\)\*\+\.\[\]\?\\\^\{\}\|]{1})/), "
\\$1");
        }
        else {
            result += str.charAt(i);
        }
    }
    return result;
}
//-----------------------------------------------------------------------------
// 정규식에 쓰이는 특수문자를 찾아서 이스케이프 한다.
// @return : String
//-----------------------------------------------------------------------------
String.prototype.remove = function(pattern) {
    return (pattern == null) ? this : eval("this.replace(/[" + pattern.meta() + "]/g, \"\")");
}
//-----------------------------------------------------------------------------
// 최소 최대 길이인지 검증
// str.isLength(min [,max])
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isLength = function() {
    var min = arguments[0];
    var max = arguments[1] ? arguments[1] : null;
    var success = true;
    if(this.length < min) {
        success = false;
    }
    if(max && this.length > max) {
        success = false;
    }
    return success;
}
//-----------------------------------------------------------------------------
// 최소 최대 바이트인지 검증
// str.isByteLength(min [,max])
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isByteLength = function() {
    var min = arguments[0];
    var max = arguments[1] ? arguments[1] : null;
    var success = true;
    if(this.byte() < min) {
         success = false;
     }
    if(max && this.byte() > max) {
        success = false;
    }
    return success;
}
//-----------------------------------------------------------------------------
// 공백이나 널인지 확인
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isBlank = function() {
    var str = this.trim();
    for(var i = 0; i < str.length; i++) {
        if ((str.charAt(i) != "\t") && (str.charAt(i) != "\n") && (str.charAt(i)!="\r")) {
            return false;
        }
    }
    return true;
}
//-----------------------------------------------------------------------------
// 숫자로 구성되어 있는지 학인
// arguments[0] : 허용할 문자셋
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isNum = function() {
    return (/^[0-9]+$/).test(this.remove(arguments[0])) ? true : false;
}
//-----------------------------------------------------------------------------
// 영어만 허용 - arguments[0] : 추가 허용할 문자들
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isEng = function() {
    return (/^[a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;
}
//-----------------------------------------------------------------------------
// 숫자와 영어만 허용 - arguments[0] : 추가 허용할 문자들
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isEngNum = function() {
    return (/^[0-9a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;
}
//-----------------------------------------------------------------------------
// 숫자와 영어만 허용 - arguments[0] : 추가 허용할 문자들
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isNumEng = function() {
    return this.isEngNum(arguments[0]);
}
//-----------------------------------------------------------------------------
// 아이디 체크 영어와 숫자만 체크 첫글자는 영어로 시작 - arguments[0] : 추가 허용할 문자들
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isUserid = function() {
    return (/^[a-zA-z]{1}[0-9a-zA-Z]+$/).test(this.remove(arguments[0])) ? true : false;
}
//-----------------------------------------------------------------------------
// 한글 체크 - arguments[0] : 추가 허용할 문자들
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isKor = function() {
    return (/^[가-힣]+$/).test(this.remove(arguments[0])) ? true : false;
}
//-----------------------------------------------------------------------------
// 주민번호 체크 - arguments[0] : 주민번호 구분자
// XXXXXX-XXXXXXX
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isJumin = function() {
    var arg = arguments[0] ? arguments[0] : "";
    var jumin = eval("this.match(/[0-9]{2}[01]{1}[0-9]{1}[0123]{1}[0-9]{1}" + arg + "[1234]{1}[0-9]{6}$/)");
    if(jumin == null) {
        return false;
    }
    else {
        jumin = jumin.toString().num().toString();
    }
    // 생년월일 체크
    var birthYY = (parseInt(jumin.charAt(6)) == (1 ||2)) ? "19" : "20";
    birthYY += jumin.substr(0, 2);
    var birthMM = jumin.substr(2, 2) - 1;
    var birthDD = jumin.substr(4, 2);
    var birthDay = new Date(birthYY, birthMM, birthDD);
    if(birthDay.getYear() % 100 != jumin.substr(0,2) || birthDay.getMonth() != birthMM || birthDay.getDate() != birthDD) {
        return false;
    }       
    var sum = 0;
    var num = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]
    var last = parseInt(jumin.charAt(12));
    for(var i = 0; i < 12; i++) {
        sum += parseInt(jumin.charAt(i)) * num[i];
    }
    return ((11 - sum % 11) % 10 == last) ? true : false;
}
//-----------------------------------------------------------------------------
// 외국인 등록번호 체크 - arguments[0] : 등록번호 구분자
// XXXXXX-XXXXXXX
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isForeign = function() {
    var arg = arguments[0] ? arguments[0] : "";
    var jumin = eval("this.match(/[0-9]{2}[01]{1}[0-9]{1}[0123]{1}[0-9]{1}" + arg + "[5678]{1}[0-9]{1}[02468]{1}[0-9]{2}[6789]{1}[0-9]{1}$/)");
    if(jumin == null) {
        return false;
    }
    else {
        jumin = jumin.toString().num().toString();
    }
    // 생년월일 체크
    var birthYY = (parseInt(jumin.charAt(6)) == (5 || 6)) ? "19" : "20";
    birthYY += jumin.substr(0, 2);
    var birthMM = jumin.substr(2, 2) - 1;
    var birthDD = jumin.substr(4, 2);
    var birthDay = new Date(birthYY, birthMM, birthDD);
    if(birthDay.getYear() % 100 != jumin.substr(0,2) || birthDay.getMonth() != birthMM || birthDay.getDate() != birthDD) {
        return false;
    }
    if((parseInt(jumin.charAt(7)) * 10 + parseInt(jumin.charAt(8))) % 2 != 0) {
        return false;
    }
    var sum = 0;
    var num = [2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5]
    var last = parseInt(jumin.charAt(12));
    for(var i = 0; i < 12; i++) {
        sum += parseInt(jumin.charAt(i)) * num[i];
   }
   return (((11 - sum % 11) % 10) + 2 == last) ? true : false;
}   
//-----------------------------------------------------------------------------
// 사업자번호 체크 - arguments[0] : 등록번호 구분자
// XX-XXX-XXXXX
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isBiznum = function() {
    var arg = arguments[0] ? arguments[0] : "";
    var biznum = eval("this.match(/[0-9]{3}" + arg + "[0-9]{2}" + arg + "[0-9]{5}$/)");
    if(biznum == null) {
        return false;
    }
    else {
        biznum = biznum.toString().num().toString();
    }
    var sum = parseInt(biznum.charAt(0));
    var num = [0, 3, 7, 1, 3, 7, 1, 3];
    for(var i = 1; i < 8; i++) sum += (parseInt(biznum.charAt(i)) * num[i]) % 10;
    sum += Math.floor(parseInt(parseInt(biznum.charAt(8))) * 5 / 10);
    sum += (parseInt(biznum.charAt(8)) * 5) % 10 + parseInt(biznum.charAt(9));
    return (sum % 10 == 0) ? true : false;
}
//-----------------------------------------------------------------------------
// 법인 등록번호 체크 - arguments[0] : 등록번호 구분자
// XXXXXX-XXXXXXX
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isCorpnum = function() {
    var arg = arguments[0] ? arguments[0] : "";
    var corpnum = eval("this.match(/[0-9]{6}" + arg + "[0-9]{7}$/)");
    if(corpnum == null) {
        return false;
    }
    else {
        corpnum = corpnum.toString().num().toString();
    }
    var sum = 0;
    var num = [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
    var last = parseInt(corpnum.charAt(12));
    for(var i = 0; i < 12; i++) {
        sum += parseInt(corpnum.charAt(i)) * num[i];
    }
    return ((10 - sum % 10) % 10 == last) ? true : false;
}
//-----------------------------------------------------------------------------
// 이메일의 유효성을 체크
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isEmail = function() {
    return (/\w+([-+.]\w+)*@\w+([-.]\w+)*\.[a-zA-Z]{2,4}$/).test(this.trim());
}
//-----------------------------------------------------------------------------
// 전화번호 체크 - arguments[0] : 전화번호 구분자
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isPhone = function() {
    var arg = arguments[0] ? arguments[0] : "";
    return eval("(/(02|0[3-9]{1}[0-9]{1})" + arg + "[1-9]{1}[0-9]{2,3}" + arg + "[0-9]{4}$/).test(this)");
}
//-----------------------------------------------------------------------------
// 핸드폰번호 체크 - arguments[0] : 핸드폰 구분자
// @return : boolean
//-----------------------------------------------------------------------------
String.prototype.isMobile = function() {
    var arg = arguments[0] ? arguments[0] : "";
    return eval("(/01[016789]" + arg + "[1-9]{1}[0-9]{2,3}" + arg + "[0-9]{4}$/).test(this)");
}

Oracle Query : Tree의 ChildNode 전체를 가져오는법

SELECT  pgm_no
   ,pgm_id
   ,pgm_name
   ,pgm_kind_code
   ,picture
   ,select_picture
   ,sort_order
   ,parent_pgm
 FROM  pf_pgm_mst
 where  pgm_kind_code='P'
  CONNECT BY PRIOR    PGM_NO  = PARENT_PGM
  start with       PGM_NO = '00015'

Oracle Query 결과를 XML로 가져오는 Function

CREATE OR REPLACE FUNCTION GET_XML_RECORD
          (XMLSQL IN VARCHAR2,
           ENCODINGTYPE IN VARCHAR2 := 'UTF-8') RETURN CLOB IS
    CTX DBMS_XMLQUERY.CTXHANDLE;
    XMLRECORD CLOB;
BEGIN
   
 -- Get Context

    CTX := DBMS_XMLQUERY.NEWCONTEXT(XMLSQL);
    -- Encoding Setting
    DBMS_XMLQUERY.SETENCODINGTAG(CTX, ENCODINGTYPE);

    -- Make XML
    XMLRECORD := DBMS_XMLQUERY.GETXML(CTX);

    RETURN xmlRecord;
END GET_XML_RECORD;


--------------------------------------------------------------------------------------
결과물(Result) XML
--------------------------------------------------------------------------------------

<?xml version="1.0" encoding="utf-8"?>
<ROWSET>
  <ROW num="1">
    <BU>111100</BU>
    <PART>Foods</PART>
    <TOT_CNT>3121</TOT_CNT>
    <TOT_AMT>33686366</TOT_AMT>
  </ROW>
  <ROW num="2">
    <BU>111200</BU>
    <PART>Equipments</PART>
    <TOT_CNT>4052</TOT_CNT>
    <TOT_AMT>25262637</TOT_AMT>
  </ROW>
  <ROW num="3">
    <BU>121100</BU>
    <PART>Family</PART>
    <TOT_CNT>211</TOT_CNT>
    <TOT_AMT>11398870</TOT_AMT>
  </ROW>
  <ROW num="4">
    <BU>121200</BU>
    <PART>Kids Ware</PART>
    <TOT_CNT>266</TOT_CNT>
    <TOT_AMT>10468550</TOT_AMT>
  </ROW>
  <ROW num="5">
    <BU>151100</BU>
    <PART>Ladys</PART>
    <TOT_CNT>457</TOT_CNT>
    <TOT_AMT>31542110</TOT_AMT>
  </ROW>
  <ROW num="6">
    <BU>161100</BU>
    <PART>Uniforms</PART>
    <TOT_CNT>214</TOT_CNT>
    <TOT_AMT>25224724</TOT_AMT>
  </ROW>
  <ROW num="7">
    <BU>181100</BU>
    <PART>Fashions</PART>
    <TOT_CNT>499</TOT_CNT>
    <TOT_AMT>43861240</TOT_AMT>
  </ROW>
  <ROW num="8">
    <BU>191100</BU>
    <PART>Sports</PART>
    <TOT_CNT>405</TOT_CNT>
    <TOT_AMT>31456710</TOT_AMT>
  </ROW>
  <ROW num="9">
    <BU>321100</BU>
    <PART>Culture</PART>
    <TOT_CNT>17</TOT_CNT>
    <TOT_AMT>32500</TOT_AMT>
  </ROW>
</ROWSET>

C# XML처리

원래 Oracle의 XML관련 패키지를 설치하면 쿼리 결과를 바로 XML로 받을수 있지만
DBA에 요청하니 시스템 관리 업체에 얘기해서 뭐 어쩌고 저쩌고..
어제오전에 얘기했는데.. 하루가 지난 오늘도 설치가 안돼 있다.
그래서.. 테스트도 할 겸 C#으로 간단하게 만들었다.

처리의 핵심은 복잡한 쿼리 결과를 웹으로 조회할 경우
접속과 요청이 있을때마다 쿼리를 보내게 되므로 커넥션쪽에도 부하가 걸리고
DB쿼리에도 부하가 걸려 전체적인 DB성능에 영향을 주게 되므로
지정간격으로 DB를 쿼리하고(물론 요청이 없으면 하지 않음) XML을 만들어
그 XML을 웹페이지가 가져가서 처리하도록 하는것이다.

지속적으로 파일을 만드는 일이라 물리DISK의 특정위치에 대한  집중적 사용으로
손상도 우려되어 5개의 파일 정도를 계속 유지할 수 있도록 하였고
XML기록중 다른 프로세스가 읽는것을 방지하기 위하여
쿼리와 동시에 XML을 바로 기록하지 않고 단번에 기록할수 있게 결과 완료후 기록하도록 했다.


쿼리문의 결과를 XML형태로 만들어 반환 (String)
메모리스트림을 사용하므로 물리적 디스크 Access가 없음

    // 쿼리결과를 XML로 만들어 반환
    private string makeQueryToXML(string connStr, string sql)
    {
        string result = "";
        OracleConnection DB = null;
        MemoryStream ms = null;
        try
        {
            DB = new OracleConnection(ConfigurationManager.ConnectionStrings[connStr].ConnectionString);
            DB.Open();
            OracleDataAdapter adapter = new OracleDataAdapter();
            adapter.SelectCommand = new OracleCommand(sql, DB);
            DataSet ds = new DataSet();
            adapter.Fill(ds);
            // 자료가 있어야만 XML 생성
            if (ds.Tables[0].Rows.Count > 0)
            {
                string[] colName = new string[ds.Tables[0].Columns.Count];
                for (int i = 0; i < ds.Tables[0].Columns.Count; i++)
                    colName[i] = ds.Tables[0].Columns[i].ColumnName.Trim();
                ms = new MemoryStream();
                // XML 생성
                XmlTextWriter textWriter = new XmlTextWriter(ms, Encoding.UTF8);
                // 들여쓰기 설정
                textWriter.Formatting = Formatting.Indented;
                // 문서에 쓰기 시작
                textWriter.WriteStartDocument();
                // 루트 설정
                textWriter.WriteStartElement("ROWSET");
                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    // ROW 노드와 값 설정
                    textWriter.WriteStartElement("ROW");
                    textWriter.WriteStartAttribute("num");
                    textWriter.WriteValue(i + 1);
                    textWriter.WriteEndAttribute();
                    // COLUMN 노드 값 설정
                    for (int j = 0; j < ds.Tables[0].Columns.Count; j++)
                    {
                        textWriter.WriteStartElement(colName[j]);
                        textWriter.WriteString(ds.Tables[0].Rows[i][j].ToString());
                        textWriter.WriteEndElement();
                    }
                    textWriter.WriteEndElement();
                }
                textWriter.WriteEndElement();
                textWriter.WriteEndDocument();
                textWriter.Close();
                result = Encoding.UTF8.GetString(ms.GetBuffer()).Trim();
                ms.Close();
                ms.Dispose();
                ms = null;
            }
            DB.Close();
            return result;
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
            return result;
        }
        finally
        {
            if (ms != null)
            {
                ms.Close();
                ms.Dispose();
            }
            if (DB != null)
                DB.Close();
        }
    }

1. 지정시간 이내에 만들어진 XML이 있는지 검사.
2. 있을경우 크기가 10바이트 미만이면 다른 프로세서가 XML을 생성중인 것으로 판단 직전생성된 XML 파일이름을 Return ()
3. 10바이트 보다 크면 정상적인 XML파일로 판단 파일이름 Return ()
3. 없을경우 오래된 XML파일을 삭제(항상 동일 갯수만 생성되어 있도록 유지)
4. 0바이트의 XML파일을 만듦 : XML자료 생성 도중 다른 프로세스가 읽어가는것을 방지
5. makeQueryToXML로 부터 받아온 XML데이터를 파일로 저장함
6. 새로 만들어진 XML 파일이름을 Return ()

    private string makeXML(string path, string prefix, string connStr, string sql, int delay_second)
    {
        // 반복간격이 5초 미만이면 처리하지 않음
        if (delay_second < 5)
            return "";
        string result = "";
        FileStream fs = null;
        StreamWriter writer = null;
        OracleConnection DB = null;
        try
        {
            DirectoryInfo di = new DirectoryInfo(path);
            FileInfo[] fi = di.GetFiles(prefix + "*.xml");
            if (fi.Length > 0)
            {
                // 마지막 자료와의 시간차 구하기
                int lastCnt = fi.Length - 1;
                string check = fi[lastCnt].Name.Replace(".xml", "").Replace(prefix, "");
                DateTime cdate = DateTime.Parse(check.Substring(0, 4) + "-" + check.Substring(4, 2) + "-" +
                    check.Substring(6, 2) + " " + check.Substring(8, 2) + ":" + check.Substring(10, 2) + ":" +
                    check.Substring(12, 2));
                TimeSpan ts = DateTime.Now - cdate;
                if (ts.Seconds < delay_second)
                {
                    // 파일크기가 10바이트 미만이면 직전 파일명 반환 : 현재 XML 생성중으로 판단
                    if (fi[lastCnt].Length < 10)
                        lastCnt--;
                    return fi[lastCnt].FullName;
                }
                // 오래된 XML 삭제
                try
                {
                    for (int i = 0; i < (fi.Length - 4); i++)
                    {
                        File.Delete(fi[i].FullName);
                    }
                }
                catch
                {
                }
            }
            // XML 파일 생성: 0 Byte
            result = path + "\\" + prefix + string.Format("{0:yyyyMMddHHmmss}", DateTime.Now) + ".xml";
            fs = new FileStream(result, FileMode.Create);
            writer = new StreamWriter(fs);
            writer.Close();
            fs.Close();
            // XML 자료 생성
            string xmlResult = makeQueryToXML(connStr, sql);
            // XML 파일 기록 : 실제 내용 기록
            fs = new FileStream(result, FileMode.Append);
            writer = new StreamWriter(fs);
            writer.WriteLine(xmlResult);
            writer.Close();
            fs.Close();
            return result;
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
            // 오류 났으면 삭제해 버림
            if (result != "")
            {
                if (File.Exists(result))
                    File.Delete(result);
            }
            return "";
        }
        finally
        {
            if (writer != null)
                writer.Close();
            if (fs != null)
                fs.Close();
            if (DB != null)
                DB.Close();
        }
    }

XML을 읽어서 ArrayList [string[]] 으로 Return
Client에서 XML자체를 받아 파싱할수도 있지만, 편한대로 처리함

    /// <summary>
    /// XML을 읽어서 결과 ArrayList를 되돌려준다.
    /// </summary>
    /// <param name="filename">XML 파일</param>
    /// <param name="field_list">필드 목록 : 대소문자 구분해야함!</param>
    /// <returns></returns>
    private ArrayList ReadXML(string filename, string[] field_list)
    {
        ArrayList result = new ArrayList();
        try
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(filename);
            XmlElement root = xmldoc.DocumentElement;
            // 노드 요소들
            XmlNodeList nodes = root.ChildNodes;
            // 노드 요소의 값을 읽어 옵니다.
            foreach (XmlNode node in nodes)
            {
                if (node.Name.ToLower().Trim() == "row")
                {
                    string[] row = new string[field_list.Length];
                    for (int i = 0; i < field_list.Length; i++)
                    {
                        row[i] = node[field_list[i]].InnerText;
                    }
                    result.Add(row);
                }
            }
        }
        catch (Exception ex)
        {
            Response.Write(ex.ToString());
        }
        return result;
    }

2010년 11월 5일 금요일

PowerBuilder DB로 부터 새로운 버전의 파일을 다운로드

Oracle DB의 LONGRAW 필드에 binary EXE 또는 Image 등을 업로드 해 놓고 Client의 Program 실행시에
버전을 검사하여 하위버전인 경우 다운로드 하도록 하는 프로그램.
업무구분에 따라 경로가 고정되어 있었으나 경로의 복잡성이 추가되어
파일이름에 경로를 붙여 사용하도록 협의되어 일부 수정되었다.

SetPointer(HourGlass!)
/* Transaction Connection */
File_Tran = Create Transaction
File_Tran.dbms       = dbms
File_Tran.logid      = userid
File_Tran.logpass    = passwd
File_Tran.servername = servername

Connect Using File_Tran;
If File_Tran.sqlcode <> 0  Then
    MessageBox ("확인",' 데이터베이스 연결 실패입니다.')
    Halt Close
    Return
End If


/* 선언부 */
String   FileName,   Version_PC,  FileStyle
String   RootPath,   FullPath,    EtcPath, FilePath, IniPath, ExePath
String   ConnectParm
Boolean  lb_Check = False

Integer  li_I, FP ,  Loops,       li_Complete,    Version_SR
Long     FLen = 0,   bytes_Read = 0,  Start_Pos = 0, Next_Pos = 0
Blob     ImageData,  Blob_Chunk


/* PC 에서 최초 실행시 각 사용자별  디렉토리 생성 */
RootPath = 'c:\program'                 // 기본 디렉토리
FullPath = RootPath + '\' + gs_UserID   //------ 실행 화일관리
EtcPath  = FullPath + '\' + 'etc'       //------ 기타화일 관리

/* 화일 저장 디렉토리 생성 */
If FileExists(RootPath) Then
    If FileExists(FullPath) Then
    If FileExists(EtcPath) = False Then
            CreateDirectoryA(EtcPath,0) 
        End If
    Else
        CreateDirectoryA(FullPath,0) 
        CreateDirectoryA(EtcPath,0)     
    End If
Else
    CreateDirectoryA(RootPath,0)
    CreateDirectoryA(FullPath,0) 
    CreateDirectoryA(EtcPath,0)       
End If  

/* 각 단위 업무 수정사항  조회 */
DECLARE Cur_File CURSOR FOR
    SELECT VER_FILENAME,         VER_VERSION,    VER_EXT_STYLE
    FROM CLSM_VER11_PROGRAM
    WHERE VER_UPMUCODE = :gs_JobGubun OR
        VER_UPMUCODE = 'S'
    ORDER BY VER_FILENAME   ASC  using File_Tran;

OPEN Cur_File;
FETCH Cur_File INTO :FileName, :Version_SR,  :FileStyle;

/* 화일 버전 체크 위항 ini 화일 체크하고 생성 */
IniPath = FullPath + '\' + gs_UserID + '.ini'
wf_Write_ini(IniPath, gs_UserID)


// 2010. 11. 6 수정
// dwis 추가로 Filename에 경로를 붙여 처리하도록 수정
//-----------------------------------------------------------------------------------------------------

String ls_full_name = ""
String ls_split_name = ""
String ls_target_path = ""
integer li_root_pos

DO WHILE File_Tran.SQLCode = 0 
    //-----------------------------------------------------------------------------------------------------
    // 저장할 경로가 존재하는지 검사 : 없으면 새로 만듦
    //-----------------------------------------------------------------------------------------------------
 

    ls_full_name = FileName 
    // 먼저 파일명을 제외한 패스가 존재하는지 부터 점검 
    ls_target_path = midA(ls_full_name, 1, Len(ls_full_name) - Pos(Reverse(ls_full_name), "\")) 
    ls_split_name = ""
    // 없으면 아래를 실행
    If Not FileExists(ls_target_path) Then
        DO while(true)
            li_root_pos = pos(ls_full_name, "\")
   

            // 마지막 자료는(\가 없음) Skip << 파일이름
            IF li_root_pos < 1 THEN
                EXIT
            END IF
            If ls_split_name = "" then
                ls_split_name += midA(ls_full_name, 1, li_root_pos - 1)
            else
                ls_split_name += "\" + midA(ls_full_name, 1, li_root_pos - 1)
            end if
            ls_full_name = midA(ls_full_name, li_root_pos + 1)

            // 드라이브 문자열만 들어올 경우 Skip (ex: c:, d: << \ 기호가 없음)

            If pos(ls_split_name, "\") > 0 Then   
                // 경로가 없을 경우 생성
                If Not FileExists(ls_split_name) Then
                    CreateDirectoryA(ls_split_name,0)
                End If
            End If
        LOOP
    End If

    //-----------------------------------------------------------------------------------------------------
    Version_PC = ProfileString(IniPath, FileName, 'FileVersion', "X")

    If (Version_SR <> Integer(Version_PC)) OR Version_PC = 'X' Then
        If lb_Check = False Then
            // 다운 받고 있을때의 Animation // 

            This.Title = '화일 내려받는 중 '        
            DelAnim()
            Trigger Event ue_animation()
  
             lb_Check = True
        End If     
 
        uo_1.uf_setvisible(0)
        st_filename.Text = FileName
      
        SELECTBLOB VER_FILESOURCE
        INTO :ImageData
        FROM CLSM_VER11_PROGRAM
        WHERE VER_FILENAME = :FileName    AND
             (VER_UPMUCODE= :gs_jobgubun OR
            VER_UPMUCODE= 'S' )
        using File_Tran ;

        IF File_Tran.Sqlcode <> 0  THEN
        DisConnect Using File_Tran;
        DelAnim()
        Halt Close
        Return
    End If 

    //-----------------------------------------------------------------------------------------------------
    // 파일 이름에 \이 포함된경우 이름 그대로 경로처리 : 추가

    If Pos(FileName, "\") > 0  Then
        FilePath = FileName
    Else

        // 기존 처리 방식
        /* 실행화일과 PBD 이외의 화일은 BMP 디렉토리에 관리 */

        If Upper(FileStyle) = 'EXE' OR Upper(FileStyle) = 'PBD' Then
            FilePath = FullPath + '\' + FileName               
        ElseIf Upper(FileStyle) = 'BMP' Then
            FilePath = RootPath + '\install\bmp\' + FileName
        ElseIf Upper(FileStyle) = 'DLL' Then 
            FilePath = RootPath + '\install\lib\' + FileName
        Else
            FilePath = EtcPath + '\' + FileName
        End If
    End If
    //----------------------------------------------------------------------------------------------------- 
    FP = FileOpen(FilePath, StreamMode!, Write!,LockWrite!, replace!)  
    ///// **** 화일 변수 책정 초기화 **** ///////

    Next_Pos = 1;   Loops = 0;   FLen = 0
    IF FP <> 0 then
        Flen = Len(ImageData)
        st_size.Text = String(FLen,'#,###,###')
        If FLen > 32765 Then
            If Mod(FLen,32765) = 0 Then
                Loops = FLen/32765
            Else
                Loops = (FLen/32765) + 1
            End If
        Else
            Loops = 1
        End If

        If Loops = 1 Then
            Bytes_Read = FileWrite(FP,ImageData)
            uo_1.uf_setvisible(100)  
        Else
            For li_I = 1 To Loops
                    li_Complete = ( (32765 * li_I ) / Len(ImageData)) * 100
                    uo_1.uf_setvisible(li_Complete)
                    If li_I = Loops Then
                        Blob_Chunk = BlobMid(ImageData,Next_Pos)
                    Else
                        Blob_Chunk = BlobMid(ImageData,Next_Pos,32765)
                    End If
                    Bytes_Read = FileWrite(FP, Blob_Chunk)
                    Next_Pos   = Next_Pos + Bytes_Read
                Next 
            End If
         
            FileClose(FP)
 
            ///// 차후 화일 다운 받기 위한 초기화 화일 /////

            SetProfileString(IniPath, FileName, 'FileVersion', String(Version_SR)) 
        End If
    End If

    FileName = '';    Version_PC = '';

    FETCH Cur_File INTO :FileName, :Version_SR,  :FileStyle;
LOOP

CLOSE Cur_File;
/* 실행 화일 넘겨질 변수 설정 */
ConnectParm = gs_UserID + '/' + gs_UserPassWD + '/' + dbms + '/' + servername +&
              '/' + gs_Jobgubun + '/' + gs_Sabun + '/' + gs_Passwd + '/' + '' + '/'

ExePath = FullPath + '\' + gs_UserID + '.exe '

If FileExists(ExePath) = False Then
    DisConnect Using File_Tran;
    MessageBox("확인", '당 업무 해당 실행화일이 없습니다. 프로그램을 종료하겠습니다.'&
                       ,StopSign!)
    Halt Close
    Return
End If  

Close(This)
Close(w_jobbmp_display)

//각 단위 업무 화일  실행 //
Run(ExePath + ConnectParm)



ASP.NET에서 다른컴퓨터의 폴더 Access

web.config의 <system.web> 내부에 다음 항목 추가

      <identity impersonate="true" userName="사용자계정" password="암호" />

폴더를 Access할때 위 계정정보를 사용하여 Access함.
당연히, 해당 컴퓨터에 사용자 정보를 만들어 줘야함

OCR 인식 테스트 : MS Officce Document Imaging : 배율확대에 의한 인식율

MS Office Document Imaging의 OCR 인식 기능을 사용하여 숫자만 가득한 이미지를 테스트 해 보았다.
인식이 잘 되는 경우도 있고 안되는 경우도 있어서 이미지를 단계별로 확대해 가며 정확하게 읽어지는지 검사했다.
주로 1.4배~1.7배 사이에서 인식이 잘 되는것 같긴 한데..
이미지에 따라 인식율이 다르게 나온다.

더 나은 OCR 라이브러리가 필요할듯...

1x    115440 4,285 4,260 4.320 4,260 4 290 4,930 3,650 3,660 15 4.. 260 1 090
1.1x  115440 4285 4,260 4,320 4,260 4, 290 4,930 3650 3,660 15 4, 261) 1 .fl
1.2x  115440 4,285 4,260 4,320 4260 4,290 4,930 3,650 3,660 15 4,260 1 .090
1.3x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 I L LJJ L090
1.4x  115440 4.285 4.260 4.320 4.260 4.2% 4.930 3.650 3.660 15 4.260 1.090
1.5x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 1090
1.5x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 1090  24bit
1.6x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 1,090 *****
1.7x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 1,090
1.8x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 L090
1.9x  115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 3,660 15 4,260 1,090
2x    115440 4,285 4,260 4,320 4,260 4,290 4,930 3,650 I_I, ? 15 4,260 1,090
3x    p _ C) N) 0, CDN)N)C)N) CD 0, 0, C) CD 0, N) 0, C) 0, (1 p p (T

* 정규식
[0-9]{5,6}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}\s+[\,\.0-9]{2,10}

C#에서 MD5 암호화 사용

public string GetMD5Hash(string input)
{
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
bs = x.ComputeHash(bs);
System.Text.StringBuilder s = new System.Text.StringBuilder();
foreach (byte b in bs)
{
s.Append(b.ToString("x2").ToLower());
}
string password = s.ToString();
return password;
}

Rijndael(AES) 암/복호화 코드(C#)

AES 미국 정부에서 민감한 정보들을 암호화하는 사용되는 표준 /복호화 알고리즘입니다. 현재 업계 표준이고, 아직까지는 알려진 약점이 없는 가장 안전한 /복호화 알고리즘입니다. 최근에 일부 SI 프로젝트에서는 방식을 것을 요구하기도 합니다.

1. 암호화

private static string EncryptString(string InputText, string Password)
{
// Rihndael class를 선언하고, 초기화 합니다
RijndaelManaged RijndaelCipher = new RijndaelManaged();

// 입력받은 문자열을 바이트 배열로 변환
byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(InputText);

// 딕셔너리 공격을 대비해서 키를 더 풀기 어렵게 만들기 위해서
// Salt를 사용합니다.
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());

// PasswordDeriveBytes 클래스를 사용해서 SecretKey를 얻습니다.
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);

// Create a encryptor from the existing SecretKey bytes.
// encryptor 객체를 SecretKey로부터 만듭니다.
// Secret Key에는 32바이트
// (Rijndael의 디폴트인 256bit가 바로 32바이트입니다)를 사용하고,
// Initialization Vector로 16바이트
// (역시 디폴트인 128비트가 바로 16바이트입니다)를 사용합니다
ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

// 메모리스트림 객체를 선언,초기화 
MemoryStream memoryStream = new MemoryStream(); 

// CryptoStream객체를 암호화된 데이터를 쓰기 위한 용도로 선언
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
                 
// 암호화 프로세스가 진행됩니다.
cryptoStream.Write(PlainText, 0, PlainText.Length);
                 
// 암호화 종료
cryptoStream.FlushFinalBlock();

// 암호화된 데이터를 바이트 배열로 담습니다.
byte[] CipherBytes = memoryStream.ToArray();



// 스트림 해제
memoryStream.Close();
cryptoStream.Close();
       
// 암호화된 데이터를 Base64 인코딩된 문자열로 변환합니다.
string EncryptedData = Convert.ToBase64String(CipherBytes);

// 최종 결과를 리턴
return EncryptedData;
}

2. 복호화

private static string DecryptString(string InputText, string Password)
{
RijndaelManaged  RijndaelCipher = new RijndaelManaged();

byte[] EncryptedData = Convert.FromBase64String(InputText);
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
       
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
       
// Decryptor 객체를 만듭니다.
ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));

MemoryStream  memoryStream = new MemoryStream(EncryptedData);
           
// 데이터 읽기(복호화이므로) 용도로 cryptoStream객체를 선언, 초기화
CryptoStream  cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);

// 복호화된 데이터를 담을 바이트 배열을 선언합니다.
// 길이는 알 수 없지만, 일단 복호화되기 전의 데이터의 길이보다는
// 길지 않을 것이기 때문에 그 길이로 선언합니다
byte[] PlainText = new byte[EncryptedData.Length];
       
// 복호화 시작
int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);
               
memoryStream.Close();
cryptoStream.Close();
       
// 복호화된 데이터를 문자열로 바꿉니다.
string DecryptedData = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);
       
// 최종 결과 리턴
return DecryptedData;
}