スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

[C#] CSVファイルをディクショナリ化

CSVファイルを読み込むとき、データベースのようにキーを設定して、読み込みたい時があると思います。

その時に実装したメモを残します。

ここでは、CSVReaderを使います。(使い方はここを参照)
ただし、特に使わなくてもCSVを読み込んでstring配列に出来れば問題ありません。

その時のコード

protected Dictionary<string, string[]> CSV_get(string csvpath, int keycolumn) {
try {
if (!File.Exists(csvpath))
return null;

using (CsvReader reader = new CsvReader(new StreamReader(csvpath, Encoding.GetEncoding("shift-jis")), true)) {
return reader.ToDictionary(x => x[keycolumn]);
}

} catch (Exception exp) {
return null;
}
}



reader.ToDictionary(x => x[keycolumn])がミソですね!

おわり

テーマ : ソフトウェア開発
ジャンル : コンピュータ

[C#] A Fast CSV Reader が速い!

C#で、CSVファイルの読込みを自作で処理していました。
完成度が高くないのでコードは書きませんが、簡易に、
1. StreamReaderで読込み
2. ReadLineにて行を読込み
3. split(',')にて値を取り出し
4.Listに格納
してました。

しかし、もっと早くできないものかな?
と考え、ちょっと調べてみたら、A Fast CSV Readerというものを発見。

そこで、A Fast CSV Readerを使ってベンチマークしてみました。
ただし、A Fast CSV Readerを取得するには、登録が必要です。
ベンチマークは以下のスペックです。
CPU : Core i7 950 3.07 GHz 
Mem : 6 GB
OS    : Windows7 64bit
CSV  :  col 4 , row 6200000


やっていることは、全ての値をList<List<string>>に格納しています。


LibTime [msec]
現状30237
A Fast CSV Reader9077


なんと、1/3程度に、短縮しています。
これは凄い。(自前がどんだけしょぼかったのかorz)

ちなみに、A Fast CSV Readerを使ったコードはこれ。

List<List<string>> lobj = new List<List<string>>();

using (LumenWorks.Framework.IO.Csv.CsvReader rcsv =
new LumenWorks.Framework.IO.Csv.CsvReader(new StreamReader(csvpath), true)) {

rcsv.SupportsMultiline = false;

while (rcsv.ReadNextRecord()) {
List obj = new List();
for (int i = 0; i < rcsv.FieldCount; i++)
obj.Add(rcsv[i]);

lobj.Add(obj);
}
}




んー、我ながらショボい。
適当に使って、こんなものだから、きちんと特徴を把握して使用すると、もっと早くなるし、コード量も減るはず。


また、Dobon.netに、CSVの定義が載っておりました。

レコードは、CRLFで区切られる。
最後のレコードは、CRLFを持つかもしれないし、持たないかもしれない。
はじめのレコードは、ヘッダかもしれない。
フィールドは、カンマ(,)で区切られる。フィールドの数は、同じでなければならない。スペースはフィールドの一部であり、無視してはいけない。レコードの最後のフィールドの後にコンマが続いてはいけない。
各々のフィールドがダブルクォートで囲まれているかもしれない。
フィールドにCRLF、ダブルクォート、カンマが含まれる場合、フィールドをダブルクォート(")で囲まなければならない。
ダブルクォートで囲まれたフィールドにダブルクォートが含まれる場合、フィールド内のダブルクォートを2つの連続するダブルクォート(つまり、「""」)に置き換えなければならない。




ふむ、私が作った適当CSVオブジェクトは、全てを満たしていないw
ということで、CSV操作をするなら、A Fast CSV Reader等を使ったほうがいいと思います。
ちなみに、A Fast CSV Readerのコードは結構大量です。
(CSVを操作するだけで、こんな量のコードを読むのはつらい。。。)



テーマ : プログラミング
ジャンル : コンピュータ

C# ListBoxで任意のクラスメンバを表示

久々に、C#です。

今回、ListBox 等のItemsにて適当なクラスを追加した際、
ListBoxに表示するメンバを設定する例を示します。
表示するメンバを設定するときは、DisplayMemberを指定します。
 
今回、Perosnクラスを作成し、このクラスをListBoxのItemsに追加します。
表示は、Nameプロパティです。
displayMembersample1

Personクラス

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace WindowsFormsApplication1 {

    public class Person {

 

        private string _Name = "";

        private int _Age = 20;

        private string _Mail = "";

 

        // 名前

        public string Name { get { return _Name; } set { _Name = value; } }

        // 年齢

        public int Age { get { return _Age; } set { _Age = value; } }

        // メール

        public string Mail { get { return _Mail; } set { _Mail = value; } }

 

        // コンストラクタ

        public Person(string name, int age, string mail) {

            Name = name;

            Age = age;

            Mail = mail;

        }

    }

}

Form1のpartialクラス 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1 {

    public partial class Form1 : Form {

 

        public Form1() {

            InitializeComponent();

        }

 

        private void button1_Click(object sender, EventArgs e) {

            Person person = new Person("斉藤", 20, "aaa@bbb.com");

            // DisplayMemberにて表示プロパティを設定

            listBox1.DisplayMember = "Name";     

            listBox1.Items.Add(personlist);

        }

    }

}





と、簡単に表示。
しかし、文字列で表示しただけで、プロパティを引っ張ってくるとは、素晴らしい作りですね。
どうやってるんだろう??

終わり


テーマ : プログラミング
ジャンル : コンピュータ

[C#] IEqualityComparerを使ってListのContains

List配列で、同じオブジェクトが入っている事を確認する場合、
Containsを使用し、簡単にbool値を取得することができますが、
今回、同じオブジェクトではないけど、比較オブジェクト内のある属性を比較したい場合、
簡単に比較する事ができたのでメモします。
(いまさらですが)

使う物は、
・System.ServiceModel.Syndication名前空間
・System.Xml名前空間
・IEqualityComparerインタフェース
です。

例として、地震情報のRSS(Goo地震RSS)を取得し、
RSSのSyndicationItemのTitleの比較しています。

1. 比較クラスの作成
   実行コードから、アクセス出来る場所に以下のクラスを作成します。

        public class CompareSyndicationItem : IEqualityComparer<SyndicationItem> {

            public bool Equals(SyndicationItem x, SyndicationItem y) {

                return x.Title.Text == y.Title.Text;

            }


            public int GetHashCode(SyndicationItem obj) {

                return obj.Title.Text.GetHashCode();

            }

        }
   ここでは、SyndicationItemは、RSSのentryのオブジェクトです。
   IEqualityComparerインタフェースを用います。
   必要なメンバは、EqualsとGetHashCodeです。
   Equalsには、比較文を書きます。(同じであればTrueを返します)
   GetHashCodeは、比較対象のハッシュを返します。(とりあえずGetHashCode()を)

2. 使い方

            SyndicationFeed feed;

            string uri = "http://weather.goo.ne.jp/earthquake/index.rdf";

            using (XmlReader rdr = XmlReader.Create(uri)) {

                feed = SyndicationFeed.Load(rdr);

            }


            // 適当なItemを作成する。適当なURIです。。。

            SyndicationItem compItem = new SyndicationItem("TestTitle", "", new Uri(uri));

            // titleが同じitemを取得する

            CompareSyndicationItem csi = new CompareSyndicationItem();

            if (feed.Items.Contains(compItem, csi))

                Console.WriteLine("一致するタイトルがありました");

            else

                Console.WriteLine("一致するタイトルがありませんでした。");
   ここでは、SyndicationFeedにRSSを読込み、
   比較するアイテム(entry)を適当に作って比較しています。

今まで、ループを回してたけど、調べてみるもんだなぁ。
おわり。

テーマ : プログラミング
ジャンル : コンピュータ

C#で共有フォルダへのアクセス

ユーザ名、パスワードを入力して、共有フォルダへアクセスし、
ファイルを操作する必要がありましたので、調べてみました。

参考にしたサイトは、以下です。
3流プログラマのメモ書き

とりあえず使うものは、
WNetAddConnection2      ← 接続用
WNetCancelConnection2  ← 切断用
というものらしいです。
詳しくは、参考にしたリンクを参考ください。

そのままメモしても意味が無いので、作成したクラスを載せておきます(--;)oO(ほぼコピペだけど)

作成したクラスは、IDisposableを実装し、オブジェクトが破棄されたときは、
削除されるようにしています。





using System;
using System.Runtime.InteropServices;

namespace myclass{
public class ConnectSharedFolder : IDisposable{

//接続切断するWin32 API を宣言
[DllImport("mpr.dll", EntryPoint ="WNetCancelConnection2",CharSet=
System.Runtime.InteropServices.CharSet.Unicode)]
private static extern int WNetCancelConnection2(string lpName, Int32 dwFlags, bool fForce);

[DllImport("mpr.dll", EntryPoint = "WNetAddConnection2", CharSet =
System.Runtime.InteropServices.CharSet.Unicode)]

private static extern int WNetAddConnection2(
ref NETRESOURCE lpNetResource, string lpPassword, string lpUsername, Int32 dwFlags);

[StructLayout(LayoutKind.Sequential)]
internal struct NETRESOURCE {
public int dwScope;
public int dwType;
public int dwDisplayType;
public int dwUsage;

[MarshalAs(UnmanagedType.LPWStr)]
public string lpLocalName;

[MarshalAs(UnmanagedType.LPWStr)]
public string lpRemoteName;

[MarshalAs(UnmanagedType.LPWStr)]
public string lpComment;

[MarshalAs(UnmanagedType.LPWStr)]
public string lpProvider;

}

#region MemberField
private string _path = "";
private string _usr = "";
private string _psw = "";
private bool _isConnect = false;
#endregion

public ConnectSharedFolder(string path, string username, string password) {
_path = path;
_usr = username;
_psw = password;
}

///
/// 共有フォルダへの接続
/// 共有フォルダパス
/// ユーザ名
/// パスワード
///
public int Connect() {
NETRESOURCE netResource = new NETRESOURCE();
netResource.dwScope = 0;
netResource.dwType = 1;
netResource.dwDisplayType = 0;
netResource.dwUsage = 0;
netResource.lpLocalName = "";
netResource.lpRemoteName = _path;
netResource.lpProvider = "";

int ret = 0;
try {
ret = WNetCancelConnection2(_path, 0, true);
ret = WNetAddConnection2(ref netResource, _psw, _usr, 0);
} catch (Exception exp) {
return -1;
}

_isConnect = true;
return ret;
}


///
/// 共有フォルダの切断
///
///
public int DisConnect() {
if (_isConnect)
return WNetCancelConnection2(_path, 0, false);
else
return 0;
}

public void Dispose() {
try {
if (_isConnect)
WNetCancelConnection2(_path, 0, false);
} catch {

}
}
}
}




コンストラクタで、必要なパラメータを取得し、
Connect()で接続、DisConnect()で切断です。

終わり。






テーマ : プログラミング
ジャンル : コンピュータ

プロフィール

ss_9

名前 :ss_9
紹介 :
20代はエンジニア、30代はプロ、40代は管理、50代は人脈。

Twitterボタン

最新記事
カテゴリ
AD
月別アーカイブ
RSSリンクの表示
RSSリンクの表示
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。