C#の最近のブログ記事
Parseしてcatchするかどうかの判定でもいいのですが、いまいちスマートじゃないなぁと。
そしたら2.0からTryParseなるメソッドが追加されていました。
いやー、不勉強ここにいたるという感じですな。
int intReturn;
Console.WriteLine (int.TryParse("hoge",out intReturn));
上記例だとFalseが出力されます。
第一引数"hoge"が整数か否かを判定して、「ちげーよ」っていう結果が出てるんですよね。整数だったらTrueが返ります。boolです。
また、Falseの場合にはintReturnに「0(ゼロ)」がセットされます。Falseの0なんですけど、何に使うのかがわかりませんでした。せめて初期値を指定できて、Falseならその値が返ってくれればいいのですが、一行目を
int intReturn = 1234;
としておいても、0が返ります。
String.Format("{0:yyyyMMdd}",DateTime.Now)
まぁこれだけの話なのですが、しょっちゅう書き方忘れるので備忘録に。
string[] strMonth = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",};
cmbMonth.Items.AddRange(strMonth);
cmbMonth.SelectedIndex = cmbMonth.FindString(DateTime.Now.Month.ToString());
例として、cmbMonthというコンボボックスに1月から12月までの値を入れています。そして、今月をSelectedIndexに指定しています。FindStringメソッドで当月が格納されているitemindexを求めて、それをselectedindexに指定しているだけ。
これって2.0からでしょうね。確か1.1のころはこんな便利なメソッドはなかった。
最近帳票出力が必要なWindowsアプリケーションの開発をやっています。帳票はPDF。ActiveReportとかを買うお金はありません。ということで、iText.NET。
フリーなのにとってもよくできているのですが、いまいち思ったとおりに動いてくれない。まぁこれは僕のセンスの問題なのですが。。。
もうちょっとしたらTipsをまとめて書けそう。忘れないうちに書かないと。。。
プロパティウィンドウにフォントサイズなる項目がなかったような気がして不安になったのですが、コードから指定したら簡単にできてしまいました。
DataGridViewの名称.Font = new Font(DataGridViewの名称.Font.Name, 22);
これでデフォルトフォントのままでサイズだけが22になります。
でも、カラムのheightも合わせて指定しないと悲しいことになります。勝手に拡大してくれたら幸せになれたのに。。。
//もしかすると名前空間足りないかも
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Collections;
//相手のCGIはeuc-jpで書かれています。
Encoding encEuc = Encoding.GetEncoding("euc-jp");//POSTするデータの作成、URLエンコードが必要です。
byte[] data = Encoding.ASCII.GetBytes("data=" + HttpUtility.UrlEncode("C#からベーシック認証の向こうにPOSTしてみました。", encEuc));//WebRequestの作成
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(CGIのURL);//POSTでURLエンコードされたデータを送信しますという宣言
webreq.Method = "POST";
webreq.ContentType = "application/x-www-form-urlencoded";//ベーシック認証使うよ宣言と、次にアカウントとパスワード
webreq.PreAuthenticate = true;
NetworkCredential network = new NetworkCredential(アカウント,パスワード);
webreq.Credentials = network;//何バイト送るよ
webreq.ContentLength = data.Length;
//送信ストリーム
Stream webreq_stream = webreq.GetRequestStream();
webreq_stream.Write(data, 0, data.Length);
webreq_stream.Close();//受信ストリーム
WebResponse webres = webreq.GetResponse();
Stream webres_stream = webres.GetResponseStream();//受信ストリームの読み込みと、クローズ
StreamReader stream = new StreamReader(webres_stream, encEuc);
string strGetData = stream.ReadToEnd();
stream.Close();
webreq_stream.Close();//受信したら書き出そう
System.Console.Write(strGetData);
Webサービス使えない状況だとやっぱりCGI経由になるわけですが、大事なデータはやっぱりベーシック認証なんかで守られてるわけですよ。しかもGETでクエリつけたらログに残っちゃいますしね。
というわけで、上記の手法を探っておりました。
これまでWindows サービスを作るにはC++の知識が必須でしたが、.NETのおかげでかなり開発しやすくなりました。(処理速度的にどうよ、2000serverで動かないケースもあるよ、というのは置いといて)
まずは、フォルダの状態監視ツールでも作ってみましょう。
using System.IO; //状態監視の宣言 Private FileSystemWatcher fileWatcher = new FileSystemWatcher();あくまでサンプルです。こんなチンケなことしかできないわけではありません。Protected override void OnStart(strings[] args)
{
//監視対象のディレクトリを指定
fileWatcher.Path = @"E:¥watch_test";//フォルダサイズが変わったらイベントを起こす
fileWatcher.NotifyFilter = (NotifyFilters.Size);//起こすイベントの定義
fileWatcher.Changed += new FileSystemEventHandler(OnChanged);//監視を有効にする
fileWatcher.EnableRaisingEvents = true;
}Public static void OnChanged(System.Object source,FileSystemEventArgs e)
{
//これが変更時に起きるイベント
}
もっと多くのことが監視できます。ま、さわりです。
ファイル単位で監視したり、フォルダも多くのイベント、状態を監視できます。
わずか数行のコードでこれだけのことができるのですから、すごいですね。
業務アプリとかになると、色々な集計結果をCSVで出力する機能が要求されることが多いです。多いっていうか、ほとんどの場合あります。
.NETのDataSetは、XMLへの変換はメソッドを呼ぶだけで簡単にできるのですが、CSVへの変換はサポートしていません。これをなんとか効率的にやりたいなぁ、と思い、色々調べてみました。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="NewDataSet">
<xsl:apply-templates select="Table" />
</xsl:template>
<xsl:template match="Table">
<xsl:value-of select="Column_A" />,<xsl:value-of select="Column_B" />,<xsl:value-of select="Column_C" />
</xsl:template>
</xsl:stylesheet>
上記内容のXSLTファイルを作成します。XSLTとは、XSLT(XSL Transformation)でして、まぁ、XMLの変換テンプレートと思ってください。これを、hoge.xsltという名前で保存しておきましょう。
System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform(); xslt.Load(@"C:\hoge.xslt");System.Xml.XmlDocument doc = new XmlDocument();
doc.Load(@"C:\hoge.xml");System.Xml.XmlTextWriter csvWriter = new XmlTextWriter(@"C:\hoge.csv",System.Text.Encoding.GetEncoding("Shift-JIS"));
xslt.Transform(doc.CreateNavigator(),null,csvWriter,null);
csvWriter.Close();
このサンプルはXMLファイルを読み込んで、それをCSVに変換してC:\hoge.csvというファイル名で出力しています。
XSLTをみていただければわかるとおり、Column_A、Column_B、Column_Cというフィールドだけが出力されます。つまり、出力するCSVごとにXSLTが必要になります。フォーマットが決まっているのなら、まったく問題ないと思います。
このやり方は、速いです。1万件(フィールド数20件ほど)のXMLの変換に4~5秒でした。
はじめてこれを書いたときは、まだまだPOPのサンプルとかってほとんどなかったのに、最近いろんなとこで公開されてるなぁ。C#もだいぶこなれてきたかな。
大事なことは、メールの送受信の方法ではありません。
ソケットプログラミングの基礎を知ること、それとPOPコマンドを知ることです。
ソケットプログラミングを覚えると、FTPソフトなんかも作れるようになりますよ。
using System.Net; using System.Text; using System.Net.Sockets; using System.IO; using System.Diagnostics;
private void button1_Click(object sender, System.EventArgs e)
{
//POPサーバと接続、ストリームを開く
TcpClient pop3Conn = new TcpClient("メールサーバ",110);
NetworkStream pop3Stream = pop3Conn.GetStream();StreamReader stmReader = new StreamReader(pop3Stream);
Debug.WriteLine(ReadStreamLine(stmReader));//ユーザ名を送信
SendStream(pop3Stream,"USER アカウント\r\n");
Debug.WriteLine(ReadStreamLine(stmReader));//パスワードを送信
SendStream(pop3Stream,"PASS パスワード\r\n");
Debug.WriteLine(ReadStreamLine(stmReader));//メールの件数を取得
SendStream(pop3Stream,"STAT\r\n");
string[] strMailCount = ReadStreamLine(stmReader).Split(' ');
int intMailCount = int.Parse(strMailCount[1]);//メール本文の取得、件数分ループさせる
for (int i=1;i<=intMailCount;i++)
{
//i件目のメールをちょうだいというコマンドを送信
SendStream(pop3Stream,"RETR " + i + "\r\n");string strBody = ReadStreamToEnd(stmReader);
Debug.Write(strBody);
}//終了コマンドの送信
SendStream(pop3Stream,"QUIT\r\n");
Debug.WriteLine(ReadStreamLine(stmReader));//ストリームを閉じる
pop3Stream.Close();
//サーバとの接続を閉じる
pop3Conn.Close();
}
private void SendStream(Stream pop3Stream, string strSendString)
{
//コマンドをバイト配列にしてストリームに流す
byte[] ByteData = Encoding.Unicode.GetBytes(strSendString);
int intByteDataCount = Encoding.Unicode.GetByteCount(strSendString);pop3Stream.Write(ByteData,0,intByteDataCount);
}private string ReadStreamLine(TextReader txtReader)
{
return txtReader.ReadLine() + "\r\n";
}private string ReadStreamToEnd(TextReader txtReader)
{
//本文開始のフラグ
bool blFlg = false;//本文を作成するStringBuilder。stringに += していくのは効率悪い
StringBuilder strReturn = new StringBuilder();//読み込んだ一行
string strBuffer;//読み込んだ文字列のバイト配列
byte[] ByteData;//配列数
int intByteDataCount;while(true)
{
strBuffer = txtReader.ReadLine();
//"."が来たら終了、メール1件の最後には必ずこれがついている
if (strBuffer.Equals(".")) break;//ヘッダ部分と本文の境目は空白一行あるだけ。
//一行ずつ読んでいって、ここに来たらフラグを立てる
if (strBuffer.Length.Equals(0))
{
blFlg = true;
}//フラグたってたら本文開始ということで、読み込み始める
if (blFlg)
{
ByteData = Encoding.ASCII.GetBytes(strBuffer);
intByteDataCount = Encoding.ASCII.GetByteCount(strBuffer);
strReturn.Append(Encoding.GetEncoding("iso-2022-jp").GetString(ByteData,0,intByteDataCount) + "\r\n");
}
}//StringBuilderをstringに変換して返す
return strReturn.ToString();
}
自分の居場所を知るのに使う
DirectoryInfo dirCurrent= new DirectoryInfo(".") ; dirCurrent.FullName + "\hoge.exe";
だと、例えばデスクトップにショートカットを作成し、
そのショートカットをダブルクリックした場合はデスクトップ上の「hoge.exe」を指してしまう。
「現在イベントの起きたところ」という意味合いだろうか。
今回使ったのはこれ
Application.StartupPath
まさしく、アプリケーションの実行ファイルの位置を示してくれた。