아래글은 http://www.idhacker96.pe.kr/tc/27 의 글을 가져왔습니다.

개인적으로 우분투 시스템에서는 gzip을 사용하여 압축을하고, 윈도우 시스템에서는 zip을 사용하여 압축을 한다. 문제는 우분투와 윈도우에서 압축한 파일을 상호 호환성 문제로 잘 풀리지 않을때가 있다.

우분투에서 압축한 파일인 *.tar.gz 파일을 윈도우에서 풀려고하면, 두번 압축을 풀어야하고, 윈도우에서 압축한 zip 파일을 우분투에서 압축을 해제하면, 한글 파일명이 깨져 출력된다.

7z 압축은 우분투와 윈도우에서도 압축을하면 한글이 깨지지 않는다는 장점과 압축 효율이 높다고 외국에서는 많이 사용한다고 들었다. 그러나 습관이 이미 들어서 인지 압축파일을 만들때만다 7z으로 만들지는 않는다.

우분투에 7z 패키지 설치

sudo apt-get install p7zip

7z에 대한 자세한 사항은 'man 7zr'을 통해서 확인할 수 있다.

7z으로 압축

7zr a 파일명.7z [대상]
ex) 7zr a filename.7z files/

7z으로 압축해제

7zr x filename.7z


'프로그래밍 > 리눅스' 카테고리의 다른 글

리눅스에서 7z 압축과 해제하기  (2) 2012.11.05
[리눅스] IP 설정 변경 하기  (0) 2009.09.04
  1. lunettes ray ban 2013.07.28 17:35

    눈을 감아봐 입가에 미소가 떠오르면 네가 사랑하는 그 사람이 널 사랑하고 있는거야.

  2. 2017.11.13 14:58

    비밀댓글입니다

공자(孔子, 기원전 551년~기원전 479년)는 유교의 시조(始祖)로 떠받들어지는 중국사상가이다. 이름은 구(丘), 자는 중니(仲尼). 공자의 자(子)는 경칭으로 '선생'이라는 뜻이 된다. < 출처 : 위키백과 - 공자 >

[공자(孔子) 명언]
- 지금과 시대적 가차관이 다른 말들이 있지만, 여전히 주옥같은 말들이 많이 있다.
  한번쯤 자신에 대해서 다시 생각해 보게 하는 말들이다.


가까이 있는 사람을 기쁘게 하고 멀리서 사람이 찾아오게 하라. -공자


가 지를 잘 쳐주고 받침대로 받쳐 준 나무는 곧게 잘 자라지만, 내버려 둔 나무는 아무렇게나 자란다. 사람도 이와 마찬가지여서 남이 자신의 잘못을 지적해 주는 말을 잘 듣고 고치는 사람은 그만큼 발전한다. -공자


군자가 이웃을 가려서 사는 것은 환난을 막기 위함이다. -공자


군자는 도(道)를 근심하고 가난을 근심하지 않는다. -공자


군 자는 말에는 더디지만, 일을 함에는 민첩하다. -공자


군자는 말을 잘하는 사람의 말에만 귀를 기울이지 않고 말이 서툰 사람의 말에도 귀담아 듣는다. -공자


군자는 말이 행함보다 앞서는 것을 부끄러워한다. -공자


군 자는 모든 것을 공경하나 신체의 공경함을 가장 으뜸으로 생각한다. 신체란 부모의 가지이니 어찌 공경하지 아니하랴? 그 몸을 공경하지 못하면 이는 곧 부모를 상하게 함이며, 부모를 상하게 함은 뿌리를 상하게 함이니, 그 뿌리가 상하면 가지도 따라서 망하게 된다. -공자


군자는 세 가지 경계할 바가 있다. 젊었을 때는 혈기가 잡히지 않았기에 여색을 경계하고, 장년이 되면 혈기가 바야흐로 굳세므로 다투는 것을 경계하고, 늙으면 혈기가 이미 쇠하였음으로 탐욕을 경계하라. -공자


군 자는 스스로 재능이 없음을 근심하며, 남이 알아주지 않음을 근심하지 않는다. -공자


군자는 타인의 좋은 점을 말하고 악한 점을 말하지 않는다. 반대로 소인은 타인의 좋은 점은 말하지 않고 악한 점만 말한다. -공자


군 자는 행위로써 말하고 소인은 혀로써 말한다. -공자


군자에게 용맹만 있고, 예가 없으면 세상을 어지럽게 한다. 소인에게 용맹만 있고, 예가 없으면 도둑이 된다. -공자


그 지위에 있지 않으면 그 정사(政事)를 논하지 말아라. -공자


길은 가까운 데에 있다. 그런데도 이것을 먼 데서 구한다. -공자


나 는 하루에 세 번 나 자신을 반성해 본다. 남을 위해 충을 다했는가, 친구와 사귀어 신(信)을 지켰는가, 배운 것을 남에게 전했는가 하고. -공자


나라를 다스리려면 식량을 충분하게 마련하고 무기를 충분히 마련하여 국민들이 위정자를 믿게 하여야 한다. 무엇보다도 국민들이 위정자를 믿지 않으면 정치를 해나갈 수 없다. -공자


나라의 질서가 바로잡혀 있을 때에는 돈이나 지위가 없다는 것이 부끄러운 일이 된다. 그러나 나라가 어지러울 때는 돈이 있고 지위가 높다는 것이 수치이다. -공자


나무가 먹줄을 좇으면 곧아지고, 사람이 충간(忠諫)함을 받아들이면 거룩해진다. -공자


나 쁜 일을 하여 하늘에서 죄를 받으면 빌 곳이 없다. -공자


남들이 듣기 싫은 성난 말을 하지 말라. 남도 그렇게 너에게 대답할 것이다. 악이 가면 화가 돌아오니 욕설이 가고 오고 매질이 오고 간다. -공자


남에게 듣기 싫은 성난 말을 하지 말라. 남도 그렇게 너에게 대답할 것이다. 악이 가면 화가 돌아오니 욕설이 가고 주먹이 오간다. -공자


남의 충고를 달갑게 받아들여라. 그러나 윗사람이나 친구간에 너무 자주 충고나 간언(諫言)을 하지는 말라. -공자


내 가르침은 간단하고 그 의미를 쉽게 터득할 수 있다. 자기 자신처럼 이웃을 사랑하라는 것이 그 전부이다. -공자


내가 원하지 않는 바를 남에게 행하지 말라. -공자


내 자신을 심하게 탓하고 남을 가볍게 책망하면, 원망을 멀리하게 된다. -공자


널리 배워서 뜻을 도탑게 하며, 간절하게 묻되 가까운 것부터 잘 생각하면 인(仁)이 그 속에 있다. -공자


높은 낭떠러지를 보지 않고서야 어찌 굴러 떨어지는 근심을 알고, 깊은 연못에 가지 않고서 어찌 빠져 죽는 근심을 알겠느냐? 큰 바다를 보지 않고서야 어찌 빠져 죽는 근심을 알겠느냐? 큰 바다를 보지 않고서야 어찌 풍파에 시달리는 근심을 알겠느냐? -공자


늙은 사람들은 편하게 모시고, 친구들은 진실한 마음으로 대하고, 젊은이는 부드럽게 대하게나. -공자


다른 사람을 대할 때 그 사람의 몸도 내 몸같이 소중히 여기라. 내 몸만 귀한 것이 아니다. 남의 몸도 소중하다는 것을 잊지 말라. 그리고 네가 다른 사람에게 바라는 일을 네가 먼저 그에게 베풀어라. -공자


다름 아닌 자신에게 전력을 다하고 충실하라. 자기를 내버려두고 남의 일에 정신이 팔려 있는 사람은 자신의 갈 길을 잃어버린 사람이다. -공자


다음의 네 가지를 두려워해야 한다. 첫째, 도의에서 벗어나는 것. 둘째, 학문을 게을리하는 것. 셋째, 정의를 듣고도 실행치 못하는 것. 넷째, 착하지 않음을 고치지 못하는 것. 이를 항상 두려워하고, 그렇지 않았을 때는 즉각 반성하고 고쳐야 한다. -공자


단 단한 돌이나 쇠는 높은 곳에서 떨어지면 깨지기 쉽다. 그러나 물은 아무리 높은 곳에서 떨어져도 깨지는 법이 없다. 물은 모든 것에 대해서 부드럽고 연한 까닭이다. 저 골짜기에 흐르는 물을 보라 그의 앞에 있는 모든 장애물에 대해서 스스로 굽히고 적응함으로써 줄기차게 흘러, 드디어는 바다에 이른다. 적응하는 힘이 자제로와야 사람도 그가 부닥친 운명에 굳센 것이다. -공자


당 신이 알고 있을 때는 똑똑히 알고 있다고 말하고 잘 모르고 있을 때는 솔직하게 모른다고 시인하는 것이 바로 참된 지식이다. -공자


대중의 소리를 막는 것은 강을 막는 것보다 어렵다. -공자


덕이 높은 사람은 외롭지 않다, 반드시 그를 따르는 이웃이 있기 때문이다. -공자


덕이 있으면 외롭지 않고 반드시 이웃이 있다. -공자


말하고자 하는 바를 먼저 실행하라. 그런 다음 말하라. -공자


맑은 거울은 형상을 살피게 하고, 지나간 옛일은 이제 되어질 일을 알게 한다. -공자


모든 것이 참되면 그것이 밖으로 나타나기 마련이다. -공자


모든 사람이 그를 좋아하더라도 반드시 살피고, 모든 사람이 그를 미워하더라도 반드시 살펴야 한다. -공자


모욕은 잊어버리고, 친절은 결코 잊지 말아라. -공자


무례 한 사람의 행위는 내 행실을 바로 잡게 해주는 스승이다. -공자


물이 너무 맑으면 고기가 없고, 사람이 너무 살피면 벗이 없다. -공자가어(孔子家語)


물처럼 스며드는 중상과 피부에 느껴지는 모략이 통하지 않는다면 가히 총명한 사람이라 할 수 있다. -공자


사는 것도 모르거늘 어찌 죽음을 알겠는가. -공자


사 람들이 알아주지 않아도 원망하지 않는 것은 또한 군자답지 아니한가. -공자


사람은 서로의 입장과 처지를 바꿔 생각해야 한다. -공자


사람은 어질더라도 배우지 않으면 현명해지지 못한다. -공자


사 람이 돈 있고 지위를 얻었을 때는 품격을 지키기는 쉽다. 불우하고 역경에 처했을 때, 그 품격이 시들지 않고 보전되어 있는 사람이 참된 품격의 사람이다. 그러므로 불행한 환경에 처했을 때일수록 처신을 잘해야 한다. -공자


사람이 큰 도덕의 영역에서 벗어나는 일은 없을지 모르지만, 작은 도덕의 영역에서 벗어나는 일은 꽤 많다. -공자


서로 위하는 마음. 네 스스로 원하지 않는 것을 다른 사람에게 행해서는 안 된다. -공자


썩은 나무에는 조각을 할 수 없고, 썩은 흙으로 쌓은 담은 흙손질을 할 수가 없다. -공자


선비가 도에 뜻을 두고서 나쁜 옷과 나쁜 음식을 부끄러워한다면 그런 사람과는 더불어 의논할 수가 없다. -공자


선을 보거든 아직도 부족한 것같이 하고, 악을 보거든 끓는 물을 만지는 것처럼 하라. -공자


선한 일을 하는 사람에게는 하늘이 복으로써 갚고, 악한 일을 하는 사람에게는 하늘이 화로써 갚는다. -공자


세 가지 길에 의하여 우리는 진리에 도달할 수가 있다. 그 하나는 사색에 의해서이다. 이것은 가장 높은 길이다. 둘째는 모방에 의해서이다. 이것은 가장 쉬운 길이다. 그리고 셋째는 경험에 의해서이다. 이것은 가장 고통스러운 길이다. -공자


세 사람과 같이 있을 때 그 중 두 사람은 나의 스승으로 삼을 수 있다. 한 사람이 좋은 말과 행동을 한다면 그것을 배울 것이고, 다른 한 사람의 말과 행동이 옳지 못하다면 그렇게 하지 않으려고 거울로 삼을 것이다. -공자


세 사람이 걸어가면, 반드시 나의 스승이 있다. -공자


순전(純全)한 완벽은 오직 신에게만 발견된다. 우리들의 삶이란 사실 신께 가까이 가는 과정으로 완성되는 것이다. 좋은 것이 좋은 것이며 악한 것이 악한 것이라는 사실을 아는 순간, 인간은 좋은 것에 가까이 간 것이며 그만큼 악에서 멀어지는 것이다. -공자


시를 읽음으로써 바른 마음이 일어나고, 예의를 지킴으로써 몸을 세우며, 음악을 들음으로써 인격을 완성하게 된다. -공자


신용을 잃어버리면 설 땅이 없게 된다. -공자


실 수하여 고치지 않으면, 곧 그것을 실수하고 만다. 실수하여 고치는 것을 꺼리지 말라. -공자


자기 반성을 엄중히 하고, 다른 사람을 꾸짖는 일을 가볍게 하면 남의 원망이 멀어진다. -공자


자기 자신을 존중함과 같이 남을 존중하자. 남이 자기 자신에게 해주기를 원하는 바 그것을 남에게 해줄 수 있는 사람은 진정한 사랑을 아는 사람이다. 이 세상에 그 이상 가치있는 것은 없다. 이것이 처세하는 최상의 비법인 것이다. -공자


자신의 가난함을 부끄럽게 여기는 일이야말로 정말 수치스러운 일이다. 오직 부끄러워 할 일은 가난을 극복하려고 노력하지 않는 일이다. -공자


자 연을 먼저 터득한 사람은 성인이다. -공자


작은 일을 참지 못하는 사람은 큰일에 낭패하고 만다. -공자


잘 못을 저지르고도 고치지 않는 것, 이를 잘못이라 이른다. -공자


젊은 시절은 일년으로 치면 봄이요, 하루로 치면 아침이다. 그러나 봄엔 꽃이 만발하고, 눈과 귀에 유혹이 많다. 눈과 귀가 향락을 쫓아가느냐, 부지런히 땅을 가느냐에 그 해의 운명이 결정된다. -공자


정치의 으뜸가는 요체는 국민의 신망을 얻는 것이다. -공자


죽 고 사는 것은 명(命)에 있고, 부(富)하고 귀하게 되는 것은 하늘에 있다. -공자


중용의 덕은 지극한 것이다. -공자


즐거워하되 즐거움에 빠지지 않고, 슬퍼하되 상심하진 말라. -공자


지혜 를 얻는 데는 세 가지 방법이 있다. 첫 번째 방법은 사색에 의한 것으로, 가장 고상한 방법이다. 두 번째는 모방으로 가장 쉬우나 만족스럽지 못한 방법이다. 세 번째는 경험을 통해 얻는 방법으로 가장 어려운 것이다. -공자


진실과 신의를 지키고 정의를 향하여 나아가는 것이 덕을 높이는 길이다. 세상 사람들은 사랑하면 그가 살기를 원하고, 미우면 그가 죽기를 원한다. 도대체 남이 살기를 원하고 또 죽기를 바라는 것은 모순이 아니고 무엇인가. 덕 있는 사람은 이런 모순을 범하지 않는다. 군자의 덕은 바람이요, 소인의 덕은 풀이다. 풀은 바람이 불면 반드시 바람에 쏠려 따르게 마련이다. 군자의 덕을 본받자. -공자


진 실은 모든 존재의 근원이며 종말이다. -공자


진짜 결점은 자신의 결점을 알면서도 고치려고 노력하지 않는 것이다. -공자


집안에 예절이 있으므로 어른과 아이의 분별이 있고, 규문(閨門)에 예가 있으므로 삼족(三族)이 화목하다. 조정에 예가 있으므로 삼족이 화목하다. 조정에 예가 있으므로 벼슬에 차례가 있고, 사냥에도 예가 있으므로 융사(戎士, 병사)가 숙련되고, 군대에 예가 있으므로 무공(武功)이 이루어진다. -공자


착한 사람과 함께 있으면 마치 지란(芝蘭)의 방에 들어간 것 같아서 오래 되면 그 향기를 느끼지 못하니 더불어 그에게 동화된 것이다. 착하지 않은 사람과 함께 있으면 마치 절인 생선가게에 들어간 듯하여 오래 되면 그 냄새를 느끼지 못하니 ? 피? 더불어 동화된 것이다. 단(丹)을 지니면 붉어지고, 칠을 지니면 검어지니 군자는 반드시 자기와 함께 있는 자를 삼가야 한다. -공자


착한 일을 하는 자에게는 하늘이 복으로 갚고, 악한 일을 하는 자에게는 하늘이 재앙으로 갚는다. -공자


천자가 참으면 나라에 해가 없고, 제후가 참으면 큰 일을 이루고, 관리가 참으면 승진하고, 형제가 참으면 집안이 부귀하고, 부부가 참으면 일생을 해로하고, 친구끼리 참으면 이름이 깎이지 않고, 자신이 참으면 재앙이 없어진다. -공자


첫째, 젊을 때에는 혈기가 안정되니 못한 지라 색(色)을 경계해야 한다. 둘째, 장년에 이르면 바야흐로 혈기가 강한 지라 투쟁을 경계해야 한다. 셋째, 노년에 이르면 혈기가 이미 쇠한 지라 탐욕을 경계해야 한다. 이 세 가지를 경계하며 살아가는 것이 가장 손쉽고 성공적인 처세의 지름길이다. -공자


총명하고 생각이 뛰어나도 어리석은 듯함으로 지켜야 하고, 공덕이 천하를 덮더라도 겸양하는 마음으로 지켜야 한다. 용맹이 세상을 진동하더라도 겁내는 듯함으로 지켜 나가며, 부유함이 사해(四海)를 차지했다 하더라도 겸손함으로써 지켜야 한다. -공자


큰 도가 행해지면 사람은 자기 부모만을 부모로 생각하지 않고, 자기 자식만을 자식으로 생각하지 않는다. -공자


평소에 공손하고, 일을 하는데 신중하고, 사람을 대하는데 진실하라. 그러면 비록 오랑캐 땅에 간다 할지라도 버림받지 않을 것이다. -공자


하나님은 존경하되 멀리하라. 그것이 백성의 바른 길이다. -공자


하늘에 죄를 지으면 용서를 빌 곳이 없다. -공자


하늘은 말하지 않는다. 사시가 운행되고 만물이 잘 자라고 있는데 하늘이 무엇을 말하랴. -공자


하늘의 이치를 따르는 자는 살고, 하늘의 이치를 거역하는 자는 망한다. -공자


학 문을 아는 자는 이를 좋아하는 사람만 못하고 학문을 좋아하는 자는 이를 즐기는 자만 못하다. -공자


학문을 좋아하는 자와 함께 가면 마치 안개 속을 가는 것과 같아서, 비록 옷은 젖지 않더라도 때때로 물기가 배어든다. 무식
한 자와 함께 가면 마치 뒷간에 앉은 것 같아서, 비록 옷은 더럽혀지지 않지만 그 냄새가 맡아진다. -공자가어(孔子家語)


한 말은 반드시 실행에 옮기고 실행하면 반드시 성과를 거두라. -공자


항상 겸손하라. 겸양과 친절은 곧 예의 기본이다. -공자


현명한 사람은 모든 것을 자신의 내부에서 찾고, 어리석은 사람은 모든 것을 타인들 속에서 찾는다. -공자


화살이 과녁을 벗어나면 훌륭한 사수는 다른 사람에게 핑계를 돌리지 않고 자신의 솜씨를 탓한다. 현명한 사람도 이와 같이 행동한다. -공자


효자의 어버이 섬김은 살아서는 공경을 다하고, 봉양함에는 즐거움을 다하고, 병드신 때에는 근심을 다하고, 돌아가신 때는 슬픔을 다하고, 제사 지낼 때엔 엄숙함을 다해야 한다. -공자


'나의 생각' 카테고리의 다른 글

[공자 명언 모음]  (1) 2010.06.17
  1. planchas ghd 2013.07.27 07:15

    귀를 기울여봐 가슴이 뛰는 소리가 들리면 네가 사랑하는 그 사람 널 사랑하고 있는거야.


출처 그대 강철빤쓰를 믿는가!!  ̄▽ ̄)乃 낄낄~ | 강철빤쓰
원문 http://blog.naver.com/bagagy/60032111167

1. 들어 가는 말

    지난 호에서는 MySQL을 이용하여 간단하게나마 슈퍼 마켓에서 매출을 관리하는 예를 들어 SQL 언어에 대해서 간단히 살펴 보았다.
    기본적인 SQL 언어만 알아도 MySQL의 Client 프로그램을 이용하여 Data들을 관리할 수 있다. 하지만, SQL 언어를 모르거나 컴퓨터를 잘 다루지 못하는 사람들은 Database를 어떻게 쓸 수 있을까. 우리네 슈퍼마켓 아저씨들 중에서 SQL 언어를 사용해서 매출을 관리할 수 있을 아저씨들이 얼마나 있을까.

    이번 호에서는 MySQL의 C API에 대해서 알아본다. MySQL의 C API를 이용하면 C나 C++로 짠 프로그램에서 MySQL 서버에 접속을 할 수 있다. (우리네 슈퍼마켓 아저씨는 어려운 SQL 언어를 배울 필요가 없다. 슈퍼마켓 아저씨를 낮춰보는 것이 아니므로 항의하는 일이 없었으면 한다.)

    MySQL과 연동하는 방법은 C API만이 전부는 아니고, PHP3, Perl, MyODBC, JDBC를 이용하여 연동을 할 수 있다. 이번 회에서는 C API에 대해서 알아보도록 하고, 다음 회에서 PHP3와 MySQL을 이용하여 Web과 연동하는 법에 대해 알아 보도록 한다.

 

2. 프로그램 컴파일

    C API를 소개하기 전에 일단 gcc의 옵션을 잘 모르는 독자를 위해 MySQL의 C API를 이용한 소스 코드를 컴파일하는 방법에 대해서 알아 본다.
    먼저 다음의 예제를 보자.

      #include <stdio.h>
      #include <mysql.h>
      #include <errno.h>

      void main(void)
      { MYSQL mysql ;
              
      mysql_init(&mysql) ;

      if(!mysql_real_connect(&mysql, NULL, “사용자이름”,”암호”, NULL ,3306, (char *)NULL, 0))
      {printf(“%s\n”,mysql_error(&mysql));
      exit(1) ;}
      printf(“성공적으로 연결되었습니다.\n”) ;
      mysql_close(&mysql) ;}

    위의 예제는 MySQL 서버에 접속을 하여, 연결이 제대로 되었을 경우 ‘성공적으로 연결되었습니다.’라는 메시지를 출력하고 종료하는 프로그램이다. 연결이 안 될 경우 왜 연결이 안 되는지 출력을 하게 된다. 에러가 나면 글의 후반부에 있는 ‘문제 해결’ 부분을 읽어 보길 바란다. 일단 위에 나온 함수들의 설명은 뒤에 하고 컴파일을 하는 방법에 대해 알아 보자.
    위의 소스 코드가 con.c라고 가정을 한다면 다음과 같이 프롬프트에서 명령을 내리면 된다.

      $ gcc -o con con.c -I/usr/local/include/mysql
      -L/usr/local/lib/mysql -lmysqlclient

    이렇게 하면 con이라는 실행 파일이 생기게 된다. -I 옵션은 헤더 파일의 경로를 정한다.
    즉, mysql.h의 경로를 지정해 주며, 필자의 경우 그 경로가/usr/local/include/mysql이다. 각자 경로가 틀리므로 자신에게 맞게 변경을 하자. 보통 /usr/include/mysql 혹은/usr/local/include/mysql 혹은 /usr/include에 존재한다. /usr/include에 있을 경우에는 이 옵션을 주지 않아도 된다.
    -l 옵션은 링킹시 사용할 라이브러리를 지정한다.
    MySQL의 C API를 사용했을 경우에는 꼭 -lmysqlclient라는 옵션을 주어야 한다.

    -L/usr/local/lib/mysql 옵션은 mysqlclient라는 라이브러리의 경로를 지정한다. 이 옵션도 사용자에 따라 다르다. MySQL의 설치 시에 어디에 라이브러리를 설치했는지 확인하자. 지정된 디렉터리 밑에서 libmysqlclient.so 라는 라이브러리를 볼 수 있다.
    옵션과 경로를 잘 지정해 주었다면 위의 소스 코드는 잘 컴파일 되고, 실행시에 MySQL 데몬이 실행 중이라면 ‘성공적으로 연결되었습니다.’라는 메시지를 볼 수 있을 것이다.

 

3. C API 자료형

    C API에서 쓰이는 자료형에 대해서 알아 보자.
    MYSQL : Database와의 연결을 관리하는 구조체이다. 대부분의 C API 함수에서 쓰인다.
    MYSQL_RES : SELECT 등 결과를 리턴하는 query의 결과를 나타내는 자료형이다.
    MYSQL_ROW : MYSQL_RES에서 하나의 레코드씩 값을 얻어 올때 쓰이는 자료형이다.
    MYSQL_FIELD : 필드의 이름과 필드의 타입 등 필드에 관한 정보를 저장하는 자료형이다.

 

4. MySQL Database에 연결하기

    이제 모든 준비를 마췄으므로 본격적으로 MySQL C API에 대해서 알아보자.

    * MYSQL* mysql_init(MYSQL *mysql)
    mysql_real_connect()를 위하여 MYSQL 객체를 초기화한다. 특별히 하는 일은 없으나 MYSQL 객체를 초기화 하므로 mysql_real_connect() 전에 꼭 호출하여 주자.

    * MYSQL* mysql_real_connect(MYSQL* mysql, const char* host, const char* user,
    const char* passwd, const char* db, uint port, const char* unix_socket, uint client_flag)
    host에 지정된 서버로 연결을 시도하는 함수이다.
    mysql_get_client_info() 함수를 제외한 모든 API 함수를 사용하기 전에 꼭 호출하여야 하는 함수이다.
    각 인자에 대한 설명은 다음과 같다.

    mysql    : MYSQL 변수에 대한 포인터 형이다.
    host      : 연결하고자 하는 서버의 IP Address 혹은 도메인 이름을 적어주면 된다.
                  NULL로 적어주면 localhost를 의미한다.
    user      : 접속시의 사용자 이름이다. NULL이면 현재 login한 user ID가 된다.
    passwd : user의 암호를 나타낸다. NULL이면 암호가 없다는 의미이다.
    db        : 접속시에 사용하고자 하는 database를 나타낸다. NULL로 지정을 하면 연결 후에
                  mysql_select_db() 혹은 mysql_query()를 이용해서 지정할 수 있고,
                  database를 바꿀 수도 있다.
    port       : TCP/IP 연결시에 사용할 포트 번호를 나타낸다.
    unix_socket : 보통 NULL로 하면된다.
    client_flag   : 이 인자도 보통 0으로 해주면 된다.
    mysql_real_connect()는 성공적으로 연결이 되면, MYSQL 포인터를 넘겨주고 연결에 실패하였을 경우 NULL을 리턴한다.
    연결에 실패 하였을 경우 이 글이 마지막에 있는 ‘문제 해결’부분을 읽어 보길 바란다. 사용 예는 위의 예제에 나와있다.

    * void mysql_close(MYSQL* mysql)
    서버와의 연결을 끊고 mysql에 할당되었던 메모리를 해제한다.

 

5. Query와 결과 값을 얻어 오기

    서버와 성공적으로 연결이 되었다면, 이제 원하는 Query를 하고, 그 결과 값을 얻어 올 수 있다. Query를 할 수 있는 함수는 mysql_query()와 mysql_real query() 두 가지가 있다.

    * int mysql_query(MYSQL* mysql, const char* query) :
    query를 실행 시킨다. mysql 클라이언트에서 했던 것 처럼 query의 끝에 ‘;’가 포함되어서는 안 된다. query의 끝은 NULL 문자(‘\0’)이다. 따라서 바이너리 데이타가 섞인 query는 수행을 할 수 없다. 바이너리 데이타가 섞은 query의 중간에는 NULL 문자가 올 수도 있기 때문이다. query를 성공적으로 마췄다면 0을 리턴한다.

    * int mysql_real_query(MYSQL* mysql, const char* query, unsigned int length) :
    mysql_query()는 query의 끝을 NULL 문자로 구분을 하는데 반해, mysql_real_query는 query의 끝을 length 만큼의 길이로 구분한다. 따라서 NULL 문자를 포함한 바이너리 데이타가 있는 query도 수행을 할 수 있다. 또한mysql_query()는내부적으로strlen()를 사용하지만, mysql_real_query()는 그렇지 않으므로 좀더 빠르다. 마찬가지로 query를 성공적으로 수행하였을 경우 0을 리턴한다.
    위의 함수를 이용하여 query를 수행할 수가 있다. 호출하는 방법은 매우 간단하다.

    mysql_query(&mysql, “SELECT * FROM dome”) ;
    위와 같이 query를 수행하면 된다.
    query를 성공적으로 수행했다면, 이제 결과 값을 얻어 와야 한다.

    * MYSQL_RES* mysql_store_result(MYSQL* mysql)
    * MYSQL_RES* mysql_use_result(MYSQL* mysql)
    위 두 함수는 모두 서버로부터 결과 값을 얻어 오는데, 차이는 query의 결과로 리턴되는 ROW들을 한꺼번에 모두 서버로부터 얻어 올 것인지(mysql_store_result()), 혹은 한번에 한 개의 ROW를 얻어 올 것(mysql_use_result())의 차이이다.
    mysql_store_result()는 ROW들을 한 꺼번에 모두 얻어와 클라이언트의 메모리에 저장을 한다. 따라서 매번 ROW를 얻어 오기 위해 서버에 접근을 할 필요가 없으므로 속도가 빠르다. 대신 결과로 넘어온 ROW의 크기가 클 경우 많은 메모리가 필요하게 된다.
    또 mysql_store_result()의 장점은 mysql_data_seek()나 mysql_row_seek()를 이용하여 현재 ROW에서 앞이나 뒤의 ROW로 자유자재로 왔다 갔다 할 수 있다는 것이다. 또한, mysql_num_rows()를 이용하여, 몇 개의 ROW가 리턴됐는지도 알 수 있다.

    반면 mysql_use_result()는 한 번에 한 개의 ROW를 서버로부터 가져 온다. 따라서 메모리를 많이 사용하지 않는다. 하지만, mysql_store_result()와 같은 장점을 가지 지 않는다. 리턴되는 ROW가 특별히 크지 않은 경우라면, 보통 mysql_store_result()를 호출하는 것이 좋다.

    결과 값을 얻어 왔다면 mysql_fetch_row()를 이용하여 각각의 row에 있는 데이타 들에 접근을 할 수 있다.

    MYSQL_ROW mysql_fetch_row(MYSQL_ROW* result)
    result에 있는 ROW들에서 한 개의 ROW를 얻어 온다. 한 개의 ROW에서 각각의 field는 배열 형태로 들어 있다. 더 이상 가져올 ROW가 없으면 NULL을 리턴한다.
    현재의 result에 몇 개의 field가 있는지 mysql_num_fields()를 이용하여 알 수 있다.

    int mysql_num_fields(MYSQL_RES* result)

    이제 실제로 query를 수행하고, 결과를 출력하여 보자.

      1:      #include <stdio.h>
      2:      #include <mysql.h>
      3:      #include <errno.h>
      4:
      5:      void main(void)
      6:      {
      7:      MYSQL           mysql ;
      8:      MYSQL_RES*      res ;   
      9:      MYSQL_ROW       row ;
      10:     int             fields ;
      11:             
      12:     mysql_init(&mysql) ;
      13:     
      14:     if(!mysql_real_connect(&mysql, NULL, “사용자”,”암호”, “test”, 3306, (char *)NULL, 0))
      15:     {
      16:     printf(“%s\n”,mysql_error(&mysql));
      17:                       exit(1) ;
      18:             }
      19:     
      20:     if(mysql_query(&mysql, “USE super”) )
               // mysql_query()는 query 수행시에 에러가 나게 되면
               // 0이 아닌 값을 리턴한다.
      {
      printf(“%s\n”, mysql_error(&mysql) ;
                              exit(1) ;
                        }
      21:     if(mysql_query(&mysql, “SELECT * FROM dome”) )
      {
      printf(“%s\n”, mysql_error(&mysql) ;
                              exit(1) ;
                                          }
      22:     
      23:     res = mysql_store_result( &mysql ) ;
      24:     fields = mysql_num_fields(res) ;
      25:     
      26:     while( ( row = mysql_fetch_row( res ) ))
      27:             {
      28:     for( cnt = 0 ; cnt < fields ; ++cnt)
      29:     printf(“%12s “, row[cnt]) ;
      30:
      31:     printf(“\n”) ;
      32:             }
      33:
      34:       mysql_free_result( res ) ;
      35:     mysql_close(&mysql) ;
      36:     }

    12번 줄은 mysql_init()을 이용하여 MYSQL 객체를 초기화 하는 과정이다.
    14번 줄은 실제 MySQL 서버와 연결을 시도하는 부분이다. 연결에 실패하였을 경우 NULL을 리턴하므로 15-18번 줄에서, 에러 메시지를 출력하고 프로그램을 종료한다.
    20번 줄은 “use super”라는 query를 이용하여 ‘super’ database를 사용하도록 지정하는 부분이다. 사용하고자 하는 database는 mysql_real_connect()에서 지정을 할 수도 있고, 프로그램 실행 중에 바꾸고자 할 때는 “use DB이름”과 같은query를 이용할 수도 있고, 혹은 mysql_select_db()를 이용할 수도 있다.
    21번 줄은 “SELECT * FROM dome” query를 수행하는 부분이다. dome 테이블의 모든 컬럼을 리턴하도록 하였다.
    23번 줄은 mysql_store_result()를 이용하여 결과 값을 저장하는 부분이다.
    24번 줄은 mysql_num_fields()를 이용하여 현재 결과 값에 몇 개의 필드가 있는지 알아 내는 부분이다.
    mysql_fetch_row()는 배열 형태로 각 필드에 접근을 하므로 배열의 인덱스를 알아내야 정확히 데이타들을 얻어 올 수 있다.

    26-32번 줄은 실제로 각 ROW들로부터 데이타에 접근하는 부분이다.
    mysql_fetch_row()를 이용하여 각각의 ROW를 얻어 온다(더이상 가져올 ROW가 없으면 NULL을 리턴한다.) 그 후 for문을 이용하여 ROW의 각각 필드를 출력하였다.
    34-35번 줄은 res와 mysql에 할당된 메모리를 해제하는 부분이다. 하지만, query에 따라서는 ROW를 리턴하지 않는 query도 있다(UPDATE나 DELETE등) 만약 위의 예제에서 사용자가 UPDATE 등을 수행하였다면, 곧바로 Segmentation Fault가 나버린다.
    이때는 mysql_num_fields()를 이용하여, 필드의 개수를 조사함으로써 문제를 해결할 수 있다. query가 ROW를 리턴하였다면, 필드는 최소한 0보다 크기 때문이다. 다음의 예제를 보자(참고로 밑의 예제는 MySQL Manual 19장에서 발췌한 내용이다.)

      MYSQL_RES*      result ;
      unsigned        int num_fields ;
      unsigned        int num_rows ;

      if(     mysql_query(&mysql, query_string) )
      {
      // mysql_query는 성공적으로
      // 수행할 경우 0을 리턴하므로
      // 이 부분이 실행 된다면
      // 에러가 있다는 의미이다.
      // 적절한 에러 핸들링을 해주다.
      }
      else // 성공적으로 query가 수행되었다.
      {
      result = mysql_store_result( &mysql ) ;
      if( result ) // 리턴된 ROW가 있다 !
      {
      num_fields = mysql_num_fields( result ) ;
      // row의 값을 얻어오는 루틴을 집어 넣으면 된다.
      // 마지막에는 mysql_free_result()를 이용하여
      // 메모리를 해제시키자.
      }
      else // 리턴된 ROW가 없다. ROW를 리턴하지 않는 query를 수행하였는지 // 혹은 query의 수행 중에 에러나 났는지 알 수 없다.
      {
      if( mysql_num_fields( &mysql ) == 0)
      {
      // ROW를 리턴하지 않는 query를 수행하였다.
      num_rows = mysql_affected_rows( &mysql ) ;
      // mysql_affected_rows()는 DELETE 등의
      // query에서 몇 개의 ROW가 영향을 받았는지
      // 리턴하는 함수이다.

      }
      else // 무언가 잘못된 것이 있다.
      fprintf(“stderr,Error : %s\n”,mysql_error( &mysql) ) ;
      // mysql_error()는 가장 최근의 에러를 리턴하는 함수이다.
      }
      }
      위의 예제를 이용하여, 결과를 리턴하는 query 든지(SELECT), 아니면 결과를 리턴하지 않는 query 든지(UPDATE, DELECT 등) 어떠한 query라도 수행을 성공적으로 할 수 있다.

    이번에는 ROW의 필드에 대한 정보를 얻어 오는 방법에 대해서 알아 보자. MYSQL_FIELD라는 구조체가 쓰이는데 MYSQL_FIELD에는 다음과 같은 멤버들이 있다.

    char* name  : 필드의 이름을 나타낸다.
    char* table : 현재 필드의 테이블 이름을 나타낸다.
    char* def   : 필드의 기본값을 나타낸다.

    MYSQL_FIELD* mysql_fetch_field( MYSQL_RES* result )
    : 한번에 하나의 MYSQL_FIELD를 리턴한다.
    MYSQL_FIELD* mysql_fetch_fields(MYSQL_RES* result )
    : 배열의 형태로 모든 MYSQL_FIELD를 리턴한다.

      예1)
      MYSQL_FIELD *field ;
      while( (field = mysql_fetch_field(result) )
      printf(“field name %s\n”, field -> name ) ;

      예2)
      unsigned int num_fields ;
      unsigned int i ;
      MYSQL_FIELD* fields ;
      num_fields = mysql_num_fields( result ) ;
      fields = mysql_fetch_fields( result ) ;
      for( i = 0 ; i < num_fields ; ++i)
      printf(“field name %s\n”, fields[i].name) ;

    위의 두 개의 예는 모두 동일안 결과를 출력한다.

 

6. 문제 해결

    이번에는 C API를 사용한 소스 코드를 컴파일할 때 혹은, 실행 도중 만나는 문제점을 해결할 수 있는 방법을 설명한다.

      1) “con.c:2: mysql.h: 그런 파일이나 디렉토리가 없음”
         이 경우는 mysql.h의 경로를 찾을 수 없어서 나는 에러이다. 다시 한번

         mysql.h가  어디에 있는지 확인을 하고, -I옵션으로 그 경로를 지정해 주자.

         -I옵션과 경로는 붙여 써야 한다.

      2) “con.o(.text+0x11): undefined reference to `mysql_init’”  위와 같이
          ‘undefined reference......’ 라고 나오는 에러는 -lmysqlclient 옵션을 주지 않았

          기 때문이다.

      3) “ld: cannot open -lmysqlclient: 그런 파일이나 디렉토리가 없음” 위의 에러는
          -L옵션 뒤에 붙은 라이브러리의 경로가 잘못 되었기 때문이다.
            libmysqlclient.so 파일의 경로를 찾아서 그 경로로 지정을 해 주자.
          -I 옵션과 마찬가지로 -L과 경로는 붙여 써야 한다. 위의 에러들은 컴파일시

            에 옵션이 잘못되었을 경우 나오는 에러 메시지이다.
            계속해서 프로그램의 실행 중에 나오는 에러 메시지를 보자.

      4) “Can’t connect to local MySQL server (2)”
          위의 에러는 MySQL의 서버에 연결을 할 수 없다는 메시지로서, MySQL 서

          버의 데몬이 실행 중이지 않을 때 나오는 메시지이다.
          safe_mysqld 명령 등을 이용하여 데몬을 실행시켜 주자.

      5) “Access denied for user: ‘rot@localhost’ (Using password: YES)”
          접근이 금지되었다는 메시지로서 사용자 아이디를 잘못 입력하였 거나, 혹

          은 암호를 잘못 입력하였을 때 나오는 메시지이다.
          MySQL의 사용자는 모두 mysql database의 user 테이블에 있으므로, 참고를

          하여 적도록 하자.

      6) “error in loading shared libraries libmysqlclient.so.6:
          cannot open shared object file: No such file or directory”
          MySQL의 라이브러리를 열지 못한다는 메시지이다. 컴파일 할 때 MySQL의

          동적 라이브러리를 사용하느데, 동적 라이브러리이므로 실행시에도 라이브

          러리가 필요하게 된다.
          libmysqlclient.so가 /usr/lib 혹은 /usr/lib/mysql 디렉터리에 존재하지 않을

          경우에 발생하는 문제이다. 가장 간단한 해결법으로는 모든 MySQL 라이브

          러리를 /usr/lib/나 /usr/local/lib밑으로 복사하는 것인데 별로 추천하는

          방법은 아니다.
          두 가지 방법이 있는데,
          먼저 시스템의 운영자라면, /etc/ld.so.conf 파일에libmysqlclient.so가있는 경

         로를 적어 준 후에 ldconfig 라는 명령을 프롬프트에서 실행하여 주면 된다.

         이러한 권한이 없는 일반 사용자라면, 자신의 쉘의 환경 변수를 이용하면 된

         다.
          각자의 쉘이 맞게, LD_LIBRARY_PATH를 libmysqlclient.so가 있는 디렉터리로
          지정을 해주자.
          C 쉘 사용자는  setenv LD_LIBRARY_PATH  경로명 본 쉘 사용자는
          export LD_LIBRARY_PATH  경로명 이렇게 해주면 된다.
          보통 위의 6개의 에러가 가장 많이 발생한다. 혹시, 해결하지 못할 에러가 있

          다면 필자에게 메일을 보내면 친절히 답변해 주겠다.

 

7. Quick Reference

    위에서 설명한 API만을 가지고도 서버에 연결하여, Query를 수행하고 그 결과를 확인 할 수 있다. 이번에는 C API의 중요한 함수들을 모아서, 함수의 프로토타입과 함수의 기능들에 대해서 간단히 알아도록 하자. 개인적으로 그다지 중요하지 않다고 생각되는 함수들은 제외시켰으므로 모든 C API를 보고 싶은 독자들은 MySQL Reference Manual의 19장을 보기 바란다. 참고로 필자가 참조한 메뉴얼은 MySQL 3.22.21용 메뉴얼이었다.

      1) my_ulonglong mysql_affected_rows(MYSQL* mysql) INSERT, UPDATE, 

          DELETE 등의 query로 영향을 받은 ROW의 수를 리턴한다.

      2) void mysql_close(MYSQL* mysql) 서버와의 연결을 종료한다.

      3) void mysql_data_seek(MYSQL_RES* result, unsigned int offset) result에서 임

          의의 ROW에 접근을 하도록 하는 함수이다.
          offset이 row의 번호를 나타낸다. 0이면 처음 ROW,  mysql_num_rows( result )

          - 1 은 마지막 row를 나타낸다.

      4) unsigned int mysql_errno(MYSQL* mysql) 가장 최근에 mysql에 일어난 에러

          의 번호를 리턴한다.

      5) char* mysql_error(MYSQL* mysql) 가장 최근에 일어난 에러 메시지를 리턴

          한다.

      6) MYSQL_FIELD*mysql_fetch_field(MYSQL_RES* result)한번 호출할 때마다 하

          나의 필드에 대한 정보를 리턴한다.

      7) MYSQL_FIELDS*mysql_fetch_fields(MYSQL_RES* result) 배열형대로 result

          의 필드에 대한 정보를 한꺼번에 리턴한다.

      8) MYSQL_FIELD_OFFSETmysql_field_seek(MYSQL* mysql,     MYSQL_FIELD_OFFSET offset)임의의 필드에 접근을 하도록 한다.

      9) MYSQL_FIELD_OFFSETmysql_field_tell(MYSQL_RES* result)현재 필드의

          offset을 리턴한다.

      10) void mysql_free_result(MYSQL_RES* result) result에 할당된 메모리를 해제

           한다.

      11) MYSQL* mysql_init(MYSQL* mysql) mysql 객체를 초기화한다.
            인자가 NULL이면 새로운 MYSQL 객체를 생성하고, 초기화하여 리턴한다.

      12) MYSQL_RES* mysql_list_dbs(MYSQL* mysql, const char* wild)
            현재 서버에 있는 데이타베이스의 목록을 리턴한다. wild는 MySQL에서 사

           용할 수 있는 정규식을 나타낸다.     
           result = mysql_list_dbs( &mysql,”%” )는 모든 데이터베이스를 리턴하는 예이

           다. (%는 ‘모든’을 나타낸다)

      13) MYSQL_RES* mysql_list_tables(MYSQL* mysql, const char* wild)
            현재 데이타베이스에 있는 테이블들의 목록을 리턴한다.

      14) unsigned int mysql_num_fields(MYSQL_RES*result) 혹은
            unsigned int mysql_num_fields(MYSQL* mysql)필드의 수를 리턴한다.

      15) my_ulonglong mysql_num_rows(MYSQL_RES* result) result에 총 몇 개의

           ROW가 있는지 리턴한다. query 수행 후 mysql_store_result()를 호출하였을

           경우에만 사용 할 수 있고, mysql_use_result()는 사용할 수 없다.

      16) int mysql_ping(MYSQL* mysql) 서버에 연결 중인지를 리턴한다. 연결이 끊

           어 졌을  경우, 다시 연결을 시도한다. 서버와 연결을 한 후, 오랫동안 가만

           히 있으면 서버가 연결을 끊어버리는데, 이런 경우에 사용한다.

      17) int mysql_query(MYSQL* mysql, const char* query) query가 포인트 하는 쿼

           리를 수행한다. query의 끝은 NULL 문자이다. 성공적으로 query를 수행하였

           으면 0을 리턴한다.

      18) MYSQL* mysql_real_connect(MYSQL* mysql, const char* host,
            const char* user, const char* passwd, const char* db, uint port,
            const char* unix_socket, unit client_flag ) host와의 연결을 시도한다.
            인자별로 자세한 설명은 윗 부분에 되어 있다.

      19) int mysql_real_query(MYSQL* mysql, const char* query,
            unsigned int length)mysql_query()처럼 query를 수행하나, query의 끝이

            legnth인 것이 다르다.

      20) MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES* result)현재 ROW의 

           offset을 리턴한다.

      21) int mysql_select_db(MYSQL* mysql, const char* db)사용하고자 하는

           database 를 변경한다.
           mysql_query()를 이용하여 “use db이름”의 query를  수행해도 같은 결과를 
           얻는다.

      22) int mysql_shutdown(MYSQL* mysql) 서버를 종료시킨다.
            현재 사용자에게 shutdown 권한이 있어야 한다.

      23) MYSQL_RES* mysql_store_result(MYSQL* mysql) query의 수행결과를 서버

           로 부터 한 번에 모두 받아 온다.

      24) MYSQL_RES* mysql_use_result(MYSQL* mysql) query의 수행결과를 서버

           로부터 한 개의 ROW 씩 받아 온다.

      [출처] [본문스크랩] MYSQL C API|작성자 JS

'프로그래밍' 카테고리의 다른 글

MYSQL C API  (0) 2009.12.02
[데이터베이스] 윈도우에서 mysql에 접근하여 사용하는법  (0) 2009.12.02

+ Recent posts