HUSKING - kotteri

技術系Note

【C#】DbDataReaderの値をモデルクラスに詰める

ODP.NETなどでExecuteReaderで取得した値をモデルクラスに詰め込みたいときに作ったメソッド。

メソッド

public static T GetColumns<T>(this DbDataReader reader)
{
    var record = Activator.CreateInstance<T>();
    foreach (var property in record.GetType().GetProperties())
    {
        object value = reader[property.Name];
        if (!DBNull.Value.Equals(value))
        {
            property.SetValue(record, value);
        }
    }
    return record;
}

使い方

DBのテーブル定義に合わせたモデルクラスを用意

※プロパティ名をテーブルカラム名に合わせる必要あり

public class Person
{
    public string NAME { get; set; }
    public int AGE { get; set; }
}
使用例

※Readerの部分だけを抜粋

cmd.CommandText = "SELECT * FROM Person";
var result = new List<Person>();
using (var reader = cmd.ExecuteReader())
{
    while (reader.Read())
    {
        // 作成したメソッドを利用してreaderの値を取得
        result.Add(reader.GetColumns<Person>());
    }
}

【C#】Pascal、CamelケースをSnakeケースに変換する

C#のプロパティ名をDatabaseのカラム名に変換したい時が稀に。。。
その際に作った変換するメソッドが以下。

変換メソッド

public static string GetSnakeCase(string str)
{
     var regex = new System.Text.RegularExpressions.Regex("[a-z][A-Z]");
     return regex.Replace(str, s => $"{s.Groups[0].Value[0]}_{s.Groups[0].Value[1]}").ToUpper();
}

使用例

Console.WriteLine(GetSnakeCase("PascalCase"));
Console.WriteLine(GetSnakeCase("camelCase"));

コンソール結果

PASCAL_CASE
CAMEL_CASE

【C#】ファイル内容のハッシュ値を求める

ファイルの同一性チェックなどでよくハッシュ値を使われることがある
今回はC#でファイルのハッシュ値を求めてみる


ハッシュ値を求めるファイルの内容

123456789
あいうえお


実際のコード

class Program
{
    static void Main(string[] args)
    {
        // EXEパスを取得
        var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;

        // ハッシュ値を求めるファイルパス
        var filePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "Text.txt");

        // ハッシュ値算出
        using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
        {
            /*
             * MD5でハッシュ値を求める
             */
            var md5 = System.Security.Cryptography.MD5.Create();
            var md5Hash = md5.ComputeHash(fs);
            Console.WriteLine($"MD5     : {BitConverter.ToString(md5Hash)}");


            // 読出し位置をリセット
            fs.Seek(0, System.IO.SeekOrigin.Begin);


            /*
             * SHA-1でハッシュ値を求める
             */
            var sha1 = System.Security.Cryptography.SHA1.Create();
            var sha1Hash = sha1.ComputeHash(fs);
            Console.WriteLine($"SHA-1   : {BitConverter.ToString(sha1Hash)}");



            // 読出し位置をリセット
            fs.Seek(0, System.IO.SeekOrigin.Begin);



            /*
             * SHA-256でハッシュ値を求める
             */
            var sha256 = System.Security.Cryptography.SHA256.Create();
            var sha256Hash = sha256.ComputeHash(fs);
            Console.WriteLine($"SHA-256 : {BitConverter.ToString(sha256Hash)}");
        }
        
        
        
        Console.ReadKey();
    }
}


コンソール出力

MD5     : 50-1A-F5-C8-DA-6E-4B-22-53-A4-67-42-89-DF-48-8E
SHA-1   : 5F-4C-A7-26-9A-CD-DD-C5-0C-7D-FD-47-26-D4-11-3A-21-79-0A-E9
SHA-256 : 4D-F7-89-F6-1E-56-DD-7F-62-7E-C4-69-2F-83-17-70-40-FF-47-F5-92-5F-10-C0-CF-66-B0-B9-41-84-51-24

【C#】複数のファイルを結合し、一つのファイルにまとめる

複数のファイルを結合して、一つのファイルにまとめてみる
手法は簡単で一つずつファイルを読みだして、結果ファイルに書き出していくだけ


結合するファイル

今回は3つのファイルを結合してみる
※ ファイルのエンコードは"UTF-8(BOM無し)"

  • ファイル1(src1.txt)
┳┻|
┻┳|
┳


  • ファイル2(src2.txt)
┻|_∧
┻┳|ω・)
┳┻|


  • ファイル3(src3.txt)
⊂ノ
┻┳| J


実際のコード

class Program
{
    static void Main(string[] args)
    {
        // EXEパスを取得
        var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;

        // 結合する2つのファイルパス(適当にリストで保持)
        // ファイルはEXEファイルと同じフォルダにあるものとする 
        var srcFilesPath = new List<string>
        {
            System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "src1.txt"),
            System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "src2.txt"),
            System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "src3.txt")
        };

        // 結果ファイルパス
        var dstFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "dst.txt");

        // 結合処理
        using (var wfs = new System.IO.FileStream(dstFilePath, System.IO.FileMode.Create, System.IO.FileAccess.Write))
        {
            // 結合するファイルを順に読んで、結果ファイルに書き込む
            var rbuf = new byte[1024 * 1024];
            foreach (var srcFilePath in srcFilesPath)
            {
                using (var rfs = new System.IO.FileStream(srcFilePath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
                {
                    var readByte = 0;
                    var leftByte = rfs.Length;
                 
                    while (leftByte > 0)
                    {
                        // 指定のサイズずつファイルの読み込む
                        readByte = rfs.Read(rbuf, 0, (int)Math.Min(rbuf.Length, leftByte));

                        // 読み込んだ内容を結果ファイルに書き込む
                        wfs.Write(rbuf, 0, readByte);

                        // 残りの読み込みバイト数を更新
                        leftByte -= readByte;
                    }
                }
            }
        }



        Console.ReadKey();
    }
}


結果ファイル(dst.txt)の中身

┳┻|
┻┳|
┳┻|_∧
┻┳|ω・)
┳┻|⊂ノ
┻┳| J

【C#】ファイルの読み書きを一度に行う

ファイルの一部を読み込んで書き換えをするのに、
一度別ファイルに書き出して置き換えるという手順が面倒だったので、
別ファイルを作成せずに行う方法を試してみた。


実行前のファイル(Text.txt)の中身

123456789
あいうえお

※ ファイルのエンコードは"UTF-8(BOM無し)"


今回試したこと

  1. 先頭の3文字「123」を読みだした後、「987」に書き換える

  2. 2行目の2~4文字「いうえ」を読みだした後、「イウエ」に書き替える


実際のコード

class Program
{
    static void Main(string[] args)
    {
        // EXEパスを取得
        var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;

        // 読み書きするテキストファイルのパスを生成(以下の場合はEXEファイルと同じフォルダにあるものとする)
        var filePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(exePath), "Text.txt");



        /*
         * パターン1:最初の3文字を読み込んで、書き換える
         */

        // 読み書き可能モードでファイルを開く
        using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None))
        {
            // 読み込み
            var rbuf = new byte[3];
            if (fs.Read(rbuf, 0, rbuf.Length) < 1)
            {
                Console.WriteLine("読み込みエラー");
                return;
            }
            // 読み込んだ文字列を出力
            Console.WriteLine($"パターン1:{Encoding.GetEncoding("utf-8").GetString(rbuf)}");

            // 書き換える文字を設定
            var wbuf = Encoding.GetEncoding("utf-8").GetBytes("987");
            // 書出し位置を先頭にもってくる
            fs.Seek(0, System.IO.SeekOrigin.Begin);
            // 書き換え
            fs.Write(wbuf, 0, wbuf.Length);
        }



        /*
         * パターン2:2行目の2~4文字目を読み込んで、書き換える
         */
        using (var fs = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None))
        {
            // 読出し位置を指定の位置に設定
            var offset = 9 + 1 + 1 + 3; // 1行目文字列 + CR + LF + 2行目全角1文字
            fs.Seek(offset, System.IO.SeekOrigin.Begin);
            // 読み込み
            var rbuf = new byte[3 * 3]; // 全角3文字      
            if (fs.Read(rbuf, 0, rbuf.Length) < 1)
            {
                Console.WriteLine("読み込みエラー");
                return;
            }
            // 読み込んだ文字列を出力
            Console.WriteLine($"パターン2:{Encoding.GetEncoding("utf-8").GetString(rbuf)}");

            // 書き換える文字を設定
            var wbuf = Encoding.GetEncoding("utf-8").GetBytes("イウエ");
            // 書出し位置を指定の位置に設定
            fs.Seek(offset, System.IO.SeekOrigin.Begin);
            // 書き換え
            fs.Write(wbuf, 0, wbuf.Length);
        }



        Console.ReadKey();
    }
}


コンソール出力

パターン1:123
パターン2:いうえ


実行後のファイル(Text.txt)の中身

987456789
あイウエお

バッチファイルにて現在日時を出力する

バッチファイル(.bat)にて現在日時を”yyyymmdd_hhmmss”形式で出力してみる

set dt=%date%
set tm=%time: =0%
echo %dt:~0,4%%dt:~5,2%%dt:~8,2%_%tm:~0,2%%tm:~3,2%%tm:~6,2%

実行結果

20191018_113803


注意点としては、午前0時~午前9時の場合、
time変数が返す文字列の先頭には、「0」ではなく、空白文字が含まれている

その為、” =0%”で空白を0に置換している


ログファイルの出力などでたまに使うので忘れないようにメモ :)

MACでパスワード付きZIPファイルを作成する

ファイル

zip -e [圧縮後のファイル名] [圧縮したいファイルパス]

zip -e hogefile.zip hogefile.txt

フォルダ

zip -e -r [圧縮後のファイル名] [圧縮したいフォルダパス]

zip -e -r hogedir.zip hogedir/



コマンド実行後にパスワードの入力を求められる

Enter password:

設定したいパスワードを入力すればOK