블로그 이미지
Don't Stop
angelyr

Recent Post

Recent Comment

Archive

calendar

1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
  • total
  • today
  • yesterday

파일 스트림 열기 함수

 

fopen (String filename, String mode[bool])

 

 파일을 읽거나 쓰기를 할 경우 파일 경로와 스트림을 연결시키는 함수입니다. 전달인자인 mode값은 r은 읽기만, r+ = 읽기와 쓰기만, w은 쓰기만, w+는 읽기와 쓰기만 가능한 mode입니다. 만약 파일이 없는 경우 0을 리턴합니다.

 

$fileName = "경로";
$handle = fopen($filename, "r"); // 파일열기
$contents = fread($handle, filesize($fileName)); // 파일의 전체 내용 읽기
fclose($handle); // 파일 닫기

 

[버퍼를 이용하는 방법] 

while( !feof($handle) ) {
    $buffer = fgets($handle, 4096); // 엔터가 있는 곳까지 최대 4096byte를 읽어옵니다. 
    echo $buffer;  // 읽은 라인을 출력합니다. 
}

 

posted by angelyr

MySQL 테이블에 랜덤한 row를 가져오기 위해서 아래와 같은 질의문을 쓸 수 있습니다. 


1
SELECT name FROM random ORDER BY RAND() LIMIT 1;


하지만 row수가 몇만건이 되면 굉장히 느려지는 방법입니다. 왜냐하면 실제로 EXPLAIN으로 검사해 보면 type이 ALL이기 때문입니다. 전체 row를 스켄하는 방법으로 index보다도 못해서 굉장히 느려집니다. 정말 비추되는 방법이지요. 


그럼 아래처럼 생각할 수 있습니다. 


1
SELECT name FROM random WHERE id = (SELECT CEIL(RAND() * (SELECT MAX(id) FROM random));


이 코드도 문제입니다. EXPLAIN 검사해보면 type이 ALL입니다. 문제는 WHERE절 뒤에 id = (SELECT....)부분이죠. 


결국 최적화를 위해 JOIN을 사용할 수 있습니다. 


1
2
3
4
5
6
SELECT name FROM random JOIN
(SELECT CEIL(RAND() *
(SELECT MAX(id)
FROM random)) AS id
) AS r2
USING (id);


이걸 검사해보면 type이 system, const로 나옵니다. 이렇게 하면 JOIN하는 테이블은 상수(const) 임시테이블로서 나오기 때문에 1개의 row만 비교하는 형태가 되어 system이 되는 겁니다. 


단지 주의할 사항은 MAX(id)라는 것은 Count(*)와는 다르다는 점입니다. 만약 row가 중간에 삭제되는 경우가 아니라면 id가 PK라는 조건내에서 서로 같은 값이 되겠지만 삭제된다면 서로 다른 값입니다. 그뿐 아니라 삭제가 되면 아에 random row를 찾지 못하는 경우도 발생합니다.

posted by angelyr

php와 Javascript를 이용하여 XML 통신을 하는 법은 이미 많은 예시가 있다.
이 글은 공부목적으로 개인적으로 정리한 것이다.

Javascript에 있는 XHR(XMLHttpRequest)를 이용하여 php에서 XML을 동적으로 받는 프로그램을 간단하게 만들었다.

특별히 Javascript에서 XHR을 구현을 위해서는 각종 브라우져마다 다르게 만들어야하는 번거로움이 있어서 나는 prototype.js 라는 Javascript 프레임워크에서 제공하는 XHR 기능을 이용했다.


아주 쉬운 예제이기 때문에 자세한 설명은 생략한다.(사실 귀찮기 때문에.. ㅋ)

index.html (Language : html4strict)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=euc-kr">
<title>prototype을 이용한 Ajax 테스트</title>
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
    function request(group)
    {
        //alert(group);
        new Ajax.Request(
            "http://192.168.0.200/~jidolstar/testXML.php",
            {
                asynchronous:true,
                method:"get",
                parameters: {"group": group} ,
                onSuccess:function(request)
                {
                    var xmlData = request.responseXML;
                    var members = new Array();
                    var memberNude  = xmlData.getElementsByTagName("member");
                    var nameNode = xmlData.getElementsByTagName("name");
                    var companyNode = xmlData.getElementsByTagName("company");
                    var telnumNode = xmlData.getElementsByTagName("telnum");
                    var memberCount = memberNude.length;
                    for ( i=0; i < memberCount; i++ )
                    {
                        var name    = nameNode[i].childNodes[0].nodeValue;
                        var company = companyNode[i].childNodes[0].nodeValue;
                        var telnum  = telnumNode[i].childNodes[0].nodeValue;
                        members.push( {"name":name, "company":company, "telnum":telnum} );
                    }

                    var str="";
                    for ( i=0; i < members.length; i++ )
                    {
                        str += "<H1>member : " + (i+1) + "</H1>";
                        str += "<div>name : " + members[i].name + "</div>";
                        str += "<div>company : " + members[i].company + "</div>";
                        str += "<div>telnum : " + members[i].telnum + "</div>";
                    }
                    //document.getElementById["divResult").innerHTML = str;
                    $("divResult").innerHTML = str;

                       
                },
                onFailure:function()
                {
                    $("divResult").innerHTML = "실패";
                }
            });
    }

</script>
</head>
<body onload="request(document.frm.groupSelect.value)" >
    <form name="frm">
        <select name="groupSelect" onchange="request(document.frm.groupSelect.value)">
            <option value="1">1 Group</option>
            <option value="2">2 Group</option>
        </select>
    </form>
    <div id="divResult"></div>
</body>
</html>




 

textXML.php (Language : php)
<?php
$group = $_GET[group];
header("Content-type: text/xml;charset=utf-8");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");

echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>";

switch($group)
{
    case 1:
        $xml="<members>
                <member>
                    <name>지돌스타</name>
                    <company>wecon</company>
                    <telnum>010-2238-0321</telnum>
                </member>
                <member>
                    <name>mira</name>
                    <company>wecon2</company>
                    <telnum>010-2222-2333</telnum>
                    </member>
                <member>
                    <name>mira</name>
                    <company>wecon2</company>
                    <telnum>010-2222-2333</telnum>
                </member>
            </members>"
;
        break;


    case 2:
        $xml="<members>
                <member>
                    <name>mikoung</name>
                    <company>uranos</company>
                    <telnum>010-233-3333</telnum>
                </member>
                <member>
                    <name>uram</name>
                    <company>uranos2</company>
                    <telnum>010-1111-2323</telnum>
                    </member>
                <member>
                    <name>deokgon</name>
                    <company>uranos3</company>
                    <telnum>010-234-9999</telnum>
                </member>
            </members>"
;

        break;

    default:


        break;
}

echo iconv("CP949","UTF-8", $xml);
?>


PHP에서 inconv("CP949","UTF-8",$xml);은 한글을 UTF-8형태로 전송하기 위한 것이다. 서버에서 UTF-8을 지원하지 않는다면 이렇게 해야한다. 그래야 UTF-8로 보낼시 한글이 깨지지 않는다

posted by angelyr
  • 개행 문자 변환하기 : Unix는 \n이지만 윈도우는 \r\n이다. 간혹 윈도우에서 만든 문서를 읽다보면 각 줄의 마지막에 ^M이 표시돼서 읽기 불편할 때가 있다. 치환할 수도 있지만 아래와 같이 명령으로 처리할 수도 있다. :set ff=unix 
  • 파일 삽입 :r 파일명
  • 명령 실행 결과 삽입 :r! 명령어
  • 외부 text복사시 자동 들여쓰기에 의한 계단 현상 제거.
    set paste
  • 대소문자 변경
    1. 모든 문자를 대문자로 :%s/.*/U 1. 모든 문자를 소문자로 :%s/.*/L 1. 모든 단어의 첫번째 문자를 대문자로 :%s/\<./\u&/g
    2. 모든 단어의 첫번째 문자를 소문자로 :%s/\<./\l&/g
    3. 모든 줄의 첫번째 단어를 대문자로 :%s/.*/\u&
    4. 모든 줄의 첫번째 단어를 소문자로 :%s/.*/\l&

  • 소식

    단축키

    보낸 사람 Linux

    해야될 작업

    • vim7이 나왔음. 가능한 vim7의 변경된 점을 추가해 볼것
      • ex) split 단축키 지원 추가 : shift+p

    추가해야될 내용

    1. 같은 문자를 여러번 삽입
      1을 100번 연속 입력해야 하는 경우를 생각해보자. 에디터로 100번 입력하는거 생각보다 짜증날 것이다. 그렇다고 프로그램을 만드는건 더 시간 낭비다. 다음과 같은 방법을 이용해 보자.
      esc키를 눌러서 명령행 모드로 넘어간다.
      100을 입력한다.
      'i'를 입력해서 입력모드로 들어간다.
      반복할 문자인 1을 입력한다.
      esc키를 눌러서 다시 명령행 모드로 넘어간다.
      1초 정도 기달려보자.
      

     

    posted by angelyr

    1. 테이블 생성

      create table 테이블명 (필드명 1 타입, 필드명 2 타입, PRIMARY KEY(필드명);

     


      ex) create table khs_table(num int NOT NULL, name char(80), PRIMARY KEY(num));

        -> NOT NULL : NULL이 되면 안된다는 뜻, 항상 값을 입력해야 한다.

        -> PRIMARY KEY : 기본키, 테이블 내에서 중복되지 않는 값을 갖도록 지정하는 키 값.

                                  테이블에 저장된 레코드를 다른 레코드와 구별시켜주는 식별자 역활

     


    2. 테이블 목록 보기

      show tables;

     


    3. 테이블 구조 확인

      desc 테이블명;

     


    4. 테이블의 새 필드 추가

      alter table 테이블명 add 새 필드명 타입;

      ex) alter table khs_table add address char(80); //char타입의 address 라는 새로운 필드 생성

        또는 alter table khs_table add char(80) after address;

     


    5. 테이블의 필드 삭제

      alter table 테이블명 drop 삭제할 필드명1, 삭제할 필드명2;

      ex) alter table khs_table drop address;

     


    6. 테이블의 필드 수정

      alter table 테이블명 change 수정할 필드명 새로운 필드명 타입;

      ex) alter table khs_table change address juso char(80);

     


    7. 테이블의 필드 타입 수정

      alter table 테이블명 modify 필드명 새타입;

      ex) alter table khs_table modify address int;

     


    8. 테이블의 이름 변경하기

      alter table 테이블명 rename 새 테이블 명;

      ex) alter table khs_table rename khs_table1;

     


    9. 테이블 삭제하기

      drop table 삭제할 테이블명

      ex) drop table khs_table1;

     


    * varchar와 char의 차이점

     


      varchar는 지정한 바이트 안에서 쪼개서 레코드 값을 할당한다,

      char는 레코드 값마다 지정한 바이트만큼 할당해준다.

      ex) 레코드 값 3개 "안녕", "홍길동", "하이"

         varchar(80)의 경우 안녕=4바이트, 홍길동=6바이트, 하이=4바이트 할당

         총 4+6+4=14바이트 varchar(80)은 최대 80바이트

         char(80)의 경우 안녕=80바이트, 홍길동=80바이트, 하이=80바이트 할당

         * varchar(80)도 한 레코드값마다 최대 바이트 할당가능

     


      varchar는 메모리를 효율적으로 사용가능하나 데이터를 읽고 쓰는데 char보다 더 오래 걸린다.

     

    posted by angelyr

     




    1. Spring 2.5 버전을 다운로드
    현재 Spring 3.0 버전이 배포되고 있지만 JPetStore의 경우 2.5버전에만 있다. 다운로드 받을때는 2.5 최상위 버전을 다운로드 받되 뒤에 dependencies가 붙은 압축파일을 받도록 하자. 이 압축파일은 spring 2.5에 의존하는 lib나 예제들이 수록되어 있다. JPetStore 샘플도 여기에 있다.



    다운로드 받으러 가기 : http://www.springsource.com/download/community

    위 주소로 접속하면 첫화면에서 개인정보를 넣으라고 할것이다. 그냥 무시하고 download page 링크를 찾아 클릭하길 바란다. 다운로드를 완료하면 아무데나 압축을 풀면 되겠다.


    2. 배포파일(war) 만들기
    다운로드를 받아 samples/jpetstore 로 들어가면 아래와 같은 폴더 및 파일을 볼 수 있다.


    원래는 ANT를 설치한 상태에서 ANT 스크립트를 담은 build.xml 만을 이용해 내부에 있는 명령인 "clean", "build", "warfile" 명령들을 이용해 최종배포파일인 war파일을 만들 수 있다. 하지만 그렇게 하면 많은 부분 불편하므로 spring 배포자가 이와 더불어 warfile.bat와 build.bat를 추가해서 ANT 환경을 구축해야하는 번거로움을 없애줬다. warfile.bat만 더블클릭으로 실행하면 자동으로 war를 만들어준다.

    warfile.bat 구조은 다음과 같다.

    build.bat warfile


    이것은 위 build.bat를 실행하고 "warfile" ANT 스크립트 명령을 실행하는 것을 의미한다.

    build.bat 내용은 다음과 같다.

    "%JAVA_HOME%/bin/java" -cp ../../lib/ant/ant.jar;../../lib/ant/ant-launcher.jar;"%JAVA_HOME%/lib/tools.jar" org.apache.tools.ant.Main %1


    build.bat는 JDK 설치경로에 ANT관련 jar를 복사해서 ANT를 실행할 수 있도록 해주는 것이 주 목표인것이다. 마지막에 org.apache.tools.ant.Main %1은 1개의 parameter를 받아 실행하겠다는 의미이다. 결국 %1이 warfile.bat의 "warfile" 문자열로 대체되어 build.xml의 warfile명령을 실행하도록 하는 것을 의미한다.

    이제 warfile.bat만 두번 클릭해서 실행하면 된다. 혹시 제대로 실행이 되지 않을지도 모른다. 이것은 JDK 경로 설정이 잘못되었기 때문인데 build.bat에 자신의 JDK 경로를 아래와 같이 추가해보고 warfile.bat를 재실행해보길 바란다.

    set JAVA_HOME=C:\Program Files\Java\jdk1.6.0_18
    "%JAVA_HOME%/bin/java" -cp ../../lib/ant/ant.jar;../../lib/ant/ant-launcher.jar;"%JAVA_HOME%/lib/tools.jar" org.apache.tools.ant.Main %


    이제 %JAVA_HOME% 변수를 제대로 설정했기 때문에 이제 war파일을 제대로 만들 수 있게 된다.

    만약 모두 지우고 war를 새로 만들고 싶다면 warfile.bat에서 warfile을 all로 수정하자.

    build.bat all


    이 모든과정을 이해하기 위해 build.xml에 있는 ANT 스크립트를 한번 훑어보는 것을 추천한다.

    모든 과정을 마쳤다면 다음과 같이 .classes, dist 폴더가 추가되었을 것이다.


    dist 폴더로 들어가면 jpetstore.war가 있다. 또한 war/WEB-INF/lib가 생성되어 그안에 필요한 jar가 복사된 것도 확인하자.


    3. Eclipse에서 프로젝트 만들기

    2가지 방법중 하나만 사용하면 되겠다. 먼저 Eclipse를 실행하기 바란다.


    3.1. Web Project를 직접 만들기
    File > New > New Project로 들어가 아래처럼 Dynamic Web Project를 선택한뒤 Next 버튼을 누른다.



    Project name으로 jpetstore를 입력하고 Target runtime은 Tomcat 6.0을 선택하면 되겠다. Finish 버튼을 누른다.


    2번 항목에서 samples/jpetstore 폴더로 가서 src와 war 내에 있는 파일을 각각 복사해 Eclipse내에 생성된 src와 WebContent 폴더에 파일을 복사한다.



    3.2 war파일을 이용해서 프로젝트 만들기

    이것은 3.1 방법외에 또 다른 방법이다.

    2번 항목에서 samples/jpetstore/dist 폴더가 생성되었고 그 안에 jpetstore.war 를 생성했었다. 이것을 이용해 프로젝트를 생성한다. 이클립스에서 File > Import 를 들어가 아래처럼 WAR file을 선택한다.


    아래 그림처럼 WAR file 경로(samples/jpetstore/dist)를 찾아 jpetstore.war를 선택하고 web project 이름과 target runtime을 설정한다. Finish 버튼을 누른다.


    이렇게 프로젝트를 생성하면 src에는 아무것도 없다. 이 상태에서 실행해도 되지만 실제로 우리는 이클립스라는 개발툴을 활용하고 있으므로 java소스도 가져와야겠다. 그러므로 samples/jpetstore/src 에 있는 내용을 프로젝트의 src에 복사하도록 하자. Project Explorer에는 다음처럼 보여야 하겠다.



    4. 실행해보기
    3번 항목으로부터 만들어진 프로젝트는 이제 테스트해볼 수 있는 준비가 마련되었다.

    이클립스에서 Window > Show View > Other 를 선택하면 아래와 같은 창이 나오고 거기서 Server를 선택한다.


    이클립스 View 창에 아래처럼 Servers가 추가되어 있는 것을 확인할 수 있을 것이다. 테스트할 서버를 추가하자. 먼저 빈공간에 오른쪽 버튼을 눌러 New>Server를 선택한다.


    아래와 같은 창이 나오면 Tomcat v6.0 Server를 선택한다.(필자는 Tomcat 6.0이 이미 설치되어 있으므로...) Next를 누른다.


    다음과 같은 창이 나오면 우리가 만든 jpetstore 프로젝트가 왼쪽에 나오는데 이것을 선택한뒤 Add> 버튼을 눌러 Configured 부분에 추가한다. 이로써 우리 프로젝트는 Tomcat 서버위에서 하나의 웹애플리케이션으로 동작할 수 있게 된다. Finish 버튼을 누른다.


    만들어진 서버에 jpetstore가 올라가 있음을 아래처럼 Servers View에서 확인할 수 있다. 이제 아래 그림처럼 실행버튼을 눌러 서버를 실행한다. 단, Tomcat 서버가 이미 실행되고 있으면 중지시킨뒤 해야하겠다.


    참고로 필자는 서버 설정시 Ports를 80으로 지정한뒤 실행했다.



    http://localhost/jpetstore 를 웹브라우저 주소창에 넣으면 아래와 같은 화면을 볼 수 있겠다. 만약 Ports가 8080이면 http://localhost:8080/jpetstore로 접속하자. 내용을 보면 이 jpetstore 애플리케이션은 Spring과 iBatis로 만들어졌음을 보여주고 있다. Enter the Store 버튼을 누르면 실제 Store로 입장할 수 있게 된다.



    5. 데이타베이스(MySQL)과 연동
    아직 설정이 완료된 것은 아니다. 데이타 베이스 설정이 남아 있기 때문이다. JPetStore의 이곳저곳 들어가보면 MySQL 접속문제로 에러가 발생하는 것을 알 수 있을 것이다.

    Spring Framework는 데이터베이스와의 연동을 위한 ORM(Object-Relation Mapping)을 지원하여 iBatis, Hibernate, JPA와 같은 영속성 프레임워크와 연동을 지원한다. 본 JPetStore는 그중에 iBatis를 이용하게 된다. 근간으로는 모두 JDBC와 같은 추상층을 사용하기 때문에 DB종류에 상관없이 간단한 프로퍼티 설정만으로 DB접속이 가능하며 JPetStore 예제는 hsqldb, mysql, oracle, postgres로 테스트 할 수 있도록 하고 있다.

    필자는 많은 DB중에 MySQL 환경이 이미 구축되어 있으므로 이것을 사용하도록 하겠다. 다른 DB도 거의 비슷하므로 따로 설명은 필요 없겠다.


    5.1 JDBC MySQL 드라이버 설치

    MySQL 데이타베이스에 접근하기 위해 JDBC 드라이버를 다운로드 받아 프로젝트내에 포함시켜야 한다. 먼저 아래 링크에서 다운로드 받자.

    http://dev.mysql.com/downloads/connector/j/

    압축을 푼 뒤, mysql_connector_java 로 시작하는 jar 파일이 존재할 것이다. 이것은 프로젝트 내에 WebContent/WEB-INF/lib에 복사한다. 여기서 lib는 JPetStore를 동작시키기 위한 프레임워크 및 라이브러리 jar가 포함되어 있다. Spring, iBatis도 있는 것을 확인하자.



    5.2 MySQL 계정정보 설정
    프로젝트내 WebContent/WEB-INF/jdbc.properties 는 JDBC 접속정보를 설정할 수 있도록 되어 있다.

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/jpetstore
    jdbc.username=jidolstar
    jdbc.password=mypassword


    위와 같은 설정은 5.1 항목에서 추가한 mysql driver에서 제공하는 MySQL 드라이버 클래스 사용한다는 것을 지정하고 있다. 또한 url, username, password를 설정하고 있다. 3306는 데이타 베이스 접속하기 위한 기본 포트번호 이며 그 뒤에 붙은 jpetstore는 접속할 DB 명이다. 그러므로 이들 정보는 필요에 따라서 수정해서 사용하면 되겠다.

    5.3 MySQL DB를 만들고 테이블 생성
    다운로드 받은 Spring Framework 폴더에 samples/jpetstore/db에 들어가면 총 4가지 자동 테이블 생성 코드가 있다. 여기서 mysql 폴더에 sql문이 존재한다.


    먼저 MySQL에 "jpetstore" 이름을 가진 DB를 먼저 만든다.  jpetstore-mysql-schema.sql 을 열어보면 use jpetstore 부분이 맨 처음에 있다. 만약 DB 이름이 다른 이름을 가진다면 jpetstore 대신 다른 이름을 넣으면 되겠다. 그런 다음 위 두개의 sql 파일을 이용해 콘솔창에서 다음과 같이 해당 DB에 테이블과 데이터를 넣을 수 있다.

    > mysql -uroot -p < jpetstore-mysql-schema.sql
    Enter password: ***********
    > mysql -uroot -p < jpetstore-mysql-dataload.sql
    Enter password: ***********


    물론 MySQL을 위한 클라이언트 애플리케이션(SQLGate나 SQLyog등)을 사용해도 되겠다.

    이제 JPetStore는 모든 페이지에서 제대로 동작하게 될 것이다. 이를 이용해 Spring과 iBatis에 대해 공부하면 되겠다.

    참고글

     

    posted by angelyr