이놈의 귀차니즘 때문에 @.@ 글을.. 쓰고 싶은데 쏘스가 주어지고 해야될일이 생기니 에휴 ~~ 이놈의 핑계~ 어째던 이번에 알아볼 것은 db에 접속 하는것을 알아 보겠다. 그것도 동일한 sql문에 param 값을 설정 하여서 한개의 sql문으로 처리 하는 방법을 해보는 것이다.


자바 소스
import java.sql.*;
public class CallableTest {
 public static void main(String[] args) throws SQLException{
  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/mysql", "root", "apmsetup");
 
  PreparedStatement stmt;
 
  String sqlStr = "select * from db where id=?";
 
  stmt = conn.prepareStatement(sqlStr);
 
  stmt.setInt(1, 10);
 
  ResultSet rs = stmt.executeQuery();
 
  while(rs.next())
  {
   System.out.println(rs.getString(1));
  }
 
  stmt.close();
  conn.close();
 }
}



 

그리고 C# 소스
using System;
using System.Data;
using System.Data.SqlClient;

class SqlParamTest
{
    static void Main(string[] args)
    {
        string connStr = "Provider=MySQLProv;Data Source=mysql;" +
                         "Location=localhost;User Id=root;Password=apmsetup";
        string query = "select * from db where id=@ID";
        SqlConnection conn = new SqlConnection(connStr);
        conn.Open();
        SqlCommand comm = new SqlCommand(query, conn);
        comm.Parameters.Add("@ID", SqlDbType.Int);
        comm.Parameters["@ID"].Value = "10";
        SqlDataReader sr = comm.ExecuteReader();
        while (sr.Read())
        {
            Console.WriteLine(sr.GetInt32(0)));
        }
        sr.Close();
        conn.Close();
    }
}



위의 코드는 솔직히 실행해보지는 못했다. 일단 실행을 할려면 MySql 설치해야 하고, 공급자도 설치해야 하고.. 아마도 자바와 닷넷용 모두 설치해야 할것이다. 그렇다고 MSSql을 설치하기도 그렇고. 그러니 이해해 주시기를 바랍니다 ^^

어째던 DB 접속에 둘다 문제가 없다면 두개의 소스가 비슷한 동작을 할것이다. 일단 둘다 각각의 Connection 객체를 통해 일단 DB에 접속 했다. 그런데 여기서 약간의 차이점은 자바에서는 DBManager 를 사용하여 객체를 생성하고, C#에서는 객체 스스로 생성되었다. 그래서 그런지는 모르겠지만 C#으로는 Connection 객체를 open을 해주는데 자바에서는 해주지 않는다.

그리고 다음은 비슷한 동작을 하는 command == statement 이두 객체가 비슷한 동작을 한다. 커넥션 객체에서 각 쿼리를 실행 하기 위한 Sql명령을 가지고 있는 객체이다. 여기서 바뀌게 되는 파라 미터 값을 command 에서는 @param 으로 구분했고 statement 에서는 ?로 구분했다. 그리고 자바에서는 preparedstatement라는 객체를 따로 만들어야 했으나, C#에서는 command라는 객체의 다른 종류는 없었다.

그리고 데이터를 읽는 것은 각각의 Reader로 읽어 값을 읽었고, 마지막으로 각 파라미터에 값을 넣을때 Java에서는 셋팅을 할때 메서드를 호출에서 ? 순서에 따라 각각의 값을 지정하였고, C#에서는 각 파라미터의 @param를 가지고 셋팅후 값을 대입 2번의 수행을 하였다.

뭐 두개다 큰 차이는 없겠지만 자바에서는 param 들이 ?로 표시되어 각각을 지정하는데 유연함이 조금 떨어질수 있겠지만, C#에서는 2번 셋팅을 해주어야 해서 불편하다는 점이 내가 내린 결론!!



에구에구 오랜만에 쓰는데 왜이리 피곤한지.. 그리고 자바에서는 또 특이하게 callablestatement라는 놈이 있다. 이놈은 preparedstatement라는 놈과는 비슷하지만 다른부분이 있다. 좀더 알아보고 기회가 된다면 다름 글에 이야기 해보겠다.

흔히 쓰는 메모장 프로그램을 쓸때 쉽게 파일을 열수 있는 방법으로 빈 메모장 프로그램을 하나 실행시킨후 파일 탐색기에서 파일을 드래그 앤 드롭 하면 파일이 열리게 되고 텍스트 파일이나 기타 다른 파일들이 열리게 된다. 비단 메모장 프로그램 뿐만 아니라 한글이나 그림판 MS워드 등등등.. 수많은 프로그램들이 이런 기능들을 지원하게 된다. 그래서 한번 해보았다.

User inserted image
User inserted image


























다음과 같이 폼한개와 텍스트 박스 하나를 놓았다. 그 후 텍스트 박스의 AllowDrop 의 속성을 True로 바꾸어 주었다.



그리고 다음과 같은 소스를 이벤트를 추가하면 파일을 저장 할수 있다.

private void textBox1_DragDrop(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        string[] file = (string[])e.Data.GetData(DataFormats.FileDrop);
        foreach (string str in file)
        {
            this.textBox1.Text += str + "\r" + "\n";
        }
    }
}
private void textBox1_DragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(DataFormats.FileDrop))
    {
        e.Effect = DragDropEffects.Copy | DragDropEffects.Scroll;
    }
}


다음과 같이 수정한 다음 파일을 드래그 해서 텍스트 파일 위에 올려 놓으면 파일명을 넘겨 받게 된다.

서버에서 TCP를 이용하여 파일을 하나 지정 받아서 대기 하고 있는다. 그런후 클라이언트에서 접속을 하게 되면 그 파일을 전송 받고, 클라이언트 프로그램에서는 파일을 받아 기록하게되는 간단한 소스 이다.

using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
public class FileServer
{
private FileStream file;
private NetworkStream ns;
private IPAddress ipAddress;
private TcpListener listener;
private Thread sender;
private TcpClient client = null;
private long sendSize = 0;
public FileServer(string f)
{
 this.file = File.OpenRead(f);
 this.ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
 this.listener = new TcpListener(ipAddress,3000);
 
 listener.Start();
 sender = new Thread(new ThreadStart(this.Acceping));
 Console.WriteLine("서버 실행중...");
 sender.Start();
}
~FileServer()
{
 file.Close();
}
public void Acceping()
{
 while(true)
 {
  client = listener.AcceptTcpClient();
  Console.WriteLine("클라이언트 접속");
  ns = client.GetStream();
  this.Send();
  ns.Close();
  client.Close();
 }
}
public void Send()
{
 byte[] b = new byte[1024];
 int count = 0;
 while( (count = this.file.Read(b,0,b.Length)) > 0 )
 {
  this.ns.Write(b,0,b.Length);
  this.sendSize += count;
 }
 Console.WriteLine("데이터 전송 완료");
}
public static void Main(string [] args)
{
 if( args.Length != 1)
 {
  Console.WriteLine("Usang args : AppName <fileName>");
  return;
 }
 if(!File.Exists(args[0]))
 {
  Console.WriteLine("File Access Error");
  return;
 }
 FileServer fServer = new FileServer(args[0]);
}
}


위의 코드를 실행 컴파일 시킨후 실행 시키게 된다. 그리고 다음은 클라이언트 소스 프로그램이다.

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
public class Client
{
private TcpClient client;
private NetworkStream ns;
private FileStream fs;
private Thread receive;
public Client(string ipAddress)
{
 this.client = new TcpClient(ipAddress,3000);
 this.ns = client.GetStream();
 this.fs = new FileStream("get.dat" , FileMode.Create);
 receive = new Thread(new ThreadStart(this.Receive));
 receive.Start();
}
public void Receive()
{
 int count = 0;
 byte[] b = new byte[1024];
 while( (count = ns.Read(b,0,b.Length))>0)
 {
  fs.Write(b,0,b.Length);
 }
 Console.WriteLine("파일전송완료");
}
~Client()
{
 fs.Close();
 ns.Close();
 client.Close();
}
public static void Main(string[] args)
{
 Client cl = new Client(args[0]);
}
}

C# 2007/01/13 13:11

파일 카피 프로그램..

바이너리 형태로 파일을 읽어 들여 복사하는 프로그램이다. 카피 할때 스레드를 이용해서 복사를 하였고, 닷넷에서 지원해 주는 카피 매서드는 이용하지 않고 구현해 보았다.

using System;
using System.IO;
using System.Text;
using System.Threading;
public class BCopy
{
private string originalFile;
private string copyFile;
private FileStream rs = null;
private FileStream ws = null;
private long fileSize = 0;
public BCopy(string ofile,string cfile)
{
 this.originalFile = ofile;
 this.copyFile = cfile;
 try
 {
  this.rs = File.OpenRead(this.originalFile);
  this.ws = new FileStream(this.copyFile,FileMode.Create);
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
}
~BCopy()
{
 rs.Close();
 ws.Close();
}
public void Copy()
{
 try
 {
  byte[] b = new byte[1024];
  int count = 0;
  while( (count = rs.Read(b,0,b.Length)) > 0)
  {
   ws.Write(b,0,count);
   this.fileSize += count;
  }
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
 finally
 {
  Console.WriteLine("File size : " + this.fileSize);
 }
}
public static void Main(string[] args)
{
 if( args.Length != 2)
 {
  Console.WriteLine("Usang Args : app <orginal Filename> <copy Filename>");
  return;
 }
 try
 {
  BCopy fileCopy = new BCopy(args[0],args[1]);
  Thread copyThread = new Thread(new ThreadStart(fileCopy.Copy));
  copyThread.Start();
 }
 catch (Exception e)
 {
  Console.WriteLine(e.Message);
 }
}
}



솔직히 별로 한것은 없고 읽은것을 쓰는데 하는것을 좀 오래 찾았아 ㅡ.ㅡ;

C# 2006/12/26 13:21

인덱서(Indexer)

인덱서
  • 클래스의 객체나 구조체의 변수를 배열형식으로 이용할 수있게 해주는 기법.

그 구조는 속성과 유사하며 속성처럼 get 및 set 접근자를 사용한다. 그리고 객체 index인자를 가지며, 객체의 이름 자체를 배열로 이용하기 때문에 this 키워드가 인텍서의 이름으로 사용된다.

사용예~


using System;
using System.Collections;
class SimpleIndexer
{
ArrayList lname = new ArrayList();
public object this[int index]
{
get
{
  if(index > -1 & index<lname.Count)
   return lname[index];
  else
   return null;
}
set
{
  if(index>-1 & index<lname.Count)
   lname[index] = value;
  else if(index == lname.Count)
   lname.Add(value);
  else
   Console.WriteLine("sid[" + index + "] : 입력 범위 초과 에러!!");
}
}
}
class IndexerTest
{
public static void Main()
{
SimpleIndexer sid = new SimpleIndexer();
sid[0] = "hong";
sid[1] = "kim";
sid[2] = "sug";
Console.WriteLine(sid[0]);
Console.WriteLine(sid[1]);
Console.WriteLine(sid[2]);
sid[10] = "park";
}
}
 

C# 2006/12/20 15:13

unsafe와 fixed

unsafe 키워드를 알아 보자

일반적으로 C#에서는 CLR이라는 놈이 메모리를 관리 해주기 때문에 메모리에 신경을 별로 쓰지 않아도 알아서 다 해준다. 그렇기 때문에 포인터 처리 차체를 기본적으로 처리 하지 않느다. 그래서 일반적인 C의 * 요놈이나 & 요놈이 처리 되지 않는다. 그런데 그렇다고 포인터 연산을 사용할수 없지는 않는단다.(전혀 몰라던 사실 ㅜㅜ)
CLR이 메모리를 관리 해주면 안전하지만 사람이 관리 하면 불안전해서 붙여진 이름인가 보다 unsafe 라는 키워드 이 키워드를 사용하면 C의 포인터를 처리 할수 있다.


using System;
class UnsafeTest2
{
unsafe static void Swap(int *x,int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
public static void Main()
{
int x = 10;
int y = 20;
Console.WriteLine("Swap Before x:{0} y:{1}",x,y);
unsafe
{
  Swap(&x,&y);
}
Console.WriteLine("Swap After x:{0} y:{1}",x,y);
}
}
 

csc /unsafe UnsafeTest.cs

UnsafeTest
Swap Before x:10 y:20
Swap After x:20 y:10


위의 소스를 보게 되면 unsafe로 선언된 함수나 구역에서는 포인터 처리를 할 수 있다. 음. 여태껏 몰랐던 사실이다. 그리고 컴파일 할 때는 옵션으로 /unsafe 라는 옵션을 넣어 주어야 한다. 그렇지 않으면 Error가 난다.

다음으로 fixed이다. 일단 이 fixed란 놈은 unsafe코드 영역 내부에서 사용되어 진다. 그런데 어떨때 사용되나? 이 fixed라는 놈은 포인터의 값으로 배열이나 혹은 클래스의 멤버를 넘겨 줄수도 있을 것이다. 그런데 일반적인 unsafe문 안에서라도 클래스의 주소를 바로 넘겨 버리면 값을 넘겨주지 못한다. 이런 황당 씨츄에이션이 ㅡ.ㅡ; 어째던 배열이나 클래스 멤버의 주소를 넘겨 줄려면 fixed를 사용해서 값을 넘겨 준다.


using System;
class Point
{
public int x,y;
}
class FixedTest2
{
unsafe static void DoubleSum(int *p)
{
 int a = *p;
 *p = a+a;
}
unsafe static void Main()
{
 Point pt = new Point();
 pt.x = 5;
 pt.y = 6;
 fixed(int *p = &pt.x)
 {
  DoubleSum(p);
 }
 Console.WriteLine("{0} {1}",pt.x,pt.y);
}
}
 



위와 같이 클래스의 멤버 변수 x를 접근 할려고 할때 fixed를 사용하게 된다. 그런데 fixed를 사용하지 않고
DoubleSum(&pt.x); 라고 바로 값을 넘겨 줄 경우

csc /unsafe FixedTest2.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.42 for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727 Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.

FixedTest2.cs(21,13): error CS0212: 고정되지 않은 식의 주소는 fixed 문의
       이니셜라이저를 통해서만 가져올 수 있습니다.



위와 같은 에러가 나게 된다. 아마도 CLR이 접근 구성하느 배열 혹은 클래스의 메모리를 C의 스타일대로 접근하려 할때 사용되는 것을 알게 되었다.

constreadonly는 둘다 상수를 선언하기 위해서 사용된다. 그러나 이 둘에는 약간의 차이가 있다. 이 차이점을 알아 보자.

const는 선언과 자동으로 static의 속성을 의무적으로 갖는다. 그렇기 때문에 클래스 이름으로 접근이 가능하다.
그리고 const 접근자는 생성과 동시에 초기값을 주어야 한다. 값을 설정하지 않으면 Error가 나게 된다.

readonly는 일반적인 static과 노멀한 변수와 구분이 된다. 선언에 따라가 다른 속성을 가질수 있다.
그리고 반드시 생성과 동시에 초기값을 줄 필요는 없다. 그리고 단 한번의 값만을 가질수 있게된다. 이 때 이한번의 값은 반드시 생성자에서만 값을 넣울수 있다.


혹 readonly가 한번의 값을 넣을수 있는데 혹시 생성자 아닌곳에서 한번 값을 넣으면 Error가 안날 것 같아서 해보았는데 그 것은 에러가 났다 결국 한번의 설정값을 설정하는것은 생성자에서만 가능하다는 알수 있었다. 그리고 readonly는 static과 일반적인 상용이 구분되니 readonly static 변수의 초기값은 static 생성자에서 설정을 해주어야 할 것이다.

csc.exe의 컴파일 옵션들이다.

/reference:xxx.dll   닷넷 어셈블리 dll을 링크 시킬때 사용
/out:xxx.exe            실행파일 명을 지정할때 사용
/target:library         exe 로 생성할지 dll로 생성할지에 대한 것을 설정한다.
/unsafe                   안전하지 않은 코드 즉 unsafe문이 들어간 코드는 이옵션을 사용해서 컴파일 해야함.

모든 단어가 길어서 치기 귀찮다면 앞글자 한자만 써도 가능하다.

아직은 이것밖에...
C# 2006/12/10 19:56

C#에서 dll을 링크 3

dll 링크 세번째 이번에는 포인터 ㅡ.ㅡ; 별쓰데 없는것에 다 한다는 생각이 든다. 불현듯 아참 C#은 포인터를 안쓰지?? 라는 생각에서 그럼 포인터를 사용한 dll을 이용할수 있을까나??? 이런 생각이 또 들었다. 아참~~ 이 꼬리에 꼬리는 무는 잡생각들~~

어째던 아래와 같이 dll을 만들었다.


extern "C" __declspec(dllexport)void IntSwap(int * a,int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
extern "C" __declspec(dllexport)void LongSwap(long * a,long * b)
{
long temp;
temp = *a;
*a = *b;
*b = temp;
}
 


포이터의 단골 주제인 Swap이다. 음...

이제는 C#코드인데..... 조금 생각을 해봤다. 과연 포인터의 인자값을 어떻게 넘길것인가에 대한 것. 여러 궁리 끝에 드디어 ref를 이용해서 dll 함수를 쓸수 있게 되었다. 음.. 역시 그럼 이제 C#으로 안되는것은 별로 없네.. 라는 생각이 들었다.


using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace DllPointer
{
  class Program
  {
       [DllImport("DllSwap.dll",CharSet=CharSet.Ansi)]
       public static extern void IntSwap(ref int a,ref int b);
       [DllImport("DllSwap.dll", CharSet = CharSet.Ansi)]
       public static extern void LongSwap(ref long a, ref long b);
       static void Main(string[] args)
       {
           int a = 10;
           int b = 20;
           IntSwap(ref a, ref b);
           Console.WriteLine("a = {0}, b = {1}",a,b);
           long c = 10000000;
           long d = 20000000;
           LongSwap(ref c, ref d);
           Console.WriteLine("c = {0}, d = {1}",c,d);
       }
  }
}
 


User inserted image

C# 2006/12/10 19:30

타 플랫폼에서의 .NET

글출처: http://cafe.naver.com/monodevelop.cafe 남정현(junghyun0816) 
------------------------------------------------------------------
닷넷은 프레임워크라고 하는 구성 요소를 중심 축으로 하여 여러 가지 서비스들을 제공하고 있습니다. 이 프레임워크는 대개의 닷넷 개발자들이 Microsoft 제품 외에는 없다고 단정을 지을 때가 상당히 많은데, 사실은 프레임워크도 종류가 여러가지입니다. Mono는 이러한 것들 중의 한 종류라고 할 수 있습니다.

 

* Microsoft .NET Framework

Windows 환경에서 가장 널리 사용됩니다. Microsoft가 .NET에 관해서 보여주고 싶어하는 것을 가장 빨리 확인할 수 있는 프레임워크이기도 합니다. 현재 공개된 가장 최근의 버전은 2.0 Beta 2이며, 아직은 1.1 버전을 널리 사용합니다. 소스 코드는 사용하실 수 없지만 무료로 다운로드하실 수 있습니다.

 

* Microsoft Rotor Framework

.NET Framework에 대한 얼터너티브 버전으로, Mac OS X, BSD 계열 유닉스, Windows를 대상으로 배포 중인 프레임워크입니다. .NET Framework의 버전에 맞춰서 같이 발매되는데, .NET Framework 2.0의 정식 버전이 발표되면 마찬가지로 이 프레임워크의 새 버전이 나옵니다. 이 프레임워크는 오픈 소스이며, 소스 코드로 제공됩니다.

 

* Mono Framework(http://www.mono-project.com/)

원래 Ximian에서 처음 개발을 시작한 오픈 소스 프레임워크입니다. Linux, Unix, Mac OS X, Windows를 대상으로 개발되는 프레임워크입니다. Microsoft .NET 영역에서 제공되지 않는 툴킷을 다수 기본 제공하며 많은 수의 닷넷 계열 오픈 소스 프로젝트들이 이 프레임워크를 기준으로 작성됩니다. GTK#, COCOA#, 다수의 ADO .NET 어댑터 (SqLite, MySQL, ...)들을 기본 제공합니다.

 

* DotGNU Framework

GPL 라이센스를 따르는 오픈 소스 프레임워크입니다. Mono에 비해 늦게 시작하였지만 Mono와는 달리 성능에 상당히 초점을 맞추고 개발하는 프레임워크입니다. 이 프레임워크가 지향하는 환경은 리눅스에서 네이티브 모드로 닷넷 어플리케이션들을 구동하는 것이라 합니다.

 

현재까지 알려진 프레임워크는 이 정도입니다. 진행하시고자 하는 프로젝트나 학습 방향에 맞는 프레임워크와 개발 도구를 선택하시는 것은 본인의 몫이기에 어느 것이 더 좋다고 이야기할 수는 없겠습니다.
------------------------------------------------------------------



좀더 자세한 사항을 알고자 한다면 MONO Framework의 개발 까페인 http://cafe.naver.com/monodevelop.cafe 를 참고하시기 바랍니다.


참고로 Rotor Framework이라고 알려져 있는 것은 SSCLI2.0으로 나와 있으며 FreeBSD에만 포팅이 되는 것으로 알고 있는데 정확치는 않습니다. 다음 사이트를 참고하시기 바랍니다.

http://research.microsoft.com/sscli/ 

div>