'2010년 이전 글/프로그래밍'에 해당되는 글 43건
- 2008.03.04
- 2007.10.23
- 2007.10.23
- 2007.10.23
- 2007.10.23
- 2007.10.12
- 2007.09.21
- 2007.08.17
- 2007.08.17
- 2007.07.03
/*************************************************************
최종수정일:
일반함수
btMov_AddList
checkNumber
일반함수
BT_getComboData 셀렉트 생성
BT_CheckLastAcctno 계좌번호 끝에 3자리 000 제거
BT_makeAcntnoDash 계좌번호에 하이픈을 넣음
BT_MakeAcntList 계좌번호를 리스트로 만듬
BT_MakePayAcntList 계좌번호를 리스트로 만듬
BT_ReduceDash 하이픈을 삭제
BT_makeCardnoDash 카드번호 하이픈 넣기
BT_getToday 오늘 날짜열을 YYYYMMDD의 형식으로 만듬
BT_make2Length 월일을 두자리로 만듬
BT_makeCardnoDash 카드번호 하이픈 넣음
BT_makeMembernoDash 회원번호(16자리) 하이픈 넣기
BT_TrimSpace 공백없애기
BT_calc 금액 더하기 계산
BT_Del_comma 콤마 삭제
BT_Add_comma 입력폼 작성시 콤마 추가
BTCom_Replace 문자변환
BT_Add_Displaycomma 금액 Display 시 콤마 추가
BT_Add_NumberComma 금액의 앞자리 0을 없애고 콤마추가
BT_Add_NumberComma1
BT_toMoneyF 환율,외화에 소수점,콤마 추가
BT_Reduce_comma 콤마 제거
BT_isAlphabet 값이 알파벳만 있는지 체크
BT_isNumber 값이 숫자만 있는지 체크
BT_number 숫자만 입력
BT_isTrsfPass 이체 비밀번호 체크 루틴
BT_getRandomNumber 씨크릿 카드 번호 생성
BT_makeCustnoDash 9자리 고객번호 하이픈을 넣음
BT_makeResnoDash 주민번호 하이픈 넣기
BT_makeLoannoDash 대출계좌에 하이픈 넣기
BT_makeDateDash yyyy-mm-dd
BT_makeDateDash_1 yyyy-mm
BT_makeDateDash_2 mm-dd
BT_makeDateDash_3 mm
BT_makeTime 00:00:00
BT_StrToInt 문자열을 10진수로 변환
BT_makeDecimalPoint 소수점이 포함된 숫자 앞에 포함된 0 을 제거
last_page 페이지 설정
BT_EngNum 숫자와영어만 허용
BT_SetServiceCode ServiceCode박아주기
BT_Setreturn_url return_url 박아주기
BT_getRandomNumber() { //씨크릿 카드 순차번호 생성
pwCheck() 비밀번호 연번 확인 => 주석확인
***************************************************************/
var alphaArray = new Array();
alphaArray[0] = 'a' ;alphaArray[1] = 'b';alphaArray[2] = 'c';alphaArray[3] = 'd';
alphaArray[4] = 'e' ;alphaArray[5] = 'f';alphaArray[6] = 'g';alphaArray[7] = 'h';
alphaArray[8] = 'i' ;alphaArray[9] = 'j';alphaArray[10] = 'k';alphaArray[11] = 'l';
alphaArray[12] = 'm';alphaArray[13] = 'n';alphaArray[14] = 'o';alphaArray[15] = 'p';
alphaArray[16] = 'q';alphaArray[17] = 'r';alphaArray[18] = 's';alphaArray[19] = 't';
alphaArray[20] = 'u';alphaArray[21] = 'v';alphaArray[22] = 'w';alphaArray[23] = 'x';
alphaArray[24] = 'y';alphaArray[25] = 'z';
alphaArray[26] = 'A';alphaArray[27] = 'B';alphaArray[28] = 'C';alphaArray[29] = 'D';
alphaArray[30] = 'E';alphaArray[31] = 'F';alphaArray[32] = 'G';alphaArray[33] = 'H';
alphaArray[34] = 'I';alphaArray[35] = 'J';alphaArray[36] = 'K';alphaArray[37] = 'L';
alphaArray[38] = 'M';alphaArray[39] = 'N';alphaArray[40] = 'O';alphaArray[41] = 'P';
alphaArray[42] = 'Q';alphaArray[43] = 'R';alphaArray[44] = 'S';alphaArray[45] = 'T';
alphaArray[46] = 'U';alphaArray[47] = 'V';alphaArray[48] = 'W';alphaArray[49] = 'X';
alphaArray[50] = 'Y';alphaArray[51] = 'Z';
function getCode(argObj1,argObj2){
Key1 = argObj1;
Key2 = argObj2;
if(top.iWallet.LoadCode_state == false){
top.iWallet.LoadCode = top.iWallet.LoadCode + 1;
if(top.iWallet.LoadCode <= 5){
setTimeout("getCode(Key1,Key2)", 1000)
}else{
alert("코드 초기화에 실패하였습니다.\n처음으로 돌아갑니다.")
SID = get_sessionid();
CryptoClient.Logout(SID);
top.location.href="/btindex.asp";
}
}else{
retString = ""
try {
sKey = argObj1 + "^" + argObj2;
retString = top.iWallet.sTradcode[sKey];
if (!retString) retString = "";
return retString;
}catch(e) {
return "";
}
}
}
//OPEN창에서 사용
function getCode2(argObj1,argObj2){
Key1 = argObj1;
Key2 = argObj2;
if(opener.top.iWallet.LoadCode_state == false){
opener.top.iWallet.LoadCode = opener.top.iWallet.LoadCode + 1;
if(opener.top.iWallet.LoadCode <= 5){
setTimeout("getCode2(Key1,Key2)", 1000)
}else{
alert("코드 초기화에 실패하였습니다.\n처음으로 돌아갑니다.")
SID = get_sessionid();
CryptoClient.Logout(SID);
top.location.href="/btindex.asp";
}
}else{
retString = ""
try {
sKey = argObj1 + "^" + argObj2;
retString = opener.top.iWallet.sTradcode[sKey];
if (!retString) retString = "";
return retString;
}catch(e) {
return "";
}
}
}
function BT_LoadCode(){
var dgbcode=ttradcode();
tmp1 = dgbcode.split("^^^");
for(k=0;k<tmp1.length;k++){
tmp2 = tmp1[k].split("^^");
top.iWallet.sTradcode[tmp2[0]]=tmp2[1];
}
}
//코드구분, 셀렉트이름, selected값
function BT_getComboData(argObj1,selname,argObj2){
Key1 = argObj1;
Key2 = selname;
Key3 = argObj2;
if(top.iWallet.LoadCode_state == false){
top.iWallet.LoadCode = top.iWallet.LoadCode + 1;
if(top.iWallet.LoadCode <= 5){
setTimeout("BT_getComboData(Key1,Key2,Key3)", 1000)
}else{
alert("코드 초기화에 실패하였습니다.\n처음으로 돌아갑니다.")
SID = get_sessionid();
CryptoClient.Logout(SID);
top.location.href="/btindex.asp";
}
}else{
try {
var data=top.iWallet.ttradcode();
var split_data=data.split("^^^");
var len = split_data.length;
var L_ListText = "<select name=\"" + selname + "\" id=\"" + selname + "\">";
for(i=0;i<len;i++) {
var splitdata_in=split_data[i].split("^^");
var splitdata_in2=splitdata_in[0].split("^");
if(splitdata_in2[0] == argObj1)
{
if (splitdata_in2[1] == argObj2) {
L_ListText += "\t<option value=\"" + splitdata_in2[1] + "\" selected>" + splitdata_in[1] + "</option>\n";
} else {
L_ListText += "\t<option value=\"" + splitdata_in2[1] + "\">" + splitdata_in[1] + "</option>\n";
}
}
}
L_ListText = L_ListText + "</select>"
return L_ListText;
}catch(e) {
return false;
}
}
}
function btAlertNoValue ( thisvalue , alertvalue )
{
if ( thisvalue.value == "" )
{
var smsg;
smsg = alertvalue + "을(를) 입력하셔야 합니다.";
alert(smsg);
thisvalue.focus();
return 1;
}
return 0;
}
function btMov_AddList(argObj, argData, argValue,selval){
argObj.length = argObj.length + 1
argObj.options(argObj.length-1).text = argData
argObj.options(argObj.length-1).value = argValue
if(selval != "" && selval == argValue) argObj.options(argObj.length-1).selected = true;
}
//숫자외의 문자 check
function checkNumber(data) {
t = data.value ;
for(i=0;i<t.length;i++)
if (t.charAt(i)<'0' || t.charAt(i)>'9') {
if (t.charAt(i) != '*') {
alert("숫자만 입력해주세요.") ;
data.value="";
data.focus() ;
return false ;
}
}
}
function btTextCheckDate(Dnum,StaYer,StaMon,StaDay,EndYer,EndMon,EndDay)
{
now = new Date();
var cur_year= now.getYear();
var cur_month = now.getMonth();
var month = now.getMonth()+1;
month=new String(month);
var cur_day = now.getDate();
cur_day=new String(cur_day);
var d_cur_date = new Date(cur_year,cur_month,cur_day);
var dategubun;
var num = Dnum;
eval("doc."+StaYer+".readOnly = true");
eval("doc."+StaMon+".readOnly = true");
eval("doc."+StaDay+".readOnly = true");
eval("doc."+EndYer+".readOnly = true");
eval("doc."+EndMon+".readOnly = true");
eval("doc."+EndDay+".readOnly = true");
if(num==0){ //당일
var before_date = new Date(Date.parse(d_cur_date) - 1*1000*60*60*24);
dategubun = "1주일전";
}else if(num==1){ //1주일전
var before_date = new Date(Date.parse(d_cur_date) - 7*1000*60*60*24);
dategubun = "1주일전";
}else if(num==2){ //15일전
var before_date = new Date(Date.parse(d_cur_date) - 15*1000*60*60*24);
dategubun = "15일전";
} else if(num==3){ //30일
var before_date = new Date(Date.parse(d_cur_date) - 30*1000*60*60*24);
dategubun = "30일";
} else if(num==4){ //기간설정(3개월)
var before_date = new Date(Date.parse(d_cur_date) - 91*1000*60*60*24);
eval("doc."+StaYer+".readOnly = false");
eval("doc."+StaMon+".readOnly = false");
eval("doc."+StaDay+".readOnly = false");
eval("doc."+EndYer+".readOnly = false");
eval("doc."+EndMon+".readOnly = false");
eval("doc."+EndDay+".readOnly = false");
dategubun = "기간설정";
}
var yest_date = new Date(Date.parse(d_cur_date)-1000*60*60*24);
var yest_year = new String(yest_date.getYear());
var yest_month = new String(yest_date.getMonth()+1);
if(yest_month.length==1){
yest_month = '0'+yest_month;
}
if(month.length==1){
month = '0'+ month;
}
if(cur_day.length==1){
cur_day = '0'+cur_day;
}
var before_year = new String(before_date.getYear());
var before_month = new String(before_date.getMonth() +1);
if(before_month.length==1){
before_month = '0'+before_month;
}
var before_day = new String(before_date.getDate());
if(before_day.length==1){
before_day = '0'+before_day;
}
if(num==0){
eval("doc."+StaYer+".value=cur_year");
eval("doc."+StaMon+".value=month");
eval("doc."+StaDay+".value=cur_day");
eval("doc."+EndYer+".value=cur_year");
eval("doc."+EndMon+".value=month");
eval("doc."+EndDay+".value=cur_day");
}
else if(num==4){
eval("doc."+StaYer+".value=''");
eval("doc."+StaMon+".value=''");
eval("doc."+StaDay+".value=''");
eval("doc."+EndYer+".value=''");
eval("doc."+EndMon+".value=''");
eval("doc."+EndDay+".value=''");
}
else
{
eval("doc."+StaYer+".value=before_year");
eval("doc."+StaMon+".value=before_month");
eval("doc."+StaDay+".value=before_day");
eval("doc."+EndYer+".value=cur_year");
eval("doc."+EndMon+".value=month");
eval("doc."+EndDay+".value=cur_day");
}
}
//*-- 필드 AutoSkip --*//
function btAutoSkip(){
var el = event.srcElement
if ((el.value == null) || (event.keyCode==13)) return(false)
// 방향키 무시
var sKeys = "8;16;46;;37;38;39;40;33;34;35;36;45;229;"
if (sKeys.indexOf(event.keyCode+";") > -1) return;
if (el.tagName == "INPUT" )
if (el.value.length >= el.maxLength ) {
var i=0
while (el != el.form.elements[i] ) i++
if ( (i+1) != el.form.elements.length ) {
while ( ( el.form.elements[i+1].type == "hidden" ) ||
( el.form.elements[i+1].type == "button" ) ||
( el.form.elements[i+1].type == "checkbox" ) ||
( el.form.elements[i+1].type == "radio" ) ||
( el.form.elements[i+1].tagName == "FIELDSET" ) ||
( el.form.elements[i+1].style.display == "none" ) ||
( el.form.elements[i+1].disabled == true ) ||
( el.form.elements[i+1].style.visibility == "hidden" )) {
i++
if ( (i+1) == el.form.elements.length ) return;
}
}
else{
el.form.elements[i].focus();
return(false);
}
el.form.elements[i+1].focus()
if(el.form.elements[i+1].tagName != "SELECT") el.form.elements[i+1].select()
else if(el.form.elements[i+1].tagName == "SELECT") {
if(el.form.elements[i+1].value==null || el.form.elements[i+1].selectedIndex==-1)
el.form.elements[i+1].value = "";
}
}
}
//계좌번호에 하이픈 넣기 - pansory
function BT_makeAcntnoDash (val) {
var DashedAcntno = val
if (val.length == 11) { //계좌번호가 11자리일 경우
DashedAcntno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5)
} else if (val.length == 12){
DashedAcntno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5,11) + "-" + val.substring(11)
}else if(val.length == 13) { //계좌번호가 13자리일 경우
DashedAcntno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5,11) + "-" + val.substring(11)
} else if (val.length == 14) { //계좌번호가 14자리일 경우
DashedAcntno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5,11) + "-" + val.substring(11)
} else if (val.length == 16){
DashedAcntno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5,11) + "-" + val.substring(11)
}
return DashedAcntno;
}
//계좌번호 끝3자리에서 000 제거
function BT_CheckLastAcctno(val){
var TempAccntno = val;
var len = val.length;
var tempAcc = len - 3;
var lastAccNo = val.substring(tempAcc, len);
if (lastAccNo == "000"){
TempAccntno = BT_makeAcntnoDash(val.substring(0, tempAcc));
} else {
TempAccntno = BT_makeAcntnoDash(TempAccntno);
}
return TempAccntno;
}
//계좌번호 선택..
function BT_SelectAcntno(USR_AccsList, NeedAcntno) {
var no = NeedAcntno.length;
var Acntno_No = USR_AccsList.length;
var SelectedAcntno = new Array();
var k = 0;
if (no == 0) {
SelectedAcntno = USR_AccsList;
//나중에 확인 필요함.. 고른 것들 중에 첫번째 것을 세션에 넣기..????
save_session("ACNTNO", USR_AccsList[0]);
save_flush();
} else {
for (var i=0; i < Acntno_No ; i++) {
for(var j=0 ; j < no; j++) {
if(USR_AccsList[i].length > 12) {
stCode = USR_AccsList[i].substring( 9, 11);
} else {
stCode = "0"; //Case Error
}
if (stCode == NeedAcntno[j]) {
SelectedAcntno[k] = USR_AccsList[i];
if (k == "0") {
//나중에 확인 필요함.. 고른 것들 중에 첫번째 것을 세션에 넣기..????
save_session("ACNTNO", USR_AccsList[i]);
save_flush();
}
k++;
}
}
}
}
return SelectedAcntno;
}
//계좌번호 Array를 셀렉트 박스로 변환 - pansory
//조건에 따라(0: 조회, 1: 이체가능, 2: 저축성, 4: 대출, 5: 신탁, 6: 기타)
function BT_MakeAcntList(val, selectedval,selname,condition) {
var Acct = BT_KindAcct(val,condition);
var tempAcct = Acct.split(",");
var L_ListText = "<select name=\"" + selname + "\" id=\"" + selname + "\">";
for(var i=0; i< tempAcct.length - 1; i++) {
if (tempAcct[i] == selectedval) {
L_ListText += "\t<option value=\"" + tempAcct[i] + "\" selected>" + BT_makeAcntnoDash(tempAcct[i]) + "</option>\n";
} else {
L_ListText += "\t<option value=\"" + tempAcct[i] + "\">" + BT_makeAcntnoDash(tempAcct[i]) + "</option>\n";
}
}
L_ListText += "</select>\n";
return L_ListText;
}
//계좌종류별로계좌번호가져오기
/*[1] 11 -> /s100/bc101_r2.jsp (1080) (계좌상세조회 결과와 같은 화면 사용)
[2] 19 ~ 28 -> /s100/bc102_r3.jsp (1020) (적립식예금)
[3] 31 ~ 34 -> /s400/bc419_r1.jsp (4190) (외화예금)
[4] 40 ~ 49 -> /s100/bc102_r2.jsp (1130) (대출계좌)
[5] 50 ~ 73 -> /s100/bc102_r1.jsp (1020) (기타)
[6] 그 외 -> /s100/bc1090_r1.jsp (1090) (요구불예금)*/
function BT_KindAcct(Acct,kind)
{
var tmpAcct = "";//new Array;
var flag = new Array;
flag = get_session("IGBGYEJI");
for(i=0; i< Acct.length; i++){
if(kind == ""){
tmpAcct = tmpAcct + Acct[i] + ",";
}else if(BT_StrToInt(kind) == BT_StrToInt(flag[i])) {
tmpAcct = tmpAcct + Acct[i] + ",";
}
}
return tmpAcct;
}
// "-" 삭제 - pansory
function BT_ReduceDash(val)
{
var x, ch;
var i=0;
var newVal="";
for(x=0; x <val.length ; x++){
ch=val.substring(x,x+1);
if(ch != "-") newVal += ch;
}
return newVal;
}
//오늘 날짜열 만들기 - pansory
function BT_getToday() {
var today = new Date();
var yyyy, mm, dd;
var Today;
yyyy = today.getYear();
mm = BT_make2Length(today.getMonth() + 1);
dd = BT_make2Length(today.getDate());
Today = yyyy.toString() + mm.toString() + dd.toString();
return Today;
}
// 월일을 두자리로 만들기 - pansory
function BT_make2Length(val) {
if(val < 10) {
val = "0" + val;
}
return val;
}
//공백 없애기
function BT_TrimSpace(str) {
var count = str.length;
var len = count;
var st = 0;
while ((st < len) && (str.charAt(st) <= ' ')) {
st++;
}
while ((st < len) && (str.charAt(len - 1) <= ' ')) {
len--;
}
return ((st > 0) || (len < count)) ? str.substring(st, len) : str ;
}
//공백 없애기
function BT_TrimSpace1(str) {
var count = str.length;
var len = count;
var st = 0;
while ((st < len) && (toString(str.charAt(st)) <= toString(' '))) {
st++;
}
while ((st < len) && (toString(str.charAt(len - 1)) <= toString(' '))) {
len--;
}
return ((st > 0) || (len < count)) ? str.substring(st, len) : str ;
}
//session의 PAY_ACNTNO 와 ACNTNO(val) 값 비교
function BT_ComparePayAcntno(val) {
var USR_AccsList = get_session("ACCS");
var check = "";
for (var i=0; i < USR_AccsList.length; i++) {
if (USR_AccsList[i] == val) {
check = "1";
}
}
return check;
}
// 금액 더하기 계산하기
function BT_calc(string,name)
{
var sum = 0;
BT_Del_comma(doc.form.REC_AMT);
if (eval(string) == 0 ) {
doc.form.REC_AMT.value = "";
}
else {
sum = doc.form.REC_AMT.value;
if (sum == "") {
sum = 0;
}
sum = eval(sum) + eval(string);
doc.form.REC_AMT.value = sum;
}
doc.form.REC_AMT.focus();
}
// 금액 더하기 계산하기
function BT_Card_calc(string,name)
{
var sum = 0;
BT_Del_comma(doc.form.SEV_AMT);
if (eval(string) == 0 ) {
doc.form.SEV_AMT.value = "";
}
else {
sum = doc.form.SEV_AMT.value;
if (sum == "") {
sum = 0;
}
sum = eval(sum) + eval(string);
doc.form.SEV_AMT.value = sum;
}
doc.form.SEV_AMT.focus();
}
//이체 비밀번호 체크
function BT_isTrsfPass(val)
{
// 이체비밀번호는 4자리이어야 한다.(자리수 검사는 따로 해야 한다.)
// 영문자가 1개이상 포함되어야 하며, 영문자와 숫자의 조합만 허락한다.
var len = val.length;
var i;
var alphanum = 0;
for(i=0;i<len;i++) {
if ( BT_isAlphabet(val.charAt(i)) )
alphanum = alphanum + 1;
else if ( isNaN(val.charAt(i)) )
return false;
}
if ( alphanum > 0 )
return true;
else
return false;
}
//알파벳인지 체크 - 이체비밀번호 체크와 세트
function BT_isAlphabet(val)
{
var alphaStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
if ( alphaStr.indexOf(val) < 0 )
return false;
else
return true;
}
//숫자만 있는지 체크
function BT_isNumber(val)
{
var numberStr = "0123456789";
if ( numberStr.indexOf(val) < 0 )
return false;
else
return true;
}
function BT_number(val){
if ((event.keyCode<48)||(event.keyCode>57 )){
if(event.keyCode != 8 ) // 백스페이스 제외
{
event.returnValue=false;
}
}
}
// 금액 입력시 "," 자동 입력 & 우측 정렬
function BT_Add_comma(REC_AMT)
{
if(!BT_isAllNumber(REC_AMT.value))
{
alert("금액을 숫자로 입력해 주세요.");
REC_AMT.value = "";
REC_AMT.focus();
return false;
}
var src
var i;
var factor;
var su;
var Spacesize = 0;
factor = REC_AMT.value.length % 3;
su = (REC_AMT.value.length - factor) /3;
src = REC_AMT.value.substring(0,factor);
for(i=0; i<su ; i++)
{
if ((factor==0)&&(i==0))// " XXX "인 경우
{
src += REC_AMT.value.substring(factor+(3*i), factor+3+(3*i));
}
else
{
src +=",";
src += REC_AMT.value.substring(factor+(3*i), factor+3+(3*i));
}
}
REC_AMT.value=src;
return true;
}
function BT_Add_NumberComma(val) {
var Ret_val = BT_StrToInt(val);
Ret_val = BT_Add_Displaycomma(Ret_val);
return Ret_val;
}
function BT_Add_NumberComma1(val) {
var Ret_val = BT_StrToInt(val);
var Zerodel = Ret_val;
if (Zerodel == "0")
Ret_val = "";
else
Ret_val = BT_Add_Displaycomma(Ret_val);
return Ret_val;
}
function BT_Add_Number(val) {
var Ret_val = BT_StrToInt(val);
return Ret_val;
}
function BT_Add_Displaycomma(val) {
var src;
var i;
var factor;
var su;
var Spacesize = 0;
var String_val = val.toString();
factor = String_val.length % 3;
su = (String_val.length - factor) /3;
src = String_val.substring(0,factor);
for(i=0; i<su ; i++)
{
if ((factor==0)&&(i==0))// " XXX "인 경우
{
src += String_val.substring(factor+(3*i), factor+3+(3*i));
}
else
{
if ( String_val.substring(factor+(3*i) - 1, factor+(3*i)) != "-" ) src +=",";
src += String_val.substring(factor+(3*i), factor+3+(3*i));
}
}
return src;
}
function BT_Add_Card_comma(SEV_AMT)
{
if(!BT_isAllNumber(form.SEV_AMT.value))
{
alert("금액을 숫자로 입력해 주세요.");
form.SEV_AMT.value = "";
form.SEV_AMT.focus();
return false;
}
var src
var i;
var factor;
var su;
var Spacesize = 0;
factor = SEV_AMT.value.length % 3;
su = (SEV_AMT.value.length - factor) /3;
src = SEV_AMT.value.substring(0,factor);
for(i=0; i<su ; i++)
{
if ((factor==0)&&(i==0))// " XXX "인 경우
{
src += SEV_AMT.value.substring(factor+(3*i), factor+3+(3*i));
}
else
{
src +=",";
src += SEV_AMT.value.substring(factor+(3*i), factor+3+(3*i));
}
}
SEV_AMT.value=src;
return true;
}
//전체 값이 숫자로만 되어 있는지 체크
function BT_isAllNumber(val)
{
var len = val.length;
var i=0;
for(i=0;i<len;i++) {
if ( isNaN(val.charAt(i)) ) return false;
}
return true;
}
// 컴마(",") 자동 삭제
function BT_Del_comma(REC_AMT)
{
REC_AMT.value = BT_Reduce_comma(REC_AMT.value);
return true;
}
// 컴마(",") 자동 삭제
function BT_Del_Card_comma(SEV_AMT)
{
SEV_AMT.value = BT_Reduce_comma(SEV_AMT.value);
return true;
}
function BT_Reduce_comma(account_number)
{
var x, ch;
var i=0;
var newVal="";
for(x=0; x <account_number.length ; x++){
ch=account_number.substring(x,x+1);
if(ch != ",") newVal += ch;
}
return newVal;
}
function BTCom_Replace(originalString, findText, replaceText){
var pos = 0
var preStr = ""
var postStr = ""
pos = originalString.indexOf(findText)
while (pos != -1) {
preString = originalString.substr(0,pos)
postString = originalString.substring(pos+findText.length)
originalString = preString + replaceText + postString
pos = originalString.indexOf(findText)
}
return originalString
}
function BT_getRandomNumber() { //씨크릿 카드 순차번호 생성
k=Math.round(Math.random()*30)
if(k == 0) k = k + 1
var L_Number = BT_make2Length(k);
return L_Number;
}
//9자리 고객번호에 하이픈 넣기 - pansory
function BT_makeCustnoDash (val) {
DashedCustno = val.substring(0,3) + "-" + val.substring(3,9);
return DashedCustno;
}
//주민번호에 하이픈 넣기
function BT_makeResnoDash (val) {
if (val.length == 10) { //기업의 경우
DashedResno = val.substring(0,3) + "-" + val.substring(3,5) + "-" + val.substring(5);
} else { //개인의 경우
if (val.substring(0,3) == "000"){
DashedResno = val.substring(3,6) + "-" + val.substring(6,8) + "-" + val.substring(8,13);
} else {
DashedResno = val.substring(0,6) + "-" + val.substring(6,13);
}
}
return DashedResno;
}
//카드번호에 하이픈 넣기 - pansory
function BT_makeCardnoDash (val) {
DashedAcntno = val.substring(0,4) + "-" + val.substring(4,8) + "-" + val.substring(8,12) + "-" + val.substring(12,16);
return DashedAcntno;
}
//회원번호(16자리)에 하이픈 넣기 - pansory
function BT_makeMembernoDash (val) {
DashedAcntno = val.substring(0,4) + "-" + val.substring(4,8) + "-" + val.substring(8,12) + "-" + val.substring(12,16);
return DashedAcntno;
}
//카드번호 Array를 셀렉트 박스로 변환 - pansory
function BT_MakeCardList(val, selectedval) {
var L_ListText = "<select name=\"ACNTNO\" id=\"ACNTNO\">";
for(var i=0; i< val.length; i++) {
if (val[i] == selectedval) {
L_ListText += "\t<option value=\"" + val[i] + "\" selected>" + BT_makeCardnoDash(val[i]) + "</option>\n";
} else {
L_ListText += "\t<option value=\"" + val[i] + "\">" + BT_makeCardnoDash(val[i]) + "</option>\n";
}
}
L_ListText += "</select>\n";
return L_ListText;
}
//카드번호 Array를 셀렉트 박스로 변환 - pansory
function BT_makeCardnoList(val) {
var L_ListText = "<select name=\"CARD_NO\" id=\"CARD_NO\">";
for(var i=0; i< val.length; i++) {
if (i == 0) {
L_ListText += "\t<option value=\"" + val[i] + "\" selected>" + BT_makeCardnoDash(val[i]) + "</option>\n";
} else {
L_ListText += "\t<option value=\"" + val[i] + "\">" + BT_makeCardnoDash(val[i]) + "</option>\n";
}
}
L_ListText += "</select>\n";
return L_ListText;
}
//카드번호 선택..
function BT_SelectCardno(USR_AccsList, NeedCardno) {
var no = NeedCardno.length;
var Cardno_No = USR_AccsList.length;
var SelectedCardno = new Array();
var k = 0;
if (no == 0) {
SelectedCardno = USR_AccsList;
//나중에 확인 필요함.. 고른 것들 중에 첫번째 것을 세션에 넣기..????
save_session("CARD_NO", USR_AccsList[0]);
save_flush();
} else {
for (var i=0; i < Cardno_No ; i++) {
for(var j=0 ; j < no; j++) {
if(USR_AccsList[i].length > 12) {
stCode = USR_AccsList[i].substring( 9, 11);
} else {
stCode = "0"; //Case Error
}
if (stCode == NeedAcntno[j]) {
SelectedCardno[k] = USR_AccsList[i];
if (k == "0") {
//나중에 확인 필요함.. 고른 것들 중에 첫번째 것을 세션에 넣기..????
save_session("CARD_NO", USR_AccsList[i]);
save_flush();
}
k++;
}
}
}
}
return SelectedCardno;
}
function BT_makeLoannoDash (val) {
DashedLoanno = val.substring(0,3) + "-" + val.substring(3,9) + "-" + val.substring(9,11) + "-" + val.substring(11,16)
return DashedLoanno;
}
function BT_makeDateDash (val) {
if (val == "00000000")
DashedDate = "";
else
DashedDate = val.substring(0,4) + "-" + val.substring(4,6) + "-" + val.substring(6,8);
return DashedDate;
}
function BT_makeDateDash_1 (val) {
if (val == "000000")
DashedDate_1 = "";
else
DashedDate_1 = val.substring(0,4) + "-" + val.substring(4,6);
return DashedDate_1;
}
function BT_makeDateDash_2 (val) {
if (val == "00000")
DashedDate_2 = "";
else
DashedDate_2 = val.substring(0,2) + "-" + val.substring(2);
return DashedDate_2;
}
function BT_makeDateDash_3 (val) {
if (val == "00000000")
DashedDate_3 = "";
else
DashedDate_3 = val.substring(6,8);
return DashedDate_3;
}
function BT_makeDateSlash (val) {
if (val == "00000000")
DashedDate_1 = "";
else
DashedDate_1 = val.substring(0,4) + "/" + val.substring(4,6);
return DashedDate_1;
}
function BT_makeTime (val) {
ReturnTime = val.substring(0,2) + ":" + val.substring(2,4) + ":" + val.substring(4,6);
return ReturnTime;
}
//문자열을 10진수로 변환
function BT_StrToInt(val) {
var Re_int = 0
if (val != "")
var Re_int = parseInt(val,10);
else
Re_int = 0;
return Re_int;
}
function BT_makeDecimalPoint(val) {
var ReturnVal = val.split(".");
ReturnVal = BT_Add_NumberComma(ReturnVal[0]) + "." + ReturnVal[1];
return ReturnVal;
}
//페이지 설정
function last_page(val){
var last_page = val%10;
var index = parseInt(val/10);
if (last_page > 0){
return(index+1);
}else
return(index);
}
//소수점이하 자리수 설정
function BT_makeCipherPoint(val,cipher)
{
var PreCipher = val.length - cipher;
var Preval = val.substring(0,PreCipher);
var Nextval = val.substring(PreCipher);
var Returnval = Preval + "." + Nextval;
return Returnval
}
//숫자와 영어만 허용
function BT_EngNum(obj,isUP){
//if (event.keyCode == 9 || event.keyCode == 37 || event.keyCode == 39) return;//에러 발생 수정함.
var returnValue = "";
for (var i = 0; i < obj.value.length; i++){
if ((obj.value.charAt(i) >= "0" && obj.value.charAt(i) <= "9") || (obj.value.charAt(i) >= "a" && obj.value.charAt(i) <= "z") || (obj.value.charAt(i) >= "A" && obj.value.charAt(i) <= "Z") ){
returnValue += obj.value.charAt(i);
}else{
returnValue += "";
}
}
obj.value = returnValue;
obj.focus();
}
//날짜 계산 -- jjung
function BT_getDate(Dnum, gubun, StaYer,StaMon,StaDay,EndYer,EndMon,EndDay){
var cur_year, cur_month, cur_day, cur_hour, cur_min, cur_sec, d_cur_date
var index=0;
var Mnum=0;
var theDate = btGetCurrTime(2,1);
var now = new Date();
var daynum = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
var monname = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
if(theDate == ""){
cur_year= now.getYear();
cur_month = now.getMonth() + 1;
cur_month = new String(cur_month);
cur_day = new String(now.getDate());
cur_hour = theDate.substring(8,10);
cur_min = theDate.substring(10,12);
cur_sec = theDate.substring(12);
}
else {
cur_year = theDate.substring(0,4);
cur_month = theDate.substring(4,6);
cur_day = theDate.substring(6,8);
cur_hour = theDate.substring(8,10);
cur_min = theDate.substring(10,12);
cur_sec = theDate.substring(12,14);
}
daynum[1] = cday(cur_year);
change_month = monname[BT_StrToInt(cur_month) - 1];
tmpDate = new String(change_month + cur_day + "," + cur_year + " " + cur_hour + ":" + cur_min + ":" + cur_sec );
d_cur_date = new Date(tmpDate);
if(gubun == "mon"){
tmpMonth = BT_StrToInt(cur_month) + Dnum;
if (tmpMonth == 0)
{
tmpMonth = "12";
change_month = monname[BT_StrToInt(tmpMonth) - 1];
tmpDate = new String(change_month + cur_day + "," + (cur_year - 1) + " " + cur_hour + ":" + cur_min + ":" + cur_sec );
}
else if (tmpMonth == -1)
{
tmpMonth = "11";
change_month = monname[BT_StrToInt(tmpMonth) - 1];
tmpDate = new String(change_month + cur_day + "," + (cur_year - 1) + " " + cur_hour + ":" + cur_min + ":" + cur_sec );
}
else {
change_month = monname[BT_StrToInt(tmpMonth) - 1];
tmpDate = new String(change_month + cur_day + "," + cur_year + " " + cur_hour + ":" + cur_min + ":" + cur_sec );
}
before_date = new Date(tmpDate);
}else{
var before_date = new Date(Date.parse(d_cur_date) + BT_StrToInt(Dnum)*1000*60*60*24);
}
if(theDate.length==0) {
var before_year = new String(before_date.getYear());
var before_month = new String(before_date.getMonth() + 1);
}else {
var before_year = new String(before_date.getYear());
var before_month = new String(before_date.getMonth() + 1);
}
if(before_month.length==1){
before_month = '0'+before_month;
}
var before_day = new String(before_date.getDate());
if(before_day.length==1){
before_day = '0'+before_day;
}
if(StaYer != "") eval("doc."+StaYer+".value=before_year");
if(StaMon != "") eval("doc."+StaMon+".value=before_month");
if(StaDay != "") eval("doc."+StaDay+".value=before_day");
if(EndYer != "") eval("doc."+EndYer+".value=before_year");
if(EndMon != "") eval("doc."+EndMon+".value=before_month");
if(EndDay != "") eval("doc."+EndDay+".value=before_day");
if(StaYer == "" && StaMon == "" && StaDay == "" && EndYer == "" && EndMon == "" && EndDay == "") return before_year + before_month + before_day;
}
//val : 전체 값, point : 소수점 앞에 자리수
function BT_toMoneyF(val,point,gubun){
var foreVal = 0;
var downVale = 0;
if (BT_TrimSpace(val) == ""){
return foreVal;
} else {
if(point == "" || point == "0") {
foreVal = val;
downVal = "";
} else {
if(gubun == "1"){
foreVal = val.substring(0,point);
} else{
foreVal = BT_Add_NumberComma(val.substring(0,point));
}
downVal = val.substring(point);
}
return foreVal + "." + downVal;
}
}
function BT_SetServiceCode(code){
save_session("SERVICE_CODE",code);
save_flush();
}
function BT_Setreturn_url(val){
save_session("RETURN_URL",val);
save_flush();
}
//2년 윤년처리
function cday(year)
{
//2월달일때 윤년 처리
if ((year % 4) == 0) { //윤년
if ((year % 100) == 0) { //평년
if ((year % 400) == 0) { //윤년
daynum = 29;
}
else {//평년
daynum = 28;
}
}
else { //윤년
daynum = 29;
}
}
else {//평년
daynum = 28;
}
return daynum;
}
/**
* 입력한 숫자 및 영문(조합도 상관없음)이 비밀번호로 사용 가능한지 다음과 같은 제한사항을
* 검사하는 메소드
* 1. 숫자의 경우 하나의 숫자 조합
* 2. 숫자의 경우 오름차순 및 내림차순
* 3. 영문의 경우 하나의 영문 조합(대소문자는 다른 문자로 인식함)
* 4. 영문의 경우 오름차순 및 내림차순
* @obj 입력폼의 object
* @return true : 비밀번호로 사용가능
* @return false : 비밀번호로 사용할 수 없음. 각 상황에 맞는 메시지가 내장되어 있음.
*/
function pwCheck(obj)
{
var val = obj.value;
var flag = false;
for(i=0;i<val.length;i++)
{
if(!BT_isNumber(val.charAt(i)))//숫자 체크
{
flag = true;
break;
}
}
if(flag)//숫자와 영문 혼합 or 영문 조합으로 예상됨
{
for(i=0;i<val.length;i++)
{
if(!BT_isAlphabet(val.charAt(i)))//영문 체크
{
flag = false;
break;
}
}
if(flag)//*** 영문으로만 조합 연번 체크 요구됨 ***
{
if(check_alpha_all_dup(val))//*** 같은 영문자만의 조합 검사 ***
{
alert("입력하신 비밀번호가 모두 같은 영문입니다.");
return false;
}
else//*** 오름 차순 및 내림 차순 검사 ***
{
if(check_alpha_asc(val))//*** 오름차순 검사 ***
{
alert("입력하신 비밀번호가 영문 오름차순입니다.");
return false;
}
else//*** 내림차순 검사 ***
{
if(check_alpha_desc(val))
{
alert("입력하신 비밀번호가 영문 내림차순입니다.");
return false;
}
else//*** 비밀번호로 사용가능 ***
{
return true;
}
}
}
}
else//*** 영문 및 숫자 조합 - 비밀번호로 상용가능 ***
{
return true;
}
}
else//*** 숫자로만 조합되었으므로 연번 체크 요구됨 ****
{
if(check_digit_all_dup(val))//*** 같은 숫자만의 조합 검사 ***
{
alert("입력하신 비밀번호가 모두 같은 숫자입니다.");
return false;
}
else//*** 오름 차순 및 내림 차순 검사 ***
{
if(check_digit_asc(val))//*** 오름차순 검사 ***
{
alert("입력하신 비밀번호가 오름차순입니다.");
return false;
}
else//*** 내림차순 검사 ***
{
if(check_digit_desc(val))
{
alert("입력하신 비밀번호가 내림차순입니다.");
return false;
}
else//*** 비밀번호로 사용가능 ***
{
return true;
}
}
}
}
}
/**
* 숫자로만 구성된 문자열이 내림차순의 숫자들인지 확인
* @return true : 내림차순이다.
* @return false : 내림차순이 아니다.
*/
function check_digit_desc(val)
{
var init_cnt = 0;
var flag = true;
for(i=0;i<numberArray.length;i++)
{
if(val.charAt(0) == numberArray[i])
{
init_cnt = i;
break;
}
}
var init_cnt_tmp = init_cnt;
for(i=0;i<val.length;i++)
{
if(val.charAt(i) == numberArray[init_cnt_tmp])
{
}
else
{
flag = false;
break;
}
init_cnt_tmp -= 1;
if(init_cnt_tmp == -1)
{
init_cnt_tmp = numberArray.length - 1;
}
}
return flag;
}
/**
* 영문으로만 구성된 문자열이 내림차순인지 확인
* @return true : 내림차순이다.
* @return false : 내림차순이 아니다.
*/
function check_alpha_desc(val)
{
var init_cnt = 0;
var flag = true;
for(i=0;i<alphaArray.length;i++)
{
if(val.charAt(0) == alphaArray[i])
{
init_cnt = i;
break;
}
}
var init_cnt_tmp = init_cnt;
for(i=0;i<val.length;i++)
{
if(val.charAt(i) == alphaArray[init_cnt_tmp])
{
}
else
{
flag = false;
break;
}
init_cnt_tmp -= 1;
if(init_cnt_tmp == -1)
{
init_cnt_tmp = alphaArray.length - 1;
}
}
return flag;
}
/**
* 숫자로만 구성된 문자열이 오름차순의 숫자들인지 확인
* @return true : 오름차순이다.
* @return false : 오름차순이 아니다.
*/
function check_digit_asc(val)
{
var init_cnt = 0;
var flag = true;
for(i=0;i<numberArray.length;i++)
{
if(val.charAt(0) == numberArray[i])
{
init_cnt = i;
break;
}
}
var init_cnt_tmp = init_cnt;
for(i=0;i<val.length;i++)
{
if(val.charAt(i) == numberArray[init_cnt_tmp])
{
}
else
{
flag = false;
break;
}
init_cnt_tmp += 1;
if(init_cnt_tmp == numberArray.length)
{
init_cnt_tmp = 0;
}
}
return flag;
}
/**
* 영문으로만 구성된 문자열이 오름차순 인지 확인
* @return true : 오름차순이다.
* @return false : 오름차순이 아니다.
*/
function check_alpha_asc(val)
{
var init_cnt = 0;
var flag = true;
for(i=0;i<alphaArray.length;i++)
{
if(val.charAt(0) == alphaArray[i])
{
init_cnt = i;
break;
}
}
var init_cnt_tmp = init_cnt;
for(i=0;i<val.length;i++)
{
if(val.charAt(i) == alphaArray[init_cnt_tmp])
{
}
else
{
flag = false;
break;
}
init_cnt_tmp += 1;
if(init_cnt_tmp == alphaArray.length)
{
init_cnt_tmp = 0;
}
}
return flag;
}
/**
* 숫자로만 구성된 문자열이 같은 숫자로 조합되었는지 확인
* @return true : 동일한 값으로 조합. 비밀번호로 사용하면 안됨.
* @return false : 다른 숫자가 적어도 하나 존재. 비밀번호로 사용해도 괜찮음.
*/
function check_digit_all_dup(val)
{
var flag = true;
for(i=0;i<numberArray.length;i++)
{
flag = true;
for(j=0;j<val.length;j++)
{
if(val.charAt(j) == numberArray[i])
{
}
else
{
flag = false;
break;
}
}
if(flag)
{
break;
}
else
{
continue;
}
}
return flag;
}
/**
* 영문으로만 구성된 문자열이 같은 영문으로 조합되었는지 확인
* @return true : 동일한 영문으로 조합. 비밀번호로 사용하면 안됨.
* @return false : 다른 영문이 적어도 하나 존재. 비밀번호로 사용해도 괜찮음.
*/
function check_alpha_all_dup(val)
{
var flag = true;
for(i=0;i<alphaArray.length;i++)
{
flag = true;
for(j=0;j<val.length;j++)
{
if(val.charAt(j) == alphaArray[i])
{
}
else
{
flag = false;
break;
}
}
if(flag)
{
break;
}
else
{
continue;
}
}
return flag;
}
다중 접속 서버 프로그래밍 (0) | 2007.10.23 |
---|---|
Dialog Window 띄우면서, 작업표시줄에서 감추기 (0) | 2007.10.23 |
중복 실행 방지. (0) | 2007.10.23 |
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
000 싸이트 자바스크립트 유틸 메소드 모음 (0) | 2008.03.04 |
---|---|
Dialog Window 띄우면서, 작업표시줄에서 감추기 (0) | 2007.10.23 |
중복 실행 방지. (0) | 2007.10.23 |
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
BOOLCDialog::OnInitDialog()
{
CDialog::OnInitDialog();
ModifyStyleEx( WS_EX_APPWINDOW,WS_EX_TOOLWINDOW,0 );
returnTRUE;
}
000 싸이트 자바스크립트 유틸 메소드 모음 (0) | 2008.03.04 |
---|---|
다중 접속 서버 프로그래밍 (0) | 2007.10.23 |
중복 실행 방지. (0) | 2007.10.23 |
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
BOOL CWinApp::InitInstance()
{
// Mutex 생성
HANDLE hMutexOneInstance = ::CreateMutex(NULL, TRUE, _T("Unique Name of Mutex"));
BOOL bFound = FALSE;
// 만약 이미 만들어져 있다면 Instance가 이미 존재함
if (::GetLastError() == ERROR_ALREADY_EXISTS)
bFound = TRUE;
if ( hMutexOneInstance )
::ReleaseMutex(hMutexOneInstance);
// 이미 하나의 Instance가 존재하면 프로그램 종료
if(bFound) {
AfxMessageBox("이미 실행중입니다");
return FALSE;
}
........
}
다중 접속 서버 프로그래밍 (0) | 2007.10.23 |
---|---|
Dialog Window 띄우면서, 작업표시줄에서 감추기 (0) | 2007.10.23 |
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
IOCP (IOCompletionPort) 분석 (0) | 2007.09.21 |
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴..
_____________________________________________________________________
RLE / RLE+ / FAX / FAX+ / Lempel-Zip 방식압축기법
---------------------------------------------------------------------
!!***********************************************************!!
< RLE (Run Length Encoding) 방식 >
가장 쉽지만 모든것이 그렇듯 가장 압출률이 저조한 방법입니다.
화일을 16 진수로 나타낸 코드를 읽어서 다음과 같은 예가 있다면
<데이터>
00 00 1C 1C 1C F3 F3 F3 F3 F3 D8 11 11 11 11 11
위의 자료는 16byte의 자료입니다.
RLE 방식으로 압축을 하면 다음과 같이 나타낼수 있습니다.
<RLE 압축>
00 02 1C 03 F3 05 D8 01 11 05
대상코드와 그 코드의 갯수를 나란히 적은 것임을 알수 있습니다.
이방법은 일반적으로 독립적으로 쓰이기보다는 여러가지 기법과 혼용되어
쓰이는 방법입니다. 또한 연속된 자료가 자주 나타나는 그림화일등에서
압축률을 높일수 있습니다. 다른 일반 자료는 오히려 압축한것이
더큰 역효과를 가져옵니다. 이유는 자료코드 하나와 갯수코드 하나씩해서
최악의 경우는(연속된자료가 전혀없는경우) 꼭 원본보다 두배의 자료가
되기 때문이죠.
-----------------------------------------------------------------------
< RLE 보완형 >
RLE의 단점은 연속되지 않은 자료의 압축시에 오히려 그 압축화일의 용량
이 더욱 커진다는 것이었습니다. 그러나 일부 그림자료등을 제외하면
대부분의 자료들은 같은 코드의 반복은 그리 눈에 띄지 않습니다...
여기서 보일 방법은 RLE의 갯수를 세는 부분을 달리 하는 것입니다.
기존에 01 02 03 ...처럼 숫자를 썼던 것 대신 C0 C1 C2 ...등으로 바꾸어
쓰는 것입니다. 이 방법은 글쎄요. RLE 방법과 그다지 별차이가 없어
보이지만 코딩시에 새로운 규칙을 첨가함으로써 변화를 도모합니다.
그 규칙이라 함은 갯수를 설정하면 코드의 갯수가 바뀌지 않는이상 다시
설정하지 않는다는 것입니다. (이해가 가실까.....그렇다면 예제를..)
<데이터>
F9 03 5D E3 21 00 EE 45 33 76 DE 3D 2F F4 5C B2
위와 같은 16byte 데이터의 RLE 보완형으로 압축하면 다음과 같습니다.
<RLE 보완압축>
C0 F9 03 5D E3 21 00 EE 45 33 76 DE 3D 2F F4 5C B2
17byte 로 원본보다 1byte나 손해를 보았습니다. 그러나 RLE 보다는
훨씬 좋은 방법임을 알수 있습니다.
위의 예는 전혀 연속되는 자료가 없었다는 겁니다. 그러나 다음의 예와
같이 연속되는 자료가 존재하면 이야기는 달라집니다.
<데이터>
03 03 03 03 5F E3 21 00 EE 45 33 76 DE 3D 2F F4 5C
<RLE 보완압축>
C3 03 C0 5F E3 21 00 EE 45 33 76 DE 3D 2F F4 5C
자 1byte의 압축 효과를 가져왔습니다.
하지만 혹자는 여기서 이런 의문을 갖을수도 있겠습니다. 만일 데이터상에
C0...CF 의 자료가 존재하면 어떻게 하는가....만일 다음과 같은 자료가
있다면 예 치고는 너무 속보이는 예제입니다만....헐~
<데이터>
C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
<RLE 보완압축?>
C0 C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
위의 압축된것이 맞을까요? 흐흐......절대 아니죠....위의 것을 다시 풀어
쓴다고 생각하면 전혀 다른 해석이 생기게 됩니다.
지금까지 쓴 RLE 보완형의 규칙을 보면 갯수는 C0...CF로적되 첨음에는 갯수
다음에 코드순이었습니다....따라서 압축된것을 거기에 준하여 해석하면
C0 C0 는 C0가 1개로 해석되지만 다음부터는 문제가 생기죠...C1 C2 에서는
엉뚱하게도 C2 라는 코드가 2개인것으로 해석된다는 맹점입니다.
따라서 이런경우를 위한 한가지의 규칙이 더 필요하게 됩니다.
* 만일 데이커상에 C0...CF 의 자료가 있으경우 그부분에 대해서 특별히
기존의 RLE 방법으로 압축한다. 갯수를 적을때는 역
C0...CF 코드를 이용
한다.
이해를 돕기위한 예제는 다음과 같습니다.
<데이터>
34 DE C3 C3 C3 F4 F4 F4 DE C0 36 8D B1 A0 00 01
위와 같은 16byte의 자료를 압축합니다. 압축시 주의할사항으로는 C# 코드발견
시 RLE로 압축하고( 갯수 + 코드 쌍형태) 다시 RLE 보완형을 시작하는 것입니다
즉, 앞에 압축한것과 별도의 압축을 한다고 생각하고 다시 C# 형태의 갯수를 쓰
는것부터 하는거죠....압축된것을 보면 다음과 같습니다.(~~ 친부분 주의할곳)
<RLE 보완압축>
C0 34 DE C2 C3 C2 F4 C0 DE C0 C0 C0 36 8D B1 A0 00 01
~~ ~~
처음부터 차근차근 살펴보겠습니다.
먼저 C0의 의미는 34 DE 라는 데이터가 한개씩 있다는 뜻입니다.
C2 C3 는 C3 데이터가 3개 있다는 이야기입니다.
C2 F4 는 F4 데이터가 3개있다는 의미인데...문제는 이전에 쓰인 C2 의 의미가
뒤에나오는 C3 C2 F4 까지 모두 3개씩이 아닌가 하는 해석의 오류를 나을수 있
다는 것입니다. 그러나 압축에서 규칙을 정한것처럼 C0...CF 자료가 둘이상 존재
할때는 이것이 특수한 규칙에 의해서 압축된 RLE 방식이라는 것을 잊어서는 안
됩니다...따라서 압축을 풀때에도 C0...CF 코드가 나오면 두개씩 짝을지어 RLE
방식으로 해석하고 풀어야 한다는 이야기입니다. 둘씩 짝을 지어 해석한후 다시
나오는 C2 는 다음에 나오는 자료가 C# 형태가 아니기 때문에 보완형으로 압축된
것임을 알수 있습니다...그래서 F4가 3개 연속이라는 뜻이죠...다음에 연속되는
C0의 해석에서는 C#형태가 연속되므로 이것은 RLE 방식의 압축입니다. 따라서 첫
C0는 갯수 다음은 코드...해서 C0 가 하나있다는 의미이구요...(역시 2개씩 짝을
짓죠...RLE 방식은 두개씩의 짝을 만들어 냅니다...) 다음에 나오는 C0는 38 8D
B1 A0 00 01 이라는 코드가 모두 하나씩 존재한다는 의미입니다.
역시 다음코드인 DE 가 1개라는 의미죠...조금은 복잡한듯 싶지만 그 규칙을 완
전히 이해한다면 별루 어려울것은 없습니다.
실전을 위해 압축된 자료의 원본을 만들어보는 연습을 하겠습니다.
<RLE 보완압축 자료>
C0 34 DE C2 C3 C2 F4 C0 DE C0 C0 C0 36 8D B1 A0 00 01
C0 34 DE 가지는 34 DE 가 하나씩 있다는 의미입니다. 다음에 나온 C2 C3 C2...
C#의 형태가 연속해있으므로 두개씩 묶어서 생각합니다. C2 C3 는 RLE 압축이
니까...C3 라는 데이터가 3개라는 의미겠죠...다음...C2는 다시 RLE 보완형의
첫부분이니까...갯수를 나타내고 다음에 나오는 F4라는 데이터의 갯수죠...
따라서 F4 3개.....C0 DE 는 DE 가 1개 다음에 역시 연속되는 C0 중에...두개를
취해서 C0가 1개있다는 의미이고....세번째 C0는 RLE 보완형 첫번째인 갯수 따라
서 36 8D B1 A0 00 01 이 하나씩... 이상을 종합하면...
<복원데이터>
34 DE C3 C3 C3 F4 F4 F4 DE C0 36 8D B1 A0 00 01
이 됩니다.....원래의 모습을 찾았죠? 이해가 가십니까?
규칙에 충실하면 어려울것이 없습니다. RLE 방식은 가장 기초적인 방식으로 다른
압축 기법을 공부하는데에 기본이 된다구나 할까요....
---------------------------------------------------------------------------
<FAX 압축>
이 압축 방법은 현재 많이 쓰이는 사무기기인 팩시밀리에서 사용하는 압축 방식입
니다. 압축률또한 위에서 언급된 RLE 계열의 방식보다 좋으며 RLE방식을 제외한
기타다른 압축방식보다 구현하기가 쉬워서 맣이 사용되고 있습니다.
간단히 설명하자면 이전까지 사용하던 16진 코드를 2진코드로 바꾸어 압축하는
방식입니다. 다른 말로 비트맵이라는 표현을 쓰기도 합니다. 마우스의 커서등을
구현할때 모눈종이에 그리던것 생각하시면 빠르겠네요..
자 우선 아래와 같은 32byte의 데이터를 읽어들입니다.
<데이터>
00 00 0F F0 1F F8 1F F8 1F F8 0F F0 00 00 00 00
0F F0 11 88 11 88 11 88 11 88 11 88 0F F0 00 00
위의 데이터를 RLE 보완압축 방식으로 압축하면 다음과 같겠죠 (쩝 압축률
0%?)
<RLE 보완압축>
C1 00 C0 0F F0 1F F8 1F F8 1F F8 0F F0 C3 00 C0
0F F0 11 88 11 88 11 88 11 88 11 88 0F F0 C1 00
비교를 위해서 RLE 방법을 쓰면 다음과 같습니다. (흐...팽창률 170%?)
<RLE 압축>
00 02 0F 01 F0 01 1F 01 F8 01 1F 01 F8 01 1F 01
F8 01 0F 01 F0 01 00 04 0F 01 F0 01 11 01 88 01
11 01 88 01 11 01 88 01 11 01 88 01 11 01 88 01
0F 01 F0 01 00 02
비교상으로도 RLE 보완형이 월등히 좋다는 것을 알수 있습니다....그럼 FAX 압축
을 위해서 우선 비트맵으로 구성해보도록 하겠습니다.
위의 데이터를 16 by 16 비트맵으로 나타내면 다음과 같습니다.(정사각형모양)
<비트맵> l <16진>
l
0000 0000 0000 0000 l 00 00
0000 1111 1111 0000 l 0F F0
0001 1111 1111 1000 l 1F F8
0001 1111 1111 1000 l 1F F8
0001 1111 1111 1000 l 1F F8
0000 1111 1111 0000 l 0F F0
0000 0000 0000 0000 l 00 00
0000 0000 0000 0000 l 00 00
0000 1111 1111 0000 l 0F F0
0001 0001 1000 1000 l 11 88
0001 0001 1000 1000 l 11 88
0001 0001 1000 1000 l 11 88
0001 0001 1000 1000 l 11 88
0001 0001 1000 1000 l 11 88
0000 1111 1111 0000 l 0F F0
0000 0000 0000 0000 l 00 00
먼저 일단계로 위의 비트맵에서 0이 많아지는 방향으로 데이터를 규칙있게
변형시키는 것입니다. 먼저 기존의 0은 그대로 두고 0에서 1로 변화되는 부분과
0 에서 1로 변화되는 부분에서마 1을 쓰는 방법이 있습니다.
변형되 형태는 다음과 같은 모습이 될것입니다.
<변형된 비트맵>
0000 0000 0000 0000
0000 1000 0000 1000
0001 0000 0000 0100
0001 0000 0000 0100
0001 0000 0000 0100
0000 1000 0000 1000
0000 0000 0000 0000
0000 0000 0000 0000
0000 1000 0000 1000
0001 1001 0100 1100
0001 1001 0100 1100
0001 1001 0100 1100
0001 1001 0100 1100
0001 1001 0100 1100
0000 1000 1000 1000
0000 0000 0000 0000
위의 데이터는 예시를 위해 조작된 것이기 때문에 확실이 0숫자가 많이 포함
되어있습니다. 그러나 일반적인 데이터는 이보다는 좋지 않은 결과가 나올경우가
더 많다는 것을 알아두셔야 합니다. 또한 FAX 압축을 풀기위한 규칙으로 가장
첫 비트가 1이면 그자리는 1로 표시해야합니다. 그렇지 않으면 나중에 압축
을 풀어나갈때 곤란한 경우가 생기게 됩니다. 우선을 그렇게 알아두시면 됩니다.
여기까지 끝이 나면 다음 단계로 넘어갑니다. 이번에는 데이터를 회전시킵니다.
프로그램상으로 구현할때에는 위에서 아래로 데이터를 읽어서 왼쪽에서 오른쪽
으로 써나가면 됩니다.(이유는 0을 많이 만들기 위함입니다)
재변형된 데이터의 형태는 아래와 같습니다.
재변형 비트맵 l 16진 l 헤더비트
---------------------------------------------
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0000 0000 l 00 00 l 00
0011 1000 l 0111 1100 l 38 7C l 11
0100 0100 l 1111 1110 l 44 FE l 11
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0111 1100 l 00 7C l 01
---------------------------------------------
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0111 1100 l 00 7C l 01
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0000 0000 l 00 00 l 00
0100 0100 l 1111 1110 l 44 FE l 11
0011 1000 l 0111 1100 l 38 7C l 11
0000 0000 l 0000 0000 l 00 00 l 00
0000 0000 l 0000 0000 l 00 00 l 00
데이터를 입력하기위해서 우선 헤더비트를 쓴후 데이터를 입력하는 방식으로
압축을 해나가는 것입니다. 여기서 헤더 비트란 것은 재변형된 비트맵상에서
1byte를 취하여 그값이 0이면 0 그외의 숫자이면 1을 부여하여 일열로 나열
한 일종의 암호데이터라고 할까요.(위에 세로줄로 나눈것은 byte 단위로 알아
볼수 있도록 한것입니다) 위에 헤더비트를 적은 것을 보면 쉽게 그 의미를
알수 있을 것입니다. 따라서 위의 데이터의 헤더비트는 다음과 같습니다.
<헤더비트>
0000 0011 1100 0001 0001 0000 1111 0000 : 03 C1 10 F0
압축된 데이터는 이 헤더비트를 가장 먼저 적고 다음에 자료를 입력하는데
단, 자료가 00일때는 적지 않습니다. 완성된 압축 데이터는 다음과 같습니다.
<FAX 압축>
03 C1 10 F0 38 7C 44 FE 7C 44 FE 38 7C
~~~~~~~~~~~
헤더비트
처음에 주어진 32 byte 데이터가 13 byte로 압축되었습니다. (압축률 약60%)
사실 위의 예제는 16 by 16 비트맵을 사용했지만 8 by 8 비트맵을 4번 압축한
것과도 같습니다...따라서 위의 예제를 8 by 8 비트맵으로 바꾸어 네번 같은
계산을 반복해도 하나의 방법으로 생각할수 있습니다.
문제는 얼마나 많은 데이터를 이용하는가와 계산상의 속도문제가 상호작용하
게 되기 때문에 적정선에서 나누는것이 좋습니다. 보통 8 by 8 비트맵이나
16 by 16 비트맵을 사용합니다.
이 FAX 압축을 푸는 방법은 지금까지 해왔던 일련의 작업을 꺼꾸로 수행하는
것입니다. 먼저 헤드를 읽어서...우선은 이 압축이 8 by 8 로 압축되었는지
16 by 16 으로 압축되었는지 알아야 하는것은 당연한것이겠죠...압축한 방법
으로 풀어야 풀리겠죠....어쨌든.. 헤드를 읽어서 데이터중에 00의위치와 0이
아닌 데이터의위치를 파악한후 자료를 순서대로 읽어 해당위치에 넣고
(여기까지는 재변형 비트맵) 회전된 것을 복구하기 위해서 데이터를 왼쪽에서
오른쪽으로 읽어서 위에서 아래로 써 원래의 변형된 비트맵을 만듭니다.
이제는 1과 0의 규칙에 따라서 원래의 자료로 복구를 하는 것입니다.
여기서 앞에서 언급했던 첫비트의 1일때 문제는 이렇습니다. 만일 첫비트가
11100 등으로 시작되었는데도....00010 등으로 쓰였을경우 복구할때...규칙에
의해서 00010 은....00011 로 복구가 되죠....원하는 값이 아닙니다....따라서
위의 경우...즉, 11100 으로 시작하는 데이터의 올바른 변형법은 10010 입니다.
그래야 규칙에 의해서 11100으로 바뀔수가 있기 때문입니다.
이점만 유의 한다면 FAX 압축도 별 어려운 것이 없을것이라고 생각합니다.
참고적으로 말씀드리자면 FAX 방법에 있어서 어떤때에는 오히려 헤더부분때문에
특히 16 by 16 비트맵 방식에서는 무려 4 byte 의 헤더가 이용되면서...압축률
에 있어서 손해를 보게 되는 경우가 많습니다...그래서 보통은 8 by 8 비트맵
의 형태를 사용하는데 그대신 많은 데이터를 한번에 읽어서 속도를 향상시키
기도 합니다. 하지만 16 by 16 의 장점은 8 by 8 보다는 데이터의 압축률에 있
어서 앞선다는 것입니다....그래서 나온것이 16 by 16 비트맵 방식에서...
헤더의 크기를 2 byte 로 줄일수 있는 방법이 있다고 합니다.
음...FAX 압축이 비록 팩시밀리에서 사용되는 방법이긴하지만 자료에 따라서는
예를 들면 실행화일을 압축하는데 있어서는 결코 쓸모있는 것은 못됩니다.
대부분의 경우....10% 내외의 압축률이나..마이너스 압축률이 나오기 쉽상
이라는 점을 알아두시기 바랍니다.
---------------------------------------------------------------------------
<FAX 보완압축>
보완형이란 다름아닌 위에서 잠시 언급한 헤더를 2byte 로 줄이는 방법입니다.
구현 원리는 FAX 와 같지만 마지막에 헤더를 쓰고 자료를 적는 부분에서만
차이를 보이는 것입니다. FAX 압축의 예제에서 보인것은 헤더를 만들때 8 bit
를 기준으로 해서 03 C1 10 F0 라는 헤더를 얻어냈었습니다... 그러나 여기서
는 16 bit 를 기준으로 해서 새로운 헤더를 만들어낼수 있습니다.
즉, 위의 헤더비트의 예에서
<8bit 헤더비트의 예>
00 00 00 11 11 00 00 01 00 01 00 00 11 11 00 00 : 03 C1 10 F0
였던 헤더비트가 16 bit를 기준으로 하면
<16bit 헤더비트로의 변형>
0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 : 19 4C
으로 변화하게 됩니다. 즉, 헤더가 8bit 일때의 절반으로 감소함으로써 데이터의
압축률이 다소 낮아지더라도 충분한 보상을 갖어오게 된다는 것입니다.
---------------------------------------------------------------------------
<Lempel-Zip 방식>
이 방식은 누구나 한번쯤은 생각했보았을만한 방법이면서 근래 많이 이용되는
압축프로그램의 원형이라고 말할수 있는 방식입니다. 크랙용 프로그램인 크랙잭을
보면 크랙을 위한 사전을 가지고 있는것을 볼수 있죠. 이와 비슷한 방식으로
같다고 볼수는 없지만 그런 접근으로 압축을 하는 것이 이방법의 개요입니다.
압축방법이라기 보다는 암호책을 대조하는 식으로 생각하면 이해가 빠를까요?
최고의 효율을 가지고 있는 방식으로 현재 압축효율이 좋은 압축 프로그램들은
모두 이 방식을 사용하거나 그 변형을 이용합니다. 이 방식의 실현은 상당히 어렵지
만 간단하게 생각하면 사전과 같이 자주 사용되는 것을 일종의 테이블로 만들어
압축하는 것입니다. 코드 필드와 서픽스로 나뉘어서 구성되는 테이블의 내용은
다중 패스를 거쳐야 하는 복잡한 알고리즘을 가지고 있지만 여기서 간단히 개념만을
파악한다면 다음과 같이 볼수 있습니다.
INDEX ENCODE 사전
┌─────┐
.. │ ..... │
... │ ..... │
... │ .... │
├─────┤
478 │ IS │
RAW DATA ├─────┤
... │ .... │
"THIS IS HOT -> ├─────┤-> INDEX OUTPUT
STUFF" 759 │ HOT │ 1295 478 759 3751
├─────┤ (12954787593751)
... │ ... │
├─────┤
1295 │ THIS │
├─────┤
.... │ .... │
├─────┤
3751 │ STUFF
├─────┤
.... │ .... │
└─────┘
INDEX ENCODE 사전이라는 것은 압축 프로그램이 규칙에의해 보유하고 있는
일종의 사전이라고 보시면 됩니다. 각각에 번호나 약속된 기호들로 구성되어
그 인덱스 하나가 하나의 단어내지는 기호를 나타내게 되는 것입니다.
압축을 하기위해서는 해당하는 INDEX를 알아야만 가능하겠죠... 일일이 이런
사전을 개인이 구축한다는 것은 그리 쉬운 일은 아닐것입니다. 많은 노력과
시간이 들겠죠.. 파싱이라는 기법을 이용해서 인덱스를 자체 생산하는 방법
이 있긴 합니다. 간단한 텍스트 압축기는 충분히 만들수 있을것이라고
생각이 듭니다.
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Dialog Window 띄우면서, 작업표시줄에서 감추기 (0) | 2007.10.23 |
---|---|
중복 실행 방지. (0) | 2007.10.23 |
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
IOCP (IOCompletionPort) 분석 (0) | 2007.09.21 |
프로그래밍 :: 오라클 강좌 (0) | 2007.08.17 |
class rrr
{
public:
void setR(int r) { _rr = r;}
int getR() {return _rr;}
int _rr;
};
class mmm
{
public:
mmm(rrr * rr) : _rr(rr) {}
void setR(rrr * r) { _rr = r;}
rrr * getR() {return _rr;}
rrr * _rr;
};
class sss
{
public:
sss() : _m(&_r) { _m.setR(&_r); }
rrr & getR() {return _r;}
mmm * getM() {return &_m;}
rrr _r;
mmm _m;
};
int main(int argc, char* argv[])
{
rrr r1;
sss s2;
sss * s1 = &s2;
s1->getR().setR(10);
cout << s1->getR().getR() << endl;
cout << s1->getM()->getR()->getR() << endl;
s1->getR().setR(15);
cout << s1->getR().getR() << endl;
cout << s1->getM()->getR()->getR() << endl;
s1->getM()->getR()->setR(20);
cout << s1->getR().getR() << endl;
cout << s1->getM()->getR()->getR() << endl;
심하게 깔끔해 보이진 않지만... 테스트겸 간략하게 짠 코드니까..ㅋㅋ
결과는뭐 당연하게 잘되지만...
왜 실제 코드에선 버그가 있는거지..
어디서 물고 있는게냐?
중복 실행 방지. (0) | 2007.10.23 |
---|---|
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
IOCP (IOCompletionPort) 분석 (0) | 2007.09.21 |
프로그래밍 :: 오라클 강좌 (0) | 2007.08.17 |
Oracle 10g의 Recycle Bin의 기능에 대해서... (0) | 2007.08.17 |
오늘은 회사 창립기념일이어서 기분이 좋습니다.^^ 예전에 IOCP에 대해서 공부할려고 작성했던 문서를 찾았습니다. 한번 읽어보세요. 예전에 이 자료 만들때는 IOCP자료 찾기가 많이 힘들었는데 요즈음에는 구글에서 찾으면 좋은 자료가 너무 많아서 찾기가 힘들죠^^;;;
----------------------------------------------------------------------------------------
1. 목적
Winsock2 IOCP를 분석한 것입니다. 이 문서는 크게 두 가지를 설명 하고 있습니다. 전자는 일반적인 IOCP에 대해서 설명합니다. 후자는 IOCP란 무엇이고 장단점은 무엇인지 입니다.
2.IOCP란?
위에서 보는 것처럼IOCP의 기본적은 구성은두개의 쓰레드로 만들어 진다. 왼편에 있는 루프는 보통 main() 함수에서 있는 루프고 오른쪽에 있는 루프는 main함수가 루프를 들어가기 전에 생성해야 하는 쓰레드로 보통 Worker쓰레드라고 한다. 권장하는 Worker쓰레드의 수는 하나의 CPU당 두개로(Send/Recv) 되어 있다. 또한 2번에서 3번으로의 데이터 전송은 전역변수를 이용하거나 Worker쓰레드를 생성할 때, 포인터를 전송하여 두 루프가 변수를 공유하는 방법이다. 이에 대해서는 달리 자세히 설명하지는 않겠다.
(1) Wait for client to connect
이 과정에 이전에 이미IOCP 핸들과 소켓 초기화, 클라이언트의 접속을 대기하는 소켓, 접속한 클라이언트들의 정보를 가지는 배열( 물론, 자료구조는 자신의 선택이다. )을 생성해 두어야 한다.여기는 클라이언트의 접속을 대기하는 소켓에 Accept()를 호출하여 클라이언트가 접속하기를 기다리는 과정이다.
(2) Open communication channel for client
1번 과정에서 클라이언트가 접속을 하면 여기서는 올바른 소켓인지 판단하고, 접속한 소켓을 클라이언트 정보를 저장하는 배열에 저장하고, IOCP에 해당 소켓을 등록하고, 소켓에 읽기 작업을 신청한다. ( 읽기를 먼저 신청하는 이유는 대해서는 설명하지 않겠다. ) 이 때 중요한 것은 현재 WSARecv(), ReadFile()함수를 사용하여 읽기 작업을 신청했지만, IOCP는 작업의 완료 시에 읽기 작업을 끝냈는지 쓰기 작업을 끝냈는지 가르쳐 주지 않는다는 것이다. 따라서,OVERLAPPED구조체를 상속( C관점에서는 새로운 구조체를 선언할 때, OVERLAPPED구조체를 제일 첨에 위치하는 멤버로 선언하여 사용할 수 있다.)하여 읽기 작업을 하는 건지 쓰기 작업을 하는 건지에 대한 흔적을 남겨야 한다.
(3) Read Request from client
이 과정에서GetQueuedCompletionStatus() 함수를 사용하여 현재 등록된 소켓들 중에 읽기나 쓰기 작업이 완료된 것이 있는지 확인한다. 이 때,IOCP가 알려주는 정보는 2번 과정에서 등록 할 때, 소켓과 같이 입력했던 KEY와 I/O작업을 신청할 때, 인자로 넘겨주었던 OVERLLAPPED 구조체( 확장을 시켰다면 확장 구조체형으로 캐스팅 해주면 된다.)의 주소이다.
(4) Excute request locally
이제3번 과정에서 받은 key와 OVERLAPPED구조체를 가지고 I/O작업을 신청했을 때, 만약 작업이 끝나면 했었을 작업을 해주면 된다.
(5) Return result to client
이 과정은 사실4번 과정과 같이 포함되는 부분이다. 즉, 채팅을 예로 들면, 어떤 사용자가 메시지를 입력했을 때, 4번과정의 If( pOverlapped->mode == 읽기 ) {} 블록안이 실행될 것이고, 어떤 메시지인지 확인한 후, 접속한 모든 사용자에게 메시지를 보내게 된다.
3. IOCP 장단점
ü 장점
A. 2번(IOCP)에서 빨간색 문자색으로 써 있는 것 처럼 적은 수의 쓰레드로 윈속2 서버를 구성 할 수 있다. 윈속 2 API중에서 가장 적다.
B. 윈속2 API중에서 CPU 점유율이 가장 낮다. 이 점은 적은 수의 쓰레드를 사용하므로 얻는 이점이다. 쓰레드 숫자가 적으므로 당연히 ThreadContext Switch도 적게 일어난다.
C. 윈속2 API 중에서 가장 확장성과 성능이 뛰어나다.
ü 단점
A. 프로그램이 어렵다. 즉, 개념 파악이 어렵다.
B. 플랫폼이 제약이 있다. 윈속2이상과 윈도우 NT이상만 지원한다. 정확하게는 윈도우 2000이상에서 개발 하는게 낫다.
- www.codeproject.com, msdn.Microsoft.com,www.codeguru.com
- PlatformSDK, Network Programming For Microsoft Windows
출처: 예전에 다른분 홈페이지에서 그림을 가져왔는데 지금 잘모르겠습니다.^^;;; 나머지는 제가 공부하면서 정리 했습니다.^^;;;
[강좌] 기초적인 압축 알고리즘 하이텔 퍼옴.. (0) | 2007.10.23 |
---|---|
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
프로그래밍 :: 오라클 강좌 (0) | 2007.08.17 |
Oracle 10g의 Recycle Bin의 기능에 대해서... (0) | 2007.08.17 |
리눅스 기본명령어 (0) | 2007.07.03 |
프로그래밍 :: 오라클 강좌
★ SQL 의 종류
1.DDL (Data Definition Language): 데이터와 그 구조를 정의 합니다. |
SQL문 | 내 용 |
CREATE | 데이터베이스 객체를 생성 합니다. |
DROP | 데이터베이스 객체를 삭제 합니다. |
ALTER | 기존에 존재하는 데이터베이스 객체를 다시 정의하는역할을 합니다. |
|
SQL문 | 내 용 |
INSERT | 데이터베이스 객체에 데이터를 입력 |
DELETE | 데이터베이스 객체에 데이터를 삭제 |
UPDATE | 기존에 존재하는 데이터베이스 객체안의 데이터 수정 |
SELECT | 데이터베이스 객체로부터 데이터를 검색 |
|
SQL문 | 내 용 |
GRANT | 데이터베이스 객체에 권한을 부여 합니다. |
REVOKE | 이미부여된 데이터베이스객체의 권한을 취소합니다. |
★ 사용자의 생성
새로운 USER를 생성하기 위해서는CREATE USER문을 이용하면 됩니다.
USER를 생성하기 위해서는USER생성 권한이 있는 사용자로 접속해야 합니다.
사용자 생성 문법(Syntax) -user_name: 사용자 이름 -BY password: 사용자가데이터베이스에 의해 인증되도록 지정하며,데이터베이스 유저 로그온시 사용하는 비밀번호 입니다. -EXTERNALLY: 사용자가운영 체제에 의해서 인증되도록 지정합니다. -DEFAULT TABLESPACE는사용자 스키마를 위한 기본 테이블 스페이스를 지정합니다. -TEMPORARY TABLESPACE는사용자의 임시 테이블 스페이스를 지정합니다. -QUOTA절을 사용하여사용자가 사용할 테이블 스페이스의 영역을 할당합니다. -PASSWORD EXPIRE: 사용자가 SQL*PLUS를 사용하여데이터베이스에 로그인할 때 암호를 재설정하도록 합니다.(사용자가 데이터베이스에 의해 인증될 경우에만 적합한 옵션입니다.) -ACCOUNT LOCK/UNLOCK: 사용자 계정을 명시적으로 잠그거나 풀 때 사용할 수 있습니다.(UNLOCK이 기본값입니다.) -PROFILE:자원 사용을 제어하고 사용자에게 사용되는 암호 제어 처리 방식을 지정하는데 사용됩니다. ※ 여기선 간단한 유저생성에 대해서만 알아보고 자세한 유저관리와 PROFILE 관리는 어드민에서 설명 하겠습니다. ※ 참고 1 -임시 테이블스페이스를 지정해 주지 않으면 시스템 테이블스페이스가 기본으로 지정되지만시스템 테이블스페이스에 단편화가 발생할 수 있으므로사용자를 생성할때 임시테이블스페이스를 따로 지정해 주는 것이 좋습니다. - 또한DEFAULT TABLESPACE도 사용자를 생성할때 지정해 주지 않으면 기본적으로 시스템 테이블스페이스가 지정이 됩니다.하지만사용자를 생성할때 DEFAULT TABLESPACE를 지정을 해서 사용자가 소유한 데이터와 객체들의 저장 공간을 별도로 관리를 해야 합니다. 시스템 테이블스페이스는 본래의 목적(모든 데이터 사전 정보와, 저장 프로시저, 패키지, 데이터베이스 트리거등을 저장)을 위해서만 사용되어져야 하지 일반사용자의 데이터 저장용으로 사용 되어서는 안됩니다. ※ 참고 2 테이블 스페이스란? -오라클 서버가 테이터를 저장하는 논리적인 구조입니다. - 테이블스페이스는하나 또는 여러개의 데이터파일로 구성되는 논리적인 데이터 저장 구조입니다. 테이블 스페이스에 대한 자세한 내용는 오라클 어드민의 테이블스페이스 강좌에서 학습하겠습니다. |
|
SQL PLUS를 실행시키고 SCOTT/TIGER로 접속을 합니다. |
새로 생성한 USER로 접속해 볼까요.. |
★ User의 변경 및 삭제
USER 변경하기 위해서는ALTER USER문을 사용합니다..
● ALTER USER문으로 변경 가능한 옵션
- 비밀번호
- 운영체제 인증
- 디폴트 테이블 스페이스
- 임시 테이블 스페이스
- 테이블 스페이스 분배 할당
- 프로파일 및 디폴트 역할
|
|
|
|
※CASCADE를 사용하게 되면사용자 이름과 관련된 모든 데이터베이스 스키마가 데이터 사전으로부터 삭제되며 모든 스키마 객체들 또한 물리적으로 삭제 됩니다. |
|
|
★시스템 권한(System Privileges)
오라클에서 권한(Privilege)은 특정 타입의 SQL문을 실행하거나 데이터베이스나 데이터 베이스
-system_privilege: 부여할시스템 권한의 이름 -role: 부여할데이터베이스 역할의 이름 -user, role: 부여할사용자 이름과 다른 데이터 베이스 역할 이름 -PUBLIC:시스템 권한, 또는 데이터베이스 역할을 모든 사용자에게 부여할 수 있습니다. -WITH ADMIN OPTION:권한을 부여 받은 사용자도 부여 받은 권한을 다른 사용자 또는 역할로 부여할 수 있게 되며,만약 사용자가 WITH ADMIN OPTION과 같이 역할을 부여 받는다면 부여된 역할은 그 사용자에 의해 변경 또는 삭제 될 수 있습니다. |
|
|
|
문법(Syntax) |
|
|
|
WITH ADMIN OPTION을 사용하여 시스템 권한을 부여했어도 시스템 권한을 취소 할 때는 연쇄적으로 취소 되지 않습니다.
|
★객체 권한(Object Privileges)
◈Object Privileges(객체 권한)
객체권한 | 테이블 | 뷰 | Sequence | Procedure |
ALTER | ○ |
| ○ |
|
DELETE | ○ | ○ |
|
|
EXECUTE |
|
|
| ○ |
INDEX | ○ |
|
|
|
INSERT | ○ | ○ |
|
|
REFERENCES | ○ |
|
|
|
SELECT | ○ | ○ | ○ |
|
UPDATE | ○ | ○ |
|
|
-object_privilege: 부여할 객체권한의 이름 -object: 객체명 -user, role: 부여할사용자 이름과 다른데이터 베이스 역할 이름 -PUBLIC: 오브젝 권한, 또는 데이터베이스 역할을모든 사용자에게 부여할 수 있습니다. -WITH GRANT OPTION:권한을 부여 받은 사용자도 부여 받은 권한을 다른 사용자 또는 역할로 부여할 수 있게 됩니다. |
|
|
- 객체 권한의 철회는그권한을 부여한 부여자만이 수행할수 있습니다. -CASCADE CONSTRAINTS: 이 명령어의 사용으로 REFERENCES객체 권한에서 사용된 참조 무결성 제한을 같이 삭제 할 수 있습니다. -WITH GRANT OPTION으로 객체 권한을 부여한 사용자의 객체 권한을 철회하면,권한을 부여받은 사용자가 부여한 객체 권한 또한 같이 철회되는 종속철회가발생합니다. |
|
|
|
WITH GRANT OPTION을 사용하여 부여한 객체 권한을 취소하면 취소 작업이 연쇄적으로 수행 됩니다.
|
|
★롤(Role)
|
★ 테이블의 생성
이번 강좌는 오라클 테이블해 대해서 설명을 하겠습니다.
테이블은 실제로 데이터들이 저장되는 곳 이라고 생각하면 쉽게 이해 할 수 있습니다.
CREATE TABLE명령어를 이용해서 테이블을 생성 할 수 있습니다.
아래의 내용은 테이블에 대한 보충 설명입니다.
테이블 이란? 1. 테이블은 오라클 데이타베이스의기본적인 데이타 저장 단위입니다. 2. 데이타베이스 테이블은 사용자가 접근 가능한 모든 데이타를 보유하며레코드와 컬럼으로 구성 됩니다. 관계형 데이타베이스가 아닌 예전의 데이타 베이스 용어에서는 파일과 테이블이, 필드와 컬럼이, 그리고 레코드와 행이 동일시 되었습니다. 3. 테이블은 시스템내에서 독립적으로 사용되길 원하는 엔티티를 표현할수 있습니다. 예를 들면, 회사에서의 고용자나 제품에 대한 주문은 테이블로 표현 가능합니다. 4. 테이블은 두 엔티티간의 관계를 표현할 수 있습니다. 즉 테이블은 고용자와 그들의 작업 숙련도 혹은 제품과 주문과의 관계를 표현하는데 사용될 수 있습니다. 테이블내에 있는 외래 키 (ForeIgn Key)는 두 엔티티 사이의 관계를 표현하는데 사용됩니다. 5. 비록 "테이블" 이라는 말이 더 많이 사용되지만 테이블의 형식어는 "릴레이션" 입니다. 컬 럼 - 테이블의 각 컬럼은 엔티티의 한 속성을 표현한다 행(ROW, 레코드) -테이블의 데이타는 행에 저장됩니다 |
|
- 테이블 이름과 컬럼은 항상 알파벳 문자로 시작해야 하며A~Z까지의 문자, 0~9까지의 숫자, |
-테이블의 컬럼 이름은30자를 초과할수 없고,예약어를 사용할수 없읍니다. |
- 오라클 테이블한 계정안에서 테이블 이름은 다른 테이블 이름과 달리 유사해야 합니다. |
- 한 테이블 안에서 컬럼이름은 같을수 없으며 다른 테이블에서의 컬럼이름과는 같을수 있습니다. |
테이블의 생성 문법 |
[Syntax]
|
테이블의 생성 예제 |
emp2와 dept2테이블을 생성하는 예제입니다. |
유저가 소유한 모든 테이블 보기 |
USER_TABLES데이터사전을 조회 하면유저가 소유한 테이블을 확인 할 수 있습니다. -- SQL*Plus에서 실행해 보세요.. SQL>SELECT table_name FROM USER_TABLES; TABLE_NAME ------------ BONUS CRETABLE DEPT DUMMY EMP EMP2 SALGRADE 위와 같이 테이블 목록이 조회 됩니다. |
★ 테이블의 제약조건
제약조건 (Constraint)
제약조건이란 테이블에 부적절한 자료가 입력되는 것을 방지하기 위해서 여러 가지 규칙을 적용해 놓는거라 생각하면 됩니다. 간단하게테이블안에서 테이터의 성격을 정의하는 것이 바로 제약조건 입니다.
★데이터의 무결성 유지를 위하여 사용자가 지정할 수 있는 성질입니다.
★모든 CONSTRAINT는 데이터 사전(DICTIONARY)에 저장됩니다.
★ 의미있는 이름을 부여했다면 CONSTRAINT를 쉽게 참조할 수 있습니다.
★ 표준 객체 명명법을 따르는 것이 좋습니다.
★ 제약조건은 테이블을 생성할 당시에 지정할 수도 있고, 테이블 생성 후 구조변경(ALTER)명령어를
통해서도 추가가 가능합니다.
★ NOT NULL제약조건은 반드시 컬럼 레벨에서만 정의가 가능합니다.
|
여기서emp_nn_ename은 (테이블이름_제약조건이름_컬럼이름)형식으로 CONSTRAINT_NAME |
|
|
|
|
|
SQL>CREATE TABLE emp( |
|
※ 기본키는 그 데이터 행을 대표하는 컬럼으로서의 역할을 수행하여다른 테이블에서 UNIQUE 조건과 마찬가지로 기본키를 정의하면 자동으로 인덱스를 생성하며 |
|
SQL>CREATE TABLE emp( |
|
|
제약 조건의 확인 |
★ 테이블의 관리
테이블의 관리는 테이블의 컬럼 관리와 테이블 정보 관리로 나누어서 설명 하겠습니다.
① 테이블 컬럼의 관리
테이블의 컬럼은 ADD, MODIFY, DROP연산자를 통해서 관리 할 수 있습니다.
ADD연산자 :테이블에 새로운 컬럼을 추가할 때 사용 합니다.
SQL>ALTER TABLE empADD(addr VARCHAR2(50)); |
|
|
|
|
② 테이블 정보의 관리 |
한번 실습해 보세요.. SQL>CREATE TABLE emp2 AS SELECT * FROM emp; 테이블이 생성되었습니다. |
|
STORAGE-CLAUSE에 들어올 수 있는 스토리지 파라미터를 정리하면 아래와 같습니다. - NEXT 다음 번 생성될 익스텐트의 크기를 Byte단위로 지정합니다. 이후의 익스텐트 크기는 PCTINCREASE만큼씩 증가 됩니다. - PCTINCREASE 마지막 생성된 익스텐트의 바로 다음에 생성될 익스텐트의 증가율을 퍼센트지로 지정합니다. - MINEXTENTS 최초 생성되는 익스텐트의 수를 지정합니다. - MAXEXTENTS 생성될 수 있는 최대 익스텐트의 수를 지정합니다. 기타 블록관련 파라미터는 테이블의 생성 강좌를 참고하세요.. |
|
-- 한번 실습해 보세요. SQLPLUS scott/tiger SQL>ALTER TABLE emp MOVE TABLESPACE test; 테이블이 변경되었습니다 |
|
|
|
SQL>DROP TABLEemp ; SQL>DROP TABLEempCASCADE CONSTRAINT; CASCADE CONSTRAINT :외래키에 의해 참조되는 기본키를 포함한 테이블일 경우 기본키를 참조하던 외래 키 조건도 같이 삭제 됩니다. |
★ 데이터의 삽입, 수정, 삭제
▣ INSERT |
|
◈모든 데이터를 입력할 경우 SQL>INSERT INTODEPT SELECT* FROM SCOTT.DEPT ; 직접 데이터를 입력해 봅시다. 오라클을 설치하면 SCOTT/TIGER USER에 기본적으로 EMP, DEPT테이블이 있습니다. 그 데이터를 TEST/TEST USER에 생성한 EMP, DEPT테이블에 INSERT하겠습니다. SQL>INSERT INTODEPT SELECT* FROM SCOTT.DEPT ; 4 개의 행이 만들어졌습니다. SQL> COMMIT; 커밋이 완료되었습니다. SQL> INSERT INTO EMP SELECT * FROM SCOTT.EMP; 15 개의 행이 만들어졌습니다. SQL> COMMIT; 커밋이 완료되었습니다. |
|
SQL>UPDATEEMP |
|
SQL>DELETEFROMEMP |
★ Select문 및 연산자
SELECT문은데이터베이스로부터 저장되어 있는 데이터를 검색하는데 사용합니다.
[Syntax]
SQL>SELECTempno 사번, ename 성명 |
▣ IN, NOT IN 연산자 |
IN 연산자 SQL> SELECT empno, ename FROM emp WHERE empnoIN (7900, 7934); --> 사번이 7900, 7934번인 사원의 사번과 성명 출력 EMPNO ENAME --------- ------------- 7934 MILLER 7900 JAMES 2 개의 행이 선택되었습니다. |
NOT IN 연산자 |
|
BETWEEN 연산자 |
|
구 분 | 설 명 |
LIKE 'A%' | 컬럼이 'A'로 시작하는 데이터들만 검색됩니다. |
LIKE '%A' | 컬럼이 'A'로 끝나는 테이터들만 검색됩니다. |
LIKE '%KIM%' | 컬럼에 'KIM' 문자가 있는 데이터 들만 검색됩니다. |
LIKE '%K%I%' | 컬럼에 'K' 문자와 'I'문자가 있는 데이터 들만 검색됩니다. |
LIKE '_A%' | 컬럼에 'A'문자가 두 번째 위치한 데이터 들만 검색됩니다. |
|
|
|
SQL> SELECT empno, ename |
★ 예명(Alias)
테이블 예명(Alias)
-테이블 alias로column을 단순, 명확히 할 수 있습니다.
-현재의 SELECT 문장에 대해서만 유효합니다.
- 테이블 alias는 길이가 30자 까지 가능하나짧을수록 더욱 좋습니다.
- 테이블alias는 의미가 있어야 합니다
- FROM절에 테이블 alias설정시 해당 테이블 alias는 SELECT문장에서 테이블 이름 대신에
사용해야 합니다.
|
★Equi Join, Non_Equi Join, Self Join
조인(Join) ?
◈둘이상의 테이블을 연결하여 데이터를 검색하는 방법입니다.
◈보통 둘 이상의 행들의 공통된 값 Primary Key 및 Foreign Key 값을 사용하여 조인합니다.
◈그러므로 두 개의 테이블을 SELECT문장 안에서 조인하려면 적어도 하나의 컬럼이
그 두 테이블 사이에서 공유 되어야 합니다..
|
|
|
SQL>SELECT e.ename, d.dname |
|
SQL>SELECT e.ename, d.dname |
|
SQL> SELECT concat(a.ename,' ') ||' : \'|| b.sal 급여 이름과 급여를 연결시켜서 보여줍니다. |
★Outer Join (LEFT, RIGHT, FULL OUTER JOIN)
◈Out(외부) Join
- equijoin 문장들의 한가지 제약점은 그것들이 조인을 생성하려 하는 두 개의 테이블의 두 개
컬럼에서 공통된 값이 없다면 테이블로부터 테이터를 Return하지 않는 다는 것입니다.
- 정상적으로 조인 조건을 만족하지 못하는 행들을 보기위해 outer join을 사용합니다.
Outer join 연산자 "( + )"입니다.
-조인시킬 값이 없는 조인측에 "( + )"를 위치 시킵니다.
- Outer join 연산자는 표현식의 한 편에만 올 수 있습니다.
|
Oracle9i부터는 ANSI/ISO SQL표준인LEFT OUTER JOIN,RIGHT OUTER JOIN,FULL OUTER JOIN를 지원 합니다. |
☞LEFT OUTER JOIN 왼쪽 테이블에 조인시킬 컬럽의 값이 없는 경우 사용합니다. SQL>SELECT DISTINCT(e.deptno), d.deptno FROM dept dLEFT OUTER JOINemp e ONd.deptno = e.deptno; ☞RIGHT OUTER JOIN - 오른쪽에 테이블에 조인시킬 컬럽의 값이 없는 경우 사용합니다. SQL>SELECT DISTINCT(a.deptno), b.deptno FROM emp aRIGHT OUTER JOINdept b ONa.deptno = b.deptno; ☞FULL OUTER JOIN 양쪽 테이블에 다 outer join을 거는것을 TWO-WAY OUTER JOIN 또는 FULL OUTER JOIN이라 합니다. SQL>SELECT DISTINCT(a.deptno), b.deptno FROM emp aFULL OUTER JOINdept b ONa.deptno = b.deptno; -- 위 세 문장의 결과는 아래와 같습니다. DEPTNO DEPTNO ---------- ---------- 10 10 20 20 30 30 40 LEFT OUTER JOIN과 RIGHT OUTER JOIN의 테이블 순서를 바꾸어 가면서 테스트를 하시면 쉽게 이해를 하실 수 있습니다. |
★Commit과 Rollback 예제
Commit 과 Rollback
이전의 커밋(COMMIT)이 일어난 뒤부터 다음의 커밋(COMMIT) 전까지의 작업이 하나의 트랜
잭션 이며, 커밋과 롤백(ROLLBACK)은 이러한 트랜잭션 단위로 데이터 베이스에서 발생한
작업을 저장, 삭제하는 일입니다.
- Automatic commit:DDL(Create, Alter, Drop), DCL(Grant, Revoke)
- Automatic Rollback:비정상적인 종료, system failure
커밋과 롤백 예제입니다.
|
|
SQL>INSERT INTO emp(empno, ename, hiredate) VALUES(10000, 'test2', sysdate ); |
★숫자함수(Number Functions)
숫자함수(Number Functions)
|
SQL>SELECTABS(-10)Absolute FROM dual ; |
|
SQL>SELECTCEIL(10.1)TEST FROM dual ; SQL>SELECTCEIL(-10.1)TEST FROM dual ; |
|
|
SQL>SELECTFLOOR(10.1)TEST FROM dual ; SQL>SELECTFLOOR(-10.1)TEST FROM dual ; |
|
|
SQL>SELECTMOD(9, 4)TEST FROM dual ; |
|
SQL>SELECTPOWER(4, 2)TEST FROM dual ; |
|
SQL>SELECTROUND(192.123, 1)TEST FROM dual ; SQL>SELECTROUND(192.123, -1)TEST FROM dual ; |
|
|
|
SQL>SELECTTRUNC(7.5597, 2)TEST FROM dual ; |
CEIL COS COSH EXP FLOOR LN LOG MOD POWER ROUND (number) SIGN SIN SINH SQRT TAN TANH TRUNC (number) WIDTH_BUCKET |
★문자열 처리 함수(Character Functions)
문자열 처리 함수(Character Functions)
|
SQL>SELECTCONCAT('Oracle', ' Korea')NAME FROM dual ; |
|
SQL>SELECTINITCAP('kim jung sick')NAME FROM dual ; |
|
SQL>SELECTLOWER('KIM JUNG SICK')NAME FROM dual ; SQL>SELECTUPPER('kim jung sick')NAME FROM dual ; |
|
SQL>SELECTLPAD('JUNG-SICK', 10, '*')NAME FROM dual ; |
|
SQL>SELECTRPAD('JUNG-SICK', 10, '*')NAME FROM dual ; |
|
SQL>SELECTSUBSTR('JUNG-SICK', 3, 3)NAME FROM dual ; -- 뒤에서부터 자를 |
|
SQL>SELECTLENGTH('JUNG-SICK') TESTFROM dual ; |
|
|
|
|
|
|
|
Character Functions |
CHR CONCAT INITCAP LOWER LPAD LTRIM NLS_INITCAP NLS_LOWER NLSSORT NLS_UPPER REPLACE RPAD RTRIM SOUNDEX SUBSTR TRANSLATE TREAT TRIM UPPER ASCII INSTR LENGTH |
★날짜 처리 함수(Date Functions)
LAST_DAY(d)
LAST_DAY함수는 달의 마지막 날의 날짜를 반환합니다
SQL>SELECT SYSDATE TODAY,LAST_DAY(SYSDATE) LASTDAYFROM dual ; |
|
SQL>SELECT TO_CAHR(ADD_MONTHS(SYSDATE,3),'RRRR/MM/DD' LASTDAY) "date" |
|
SQL>SELECTMONTHS_BETWEEN(TO_DATE('2000/06/05') , TO_DATE('2000/09/23')) "Date" |
|
SQL>SELECTROUND(TO_DATE('1998/09/11'), 'YEAR') FROM dual ; |
☞ 날짜에 대한 산술 연산
|
★ 변환 함수(Conversion Functions)
TO_CHAR
TO_CHAR함수는 DATE형, NUMBER형을 VARCHAR2형으로 바꺼 줍니다.
SQL>SELECTTO_CHAR(SYSDATE, 'MONTH') CHARTESTFROM dual ; |
|
SQL>SELECTTO_DATE('2000/06/16','RRRR/MM/DD')FROM dual ; |
|
SQL>SELECTTO_NUMBER('1210616')FROM dual ; |
★General Functions
NVL |
SQL>SELECT empno,NVL(comm, 0) |
|
SQL> SELECT deptno, DEPTNO DECODE(DEP |
★기타 함수들
DUMP: DUMP는 바이트 크기와 해당 데이터 타입 코드를 반환합니다.. |
SQL>SELECT ename,DUMP(ename, 16) "16진수" |
|
SQL>SELECTGREATEST(10, 100, 5, -7) FROM DUAL; |
|
SQL>SELECTLEAST(10, 100, 5, -7) FROM DUAL; |
|
SQL> SELECTUSER, UIDFROM DUAL; |
|
SQL> SELECTUSERENV('LANGUAGE') FROM DUAL; |
|
SQL> SELECTVSIZE(ename), ename |
★Group Function의 종류
☞ 그룹함수란 ?
- 그룹 함수란여러 행 또는 테이블 전체의 행에 대해 함수가 적용되어 하나의 결과값을 가져오는
함수를 말합니다..
-GROUP BY절을 이용하여그룹 당 하나의 결과가 주어지도록 그룹화 할 수 있습니다.
-HAVING절을 사용하여그룹 함수를 가지고 조건비교를 할 수 있습니다.
-COUNT(*)를 제외한 모든 그룹함수는 NULL값을 고려하지 않습니다.
-MIN, MAX그룹함수는모든 자료형에 대해서 사용 할 수 있습니다.
☞그룹 함수의 종류
COUNT
COUNT 함수는 검색된 행의 수를 반환합니다.
SQL>SELECTCOUNT(deptno) FROM DEPT ; |
|
SQL>SELECTMAX(sal) salary FROM emp ; |
|
SQL>SELECTMIN(sal) salary FROM emp ; |
|
SQL>SELECTROUND(AVG(sal),1) salary FROM emp WHERE deptno = 30 |
|
SQL>SELECTSUM(sal)salary FROM emp WHERE deptno = 30; |
|
SQL> SELECTROUND(STDDEV(sal),3)salary FROM emp WHERE deptno = 30 ; |
★Group By절과 Having절
GROUP BY
- 특정한 컬럼의 테이터 들을 다른 데이터들과 비교해유일한 값에 따라 무리를 짓습니다.
-GROUP BY절을 사용하여한 테이블의 행들을 원하는 그룹으로 나눕니다.
- Column명을 GROUP함수와 SELECT절에 사용하고자 하는 경우 GROUP BY뒤에 Column명을
추가 합니다.
부서별로 그룹을 지은 검색 결과 값이며 |
☞ Group By 예제 |
|
HAVING절 예제 |
★인덱스(Index)
|
자동 인덱스:프라이머리 키또는uinque 제한 규칙에 의해자동적으로 생성되는 인덱스입니다. |
※ Index를 생성하는 것이 좋은 Column |
※ 오라클 인덱스는B-tree(binary search tree)에 대한 원리를 기반으로 하고 있습니다. |
|
SQL>CREATE BITMAP INDEXemp_deptno_indx |
|
SQL>CREATE UNIQUE INDEXemp_ename_indx |
|
SQL>CREATE INDEX dept_dname_indx |
|
SQL>CREATE UNIQUE INDEXemp_empno_ename_indx |
※ 인덱스의 삭제 |
※ 인덱스에 대한 정보는USER_INDEXES뷰 또는USER_IND_COLUMNS뷰를 통해 검색할 수 |
SQL> SELECTindex_name , index_type |
★ VIEW 테이블
뷰란? |
|
-FORCE:기본 테이블 유무에 관계없이 VIEW를 생성 -WITH CHECK OPTION:VIEW에 의해 엑세스될 수 있는 행만이 입력되거나 변경될 수 있음을 지정 합니다. -WITH READ ONLY:SELECT만 가능한 VIEW의 생성 - VIEW를 정의하는 질의어에는ORDER BY절을 사용 할 수 없습니다. -함수를 사용한 컬럼은 반드시 ALIAS를 지정해야 합니다. |
SQL> CREATE OR REPLACE VIEWName_Query |
|
|
|
SQL> CREATE OR REPLACE VIEWRead_Only |
|
|
★SEQUENCE(시퀀스)
|
START WITH:시퀀스의 시작 값을 지정합니다. n을 1로 지정하면 1부터 순차적으로 시퀀스번호가 증가 합니다. INCREMENT BY:시퀀스의 증가 값을 말합니다. n을 2로 하면 2씩 증가합니다. START WITH를 1로 하고 INCREMENT BY를 2으로 하면 1, 3, 5,7,.. 이렇게 시퀀스 번호가 증가하게 됩니다. MAXVALUE n | NOMAXVALUE : MAXVALUE는시퀀스가 증가할수 있는 최대값을 말합니다. NOMAXVALUE는 시퀀스의 값을 무한대로 지정합니다. MINVALUE n | NOMINVALUE : MINVALUE는시퀀스의 최소값을 지정합니다. 기본값은 1이며, NOMINVALUE를 지정할 경우 최소값은 무한대가 됩니다 |
|
START WITH는 수정할수 없습니다. START WITH 절이 없다는 점을 빼고는 CREATE SEQUENCE와 같습니다. |
|
★SYNONYM(동의어)
시노님은 오라클 객체(테이블, 뷰, 시퀀스, 프로시저)에 대한 대체이름(Alias)를 말합니다.
Synonym은 실질적으로 그 자체가 Object가 아니라 Object에 대한 직접적인 참조 입니다.
시노님을 사용하는 이유는..
①데이터베이스의 투명성을 제공하기 위해서 사용 한다고 생각하면 됩니다.
시노님은 다른 유저의 객체를 참조할 때 많이 사용을 합니다.
② 만약에 실무에서 다른 유저의 객체를 참조할 경우가 있을 때 시노님을 생성해서 사용을 하면은
추후에 참조하고 있는 오프젝트가 이름을 바꾸거나 이동할 경우 객체를 사용하는 SQL문을 모두
다시 고치는 것이 아니라 시노님만 다시 정의하면 되기 때문에 매우 편리 합니다.
③객체의 긴 이름을 사용하기 편한 짧은 이름으로 해서 SQL코딩을 단순화 시킬 수 있습니다.
④또한 객체를 참조하는 사용자의 오브젝트를 감추 수 있기 때문에 이에 대한 보안을 유지할 수
있습니다.
시노님을 사용하는 유저는 참조하고 있는 객체를에 대한 사용자의 object의 소유자, 이름, 서버이름을 모르고 시노님 이름만 알아도 사용 할 수 있습니다.
Synonyms을 사용하는 경우
-오브젝트의 실제 이름과 소유자 그리고 위치를 감춤으로써 database 보안을 개선하는데 사용됩니다
- Object에의 Public Access를 제공 합니다.
-Remote Database의 Table, View, Program Unit를 위해 투명성을 제공합니다.
-Database 사용자를 위해 SQL 문을 단순화 할 수 있습니다.
시노님에는 두가지 종류가 있습니다.
①Private Synonym
- 전용 시노님은특정 사용자만 이용할수 있습니다.
②Public Synonym
- 공용 시노님은 공용 사용자 그룹이 소유하며 그Database에 있는 모든 사용자가 공유 합니다.
시노님 생성 문법(Syntax)
- PUBLIC : 모든 사용자가 접근 가능한 시노님을 생성 합니다.
PUBLIC 시노님의 생성 및 삭제는 DBA만이 할 수 있습니다.
|
class 들의 단계적 참조 관계 (0) | 2007.10.12 |
---|---|
IOCP (IOCompletionPort) 분석 (0) | 2007.09.21 |
Oracle 10g의 Recycle Bin의 기능에 대해서... (0) | 2007.08.17 |
리눅스 기본명령어 (0) | 2007.07.03 |
4. Net8 클라이언트측의 기본적인 구성 (0) | 2007.05.07 |
ORA-38301: can not perform DDL/DML over objects in Recycle Bin
SQL> show recyclebin
ORIGINAL NAME RECYCLEBIN NAME OBJECT TYPE DROP TIME
---------------- ------------------------------ ------------ -------------------
MEMBER BIN$7ibiCGZXF4PgMOabUJ0qBQ==$0 TABLE 2005-01-21:11:48:19
MEMBER BIN$7hq6upeqF+TgMOabUJ0hlg==$0 TABLE 2005-01-20:21:18:20
PICTURES BIN$7ibiCGZLF4PgMOabUJ0qBQ==$0 TABLE 2005-01-21:11:48:18
SQL> FLASHBACK TABLE PICTURES TO BEFORE DROP;
FLASHBACK COMPLETE.
SQL> purge recyclebin;
Recyclebin purged.
SQL> drop table PICTURES purge;
IOCP (IOCompletionPort) 분석 (0) | 2007.09.21 |
---|---|
프로그래밍 :: 오라클 강좌 (0) | 2007.08.17 |
리눅스 기본명령어 (0) | 2007.07.03 |
4. Net8 클라이언트측의 기본적인 구성 (0) | 2007.05.07 |
3. Net8 서버측의 기본적인 구성 (0) | 2007.05.07 |
기본적인 명령어
#ls (-l,-a):각 루트상에서 디렉토리 및 파일을 출력한다. 도스의 dir과 같은 명령..
#pwd 현재 디렉토리경로
#df :리눅스파티션을 보고자할 때 사용.
#cd ..상위디렉토리로 이동
#cd 폴더/해당디렉토리로 이동
#vi 편집명령어
#cat 내용출력
#du -sh 남은 용량확인법
#chmod 권한설정
#tar :압축명령(옵션)
#gzip :이중압축명령(옵션)
디렉토리 이동명령
일반적으로 디렉토리나 파일이 많을 경우 자신이 어디에 위치에 있는지 그리고 직접적으로 디렉토리로 다이렉트로 이동해야 하는경우가 많아진다... 디렉토리 이동명령을 통해 바로이동할수있는 것이 숙제
예) # cd /home 홈디렉토리로 바로이동하기.....
# ls -l 홈디렉토리 내용살피기
# cd master1 마스터1의 디렉토리안으로 이동하기...
목록보기
목록보기에는 대부분 ls를 사용하는데 여기에도 다양한 옵션으로 다양한 결과물을 볼수가 있다....가장많이 쓰는 명령이니만큼 다양한 특징을 안다면 작업하는데 굉장히 편리할 것이다.
#ls -l 세로배열로 결과물을 출력해준다....
#ls -al 가능모든 파일을 결과물로 통해 세로배열로 보여준다.
#ls -al |more:파일의 내용이 많을 때 한단계씩 보여준다(dos:dir/p)와 같은 효과이다.
스페이스바를 누르면 다음결과물을 보여주고 Q를 누르면 빠져나간다.
#ls -l /etc/group:특정파일을 다음과 같은 명령으로 찾아볼 수 있다.
#ls -F :이명령은 실일파일여부를 확인하는 명령이다. 실행파일일 경우 *이붙어서 나온다
그밖에 많은 옵션이 있지만 생략한다.(#ls --help)를 보면 여러 가지 옵션을 볼 수 있다.
디렉토리생성과 삭제
디렉토리를 생성과 또 삭제하는데 필요한 명령을 알아보자
대체적으로 생성하는 명령은 mkdir명령을 쓴다.
특정디렉토리에서 #mkdir kkk라치면 그특정디렉토리하위에 kkk라는 디렉토리가 생성이 된다. ls로 확인을 하여보자.
또한 특정한 곳에 디렉토리를 생성하고싶은면 이렇게 하면된다.
#mkdir /home/webmaster/kkk라치면 홈밑에 웹마스터란 방밑에 kkk를 생성한다는 뜻이다.
디렉토리를 삭제하는 명령또한 동일하다.
홈디렉토리밑에 kkk란 디렉토리가 있다면 이디렉토리를 삭제하는 방법이다.
#rmdir kkk라치면 kkk란 디렉토리가 삭제된다.
#rmdir /home/webmaster/kkk라치면 홈밑에 웹마스터란 방밑에 kkk를 삭제한다는 뜻이다.
하지만 하위디렉토리에 내용이나 또다른 디렉토리가 있다면 삭제가 되질않는다...
이때는 rm이란 명령으로 삭제를 한다....옵션 또한 여러 가지가 있지만....
가장많이 쓰는 명령만 간단히 소개한다.
#rm -r kkk라치면 먼저 하위디렉토리로 들어가서 지울지여부를 물어본다....삭제하고자한다면 y(yes)를치면 그해당파일은 삭제가 된다.
하지만 이과정을 모두 생략하기를 원한다면 다음과 같이 입력하면 삭제가 된다.
#rm -rf kkk이렇게 치면 깨끗이 삭제가 된다....
하지만 지우면 복귀할수 없으므로 정말 신중에 신중을 기하여 삭제하길 바란다.
복사명령과 이동명령
리눅스에서 도 파일을 복사하는 명령이 있다.....통상적으로 도스에서는 copy,diskcopy명령으로 복사를 했지만 리눅스에서는 cp로 사용한다...별반 다를게 없으므로 작업을 해보면 쉽게 이해할수 있다...
임의의 디렉토리를 하나 생성한다. 여기서는 webmaster밑에 webm01이란 디렉토리를 예로 한다.
#cd ~webm01이라 입력을 하면 바로 특정디렉토리로 이동을 할 수 있다.
만약 이동을 하지않는다면 webm01이란 방이 없거나 경로가 잘못되어서 그러므로 경로를 바꾸어주면 된다.... 경로바꾸는 것은 위에서 설명하였으므로 생략한다.
#cd _webm01로 이동
#touch test1:테스트1이란 빈파일을 만든다는 뜻이다(touch:빈파일만들기)
#vi test1:vi 편집기를 통해 test1에 임의의 내용을 입력하고 저장하고 나온다.
#cp test1 test2:test1을 test2란 파일로 복사한다는 뜻이다.
#vi test2:이파일을 열어 test1안에 적힌 내용과 같은지 확인한다.(같다면 성공이다.)
이번엔 test란 디렉토리를 만들어 방법만든 test1,2파일을 디렉토리에 복사하여 넣어보자..
#mkdir test란 디렉토리생성한다.
#cp test1 test2 test/라 입력하면 test1,test2파일이 test디렉토리에 복사된다.확인하여보자(ls)
다음은 하위디렉토리에서 특정디렉토리로 복사하는 법을 알아보자
여기서는 하위디렉토리에서 홈디렉토리로 복사하는법을 설명한다.
#cp -r test /home:여기서 -r은 디렉토리째로 복사한다는 뜻이다. test란 디렉토리를 home에 복사를 한다. 확인하여보자.....
다음은 동시에 여러개의 빈파일을 만드는 방법이다.
#touch aaa bbb ccc ddd eee fff:여기서 나온 파일을 동시에 만든다는뜻이다. 당연히 더많이도 생성가능하다..... 파일이 만들어졌는지 확인하여보자.
다음은 특정파일만 삭제
#rm -r a*:이말은 a로 시작하는 모든 파일을 삭제한다는 뜻이다.
다음은 이동명령 mv를 알아보자 이명령은 디렉토리나 파일을 이동할때사용하면 파일의이름을 변경할때는 적용이된다.
#mv test test2:이말은 옮긴다는 뜻이아니라 test test2로 명명한다는 뜻이다.
#mv test /home/webmster:이말은 test란 디렉토리를 홈밑에 웹마스터방밑에 이동한다는 뜻이다. 자 한번 실습해보기 바란다.
일정한 자료찾기 명령
#find / -name skell -> 일정한 자료찾기를 할 수 있다.
간단한 vi편집기명령알기(cat)동일
cat의 경우 수정,변경,저장할 수는 없다 단지출력명령.
vi 명령을 쓰면 일정텍스트상의 내용을 수정 변경 저장할 수 있다.
일반적인 명령을 예로 들어보자
예)
#vi /etc/group ->etc밑에 그룹의 내용을 보거나 수정한다는 내용이다.
텍스트가 출력이 되면 수정하고자하는 부분이 있을 경우 insert키를 눌려 수정하고자하는 셀로 이동을 한다.... 만약수정하였으면 esc키를 눌려 insert키를 해제시키고 콜론이누른다.(shift+:)그러면 하위에 콜론이 생성이되는데....저장하고자 한다면 qw(종료저장),저장하지않고 그냥종료시킨다면, q!를 누르면 된다...자 이제 활용을 해보자.
리눅스 설치에서 파티션나누기...
리눅스는 일반 윈도우와는 달리 각각에 대한 루트계정을 만들어 주어야 한다.
윈도우즈의 경우는 포맷과 운영체제설치와 동시에 모든 디렉토리생성 및 응용프로그램설치를 아무곳에서나 가능하나 리눅스는 이와는 다른다....
/:최상위 디렉토리로 운영자가 직접관리 및 운용할수있는공간
/boot:
/usr : 현재 시스템에서 사용하는 응용프로그램을 이곳에 설치를 한다.윈도우즈의 경우 programs files디렉토리에 설치를 하듯이곳에 리눅스 패키지가 설치된다.
/home : 이곳엔 일반인에게 계정을 부여하고 일정의 공간을 할당해주는 역할을 한다.
웹호스팅을 사용해본 유저라면 쉽게 이해하리라 생각이 든다.
/swap : 일반적으로 swap이란 가상메모리를 뜻하는데 리눅스에서 이렇게 램이 아닌 가상메모리지원해 줌으로써 램이 적더라도 swap메모리를 할당해주어 램과 같은 역할을 하여준다.
swap메모리를 활용을 하면 최상의 시스템구축이 가능하다. 일반적으로 자신의 램의 2배를 지정해주는 것이 좋다고 한다.
가상콘솔(ctrl+alt_f1) x-window에 들어가지 않고 바로 가상콘솔로접속
[root@note/root}#:#를 bash sell이라 함...
콘솔과 터미널:콘솔 :서버앞에서 직접작업을 하는 것을 콘솔이라하며, 터미널이란 멀리서 원격으로 접속을 하여 작업을 하는 것. 또한 가상콘솔작업은 root계정으로 작업을 하면 이것은 보안문제 때문에 다른계정으로 작업을 많이한다. 터미널의 경우 root작업은 치명적인 보안문제 때문에 일반계정으로 접속하여 작업을 많이함.....
단축키명령
(ctrl+alt_f1):가상콘솔 작업
(ctrl+alt_f2)
(ctrl+alt_f3):초기화 로그인
(ctrl+alt_f7):x-windows로 들어가기
콘솔상의 작업종료:exit,logout명령이 있으면 shutdown의 경우 시스템을 종료할 때 사용한다.
옵션명령 : -r 재부팅 -h 시스템종료 -c shutdown명령을 취소
시간타임 : now지금 즉시 지정된 shutdown명령실행
+m m분후에 지정된 shutdown명령을 실행
hh:mm hh시 mm분에 지정된 shutdown명령을 실행
메세지 :현재 접속되어 있는 로그인 사용자들에게 언제쯤 종료를 한다고 알리는 메시지 기능을 제공(중요사항)
예)shutdown -r now지금 즉시종료시행 shutdown +5 now 5분후 종료....
새로운 사용자를 추가(계정)을 부여하기 위해 사용한다.
일반적으로 adduser/useradd 명령을 사용한다.(사용법은 완전히 동일하다.)
예)# adduser master1
# passwd master1
# 패스워드 입력
# 재입력.......
(패스워드의 경우 숫자와 일반글자를 조합하는 것이 좋으며 나쁜패스는 시스템에서 받아 들이지 않는다....)
등록을 성공하면 successfully메세지가 나온다....이메세지가 나오면 성공....
자 /home디렉토리로 이동을 하면 새롭게 추가된 계정을 확인할수 있다. 자 (ls -l)
(사용자이름을 생략하고 passwd를 실행하면 현재 로그인한 사용자의 패스워드를 변경할 수 있다.
패스
#vi /etc/passwd를 실행하면 리스트가 출력이 된다.
리스트중에 다음의 글이있을 것이다.
root : x : 0 : 0 : root: /root: /bin /bash(bash)란쉘을 뜻함.
root:사용자명
x:비밀번호
0:uid
0:gid(그룹아디)
root:선명(전화)comment
root:홈디렉토리
shadow:특정계정을 추가한후 패스파일을 암호화한 파일을 말한다.
#useradd mask1
#passwd mask1
암호를 준후
#vi /etc/passwd확인
#vi /etc/passwd확인후 암호화(shadow)를 확인.
일반계정부여와 함께 자동 홈페이지방 만들기...
리눅스상에서 방을 부여하면 홈페이지를 만들수 있는 방이 필요하다...
이것이 public_html이란것인데 이것을 계정부여와 동시에 만드는 방법을 배워본다.
#cd /etc/skel
#ls -l
#pwd
#mkdir mail
#mkdir public_html
#ls -l
이렇게해주면 계정부여와 동시에 자동으로 sand mail과 public_html이 자동으로 만들어진다.
그룹생성명령(group)
그룹이란 일정한 시스템에서 여러사람이 그사용자성격상 비슷한사람들이 그룹으로 나우어 관리를 하는 경우 사용한다. 그룹을 잘이용하면 여러모로 전문적성격을 지닌 시스템으로 활용을 할 수 있다.
예) 그룹생성과 일반계정으로 그룹에 등록시키는 내용
#groupadd wm --->그룹명을 wm으로 지정을 하였다.
#vi /etc/group --->vi편집기를 통해 group내용을 확인변경할수 있다.
#useradd --help -->옵션을 활용할 때 이렇게하면 옵션사항을 출력하여 볼 수 있다.
그룹에 등록시키는법
#useradd -g wm web1 : web1이란 아이디를 wm이란 그룹에 등록한다는 내용이다
#useradd -g wm web1 : web2역시 wm이란 그룹에 등록
#vi /etc/passwd --> 등록이 잘되었는지 확인할 수 있다.
모드설정변경
리눅스에서 모드설정이란 text모드 x-windows등등 이있는데 이기본모드를 수정할 때 사용한다.
먼저 #cat /etc/inittab : $more를 출력하면 리스트가 출력이 되는데...
출력에 보면 id (숫자):initdefault란곳에 숫자를 바꾸어주면 된다.
x-windows:5번
single :1번
text : 3번으로 구성이 되어있다.
특정그룹추가하기
일반계정을 그룹화하여 같은 폴더에서 관리하면 관리하기도 좋고 여러모로 편하다.
그러나 그룹추가는 추상적이기 때문에 폴더개념과는 다르다.
이점을 유의하기바란다. 그룹명을 지정해주고 그룹명과 같은 폴더를 만들어줄 때
비로서 그룹화 된다고 보면된다.
#groupadd (그룹명) :그룹은 만들어지었으나 폴더는 만들어지지않았다.
#mkdir 폴더(일반적으로 그룹명과 동일하면 좋다):그룹과 폴더가 모두만들어지었다
자 일반계정을 추가하여 방금만들어진 그룹에 추가하여보자
#useradd -D -b /home/wm:초기 디렉토리의 경로를 지정해준다.
#useradd -g wm wm01:-g는 그룹에 추가한다는 옵션명이고,wm은 그룹명이다
그리고 wm01은 일반계정자이다..즉 wm01은 wm에소속되도록 -g(그룹화)하여 준다는 뜻이다.
#passwd wm01 :이제 wm01의 패스워드를 추가하면 된다.
userdel(유저삭제명령)
일반계정을 추가하고 나면 나중에 삭제또한 하게 된다. 싶게 하위디렉토리까지 삭제하는법을 알아보자.
#userdel (지울계정명):이렇게 지정하면 모두삭제된다.
하위에 디렉토리가 없을 경우
#rm -rf 계정명:으로 깨끗이 삭제할 수가 있다.
usermod(일반생성 계정에 대한 편집명령),groupmod(그룹에 대한 편집명령)
적용예(uid,향,comment,home,shell)
#usermod -c bbb web02: (web02를 bbb로 바꾼다는 것이다. (단 폴더가 바뀌는 것이 아니라 .comment가 바뀐다는 것이다. 명령에 -c는 comment란 뜻이다.
확인할려면, vi /etc/passwd로 확인을 해보라....
#usermod -d /home/wm
#vi /etc/passwd
#usermod -n webm web:(web이란 그룹을 webm으로 변경하라...
#vi /etc/group:이곳으로 가면 바뀐내용을 확인할수 있다.
su명령의 아름다운반란(사용자 대체)
su란 여러 계정을 오고가며 작업을 하는 것이다.
리눅스의 묘미를 맛볼수 있는 것이기도 하다...또한 root가 어느정도로 막강한지를 쉽게 알수가 있다... 자 이제 실행하여보자
보통 터미널로 작업을 할때에는 root로 로그인이 불가능하는 하지만 su를 통해 가능하여진다 먼저 일반계정으로 접속을 하여 #su root로 변환하여주면 가능하다...
하지만 일반계정에서#su root를 실행하면 root의 패스워드를 묻게된다.패스를 모르면 끝장이다. 그냥 집에가야 될듯......흐흐흐
패스를알고있다면 입력. 성공메세지가 출력되고 root로 작업환경이 변환된다.
이번엔 root권한으로 일반계정으로 변환하여 작업을해보자
#su webm01이렇게 하면 패스워드를 묻지않고 바로작업에 들어갈수가 있다....요것이 root만의 권한.....
이번엔 일반계정에서 일반계정으로 변경작업하여보자
#su webm02라실행하면 역시 패스워드를 묻는다....모르면 찌그러지고 알면 들어가서 작업하면된다.
즉 정의하자면 root는 su명령을 통해 어떠 계정에도 접속하여 작업을 할수있으나 일반작업자의 경우 root로 작업을변환할 때 패스워드를 알아야 하며,역쉬 일반계정끼리의 작업또한 패스워드를 알아야 작업이 가능하다는 것이다. 이권한을 chmod로 뚫을수있을까...
에러발생시 대책법
윈도우즈의 경우 에러가 발생하면 강제종료를 시키면 scandisk가 바로잡아준다.
리눅스의 경우도 그러하지만 이건 바람직하지가 않다. 에러가 발생하면 나름대로 에러를
잡는 법을 알아보자.
먼저 에러가 발생을 하면 read읽기 기능만으로 자동으로 변환이 된다.
이를 바꾸기위해선 다음과 같은 명령을 수행하면 된다.
먼저 readolny가 나오면 이건 읽기기능만이 수행된다는 뜻이다.
lilo에서 ctrl+x로 text모드로 들어간다. 아이디와 패스를 입력하고
#mount -n -0 remount , rw(읽고쓰기로 변환한다는 뜻이다.) /dev/hda5(리눅스가 깔린장치명)입력하면된다.
초기부팅화면 설정변경
멀티부팅시 dos모드나 linux모드중 어느것을 먼저택할건지 지정해주는 것이다.
역시 명령어는 다음과 같다.
#cat /etc/lilo.conf 엔터를 치면 리스트출력 하면 수정부분이 눈에 들어온다.
단 cat명령어는 출력명령어 이므로 vi로 바꾸어 출력을 하면된다. 역시 수정하고 저장하고 나오면 된다.)
로그인 패스워드변경법
lilo화면에서 ctrl+x키로 누르면 된다.
먼저 linux 1이나 single로 입력을 한후
passwd를 입력한다...암호를 임의로지정을 하고 반복암포를 누르고 빠져나온다.
자한번 테스트해보자.
한템창에서의 멀티작업시 에러메세지....
통상적으로 리눅스에서는 여러개의 한텀창을 띄어놓고 작업을한다.
하지만 열어본작업을 닫지않고 다른창에서 또같은 작업을 병행하면 swap메모리를 먹기 때문에 좋지않다...또한 여러 가지 메시지를 동반하므로 귀찮기 짝이없다.
한번쯤 이런 경험을 해보셨을거라 믿는다.....
참고로 편집도중 ctrl+z를 사용하면 꼬옥 창이 닫힌것처럼 결과가 나오는데...
이건 창이 완전히 닫힌게 아니라 잠시 숨겨두는 것이다.
ctrl+z를 누른후 #jobs라 쳐보자 그러면 작업중인게 한 개가 있다는 메시지가 나온다.
완전히 해제시킬려면 #kill %1이라 치면 완전 종료된다.
아니면 첨부터 윈도창에서 닫임단추를 누르면 종료된다.
프로그래밍 :: 오라클 강좌 (0) | 2007.08.17 |
---|---|
Oracle 10g의 Recycle Bin의 기능에 대해서... (0) | 2007.08.17 |
4. Net8 클라이언트측의 기본적인 구성 (0) | 2007.05.07 |
3. Net8 서버측의 기본적인 구성 (0) | 2007.05.07 |
2. 기본적인 NET8 구조 (0) | 2007.05.07 |