忘れがちなことを、つらつらと...

俺的備忘録を公開してみるテスト

データベースのデータをCSVエクスポートする

まぁ、ネットにソースはいっぱい転がってるよね...データ移行なんかで単純にエクスポートしたいわけで。

こんな感じでいい加減に作ってみましたw

/*
 * SharpDevelopによって生成
 * ユーザ: hoge
 * 日付: 2014/03/01
 * 時刻: 15:09
 * 
 * このテンプレートを変更する場合「ツール→オプション→コーディング→標準ヘッダの編集」
 */
using System;
using System.Data.Common;

namespace ODBC2CSV
{
    class Program
    {
        public static void Main(string[] args)
        {
            // TODO: Implement Functionality Here
            DBAccess db = new DBAccess("AS/400");
            db.Connection.Open();
            db.Command.CommandText = "SELECT * FROM " + args[0];
            DbDataReader reader = db.Command.ExecuteReader();
            using (CsvFileWriter writer = new CsvFileWriter(args[0]+".csv", false, System.Text.Encoding.GetEncoding("shift_jis")))
            {
                while (reader.Read()) 
                { 
                    CsvRow row = new CsvRow();
                    for (int j = 0; j < reader.FieldCount; j++)
                        if (!reader.IsDBNull(j)) {
                            object res = reader.GetValue(j);
                            row.Add(res.ToString());
                        }
                        else
                            row.Add(string.Empty);
                    writer.WriteRow(row);
                }
            } 
            reader.Close(); 
            db.Connection.Close(); 
        }
    }
}

パラメータとしてテーブル名を渡してその中身を出力する的な感じ。データベースとの接続設定はconfigファイルに書く。

<?xml version="1.0" encoding="utf-8" >
<configuration>
    <connectionStrings>
        <add name="AS/400"
             connectionString="Driver={iSeries Access ODBC Driver};DefaultLibraries=QGPL;System=10.1.0.104; Uid=QSECOFR; Pwd=QSECOFR"
             providerName="System.Data.Odbc" >
    </connectionStrings>
</configuration>

あと、データベース操作用のクラスと

/*
 * SharpDevelopによって生成
 * ユーザ: hoge
 * 日付: 2014/03/01
 * 時刻: 15:13
 * 
 * このテンプレートを変更する場合「ツール→オプション→コーディング→標準ヘッダの編集」
 */
using System;
using System.Data;
using System.Data.Common;
using System.Configuration;

namespace ODBC2CSV
{
    /// <summary>
    /// Description of DBAccess.
    /// </summary>
    public class DBAccess
    {
        private string connectionString;
        private string providerString;
        private DbProviderFactory dbProviderFactory;
        
        public DbConnection Connection { get; set; }
        public DbCommand Command { get; set; }
        public DbDataAdapter DataAdapter { get; set; }
        public DbCommandBuilder CommandBuilder { get; set; }
        
        private void initialize()
        {
            dbProviderFactory = DbProviderFactories.GetFactory(providerString);
            this.Connection = dbProviderFactory.CreateConnection();
            this.Connection.ConnectionString = connectionString;
            this.Command = dbProviderFactory.CreateCommand();
            this.Command.Connection = this.Connection;
            this.DataAdapter = dbProviderFactory.CreateDataAdapter();
            this.DataAdapter.SelectCommand = this.Command;
            this.CommandBuilder = dbProviderFactory.CreateCommandBuilder();
            this.CommandBuilder.DataAdapter = this.DataAdapter;
        }

        public DBAccess(string constr, string provider)
        {
            connectionString = constr;
            providerString = provider;
            try {
                initialize();
            } catch {
                throw new Exception("データベース接続設定が不適切.");
            }
        }
        
        public DBAccess(string config)
        {
            try {
                connectionString = ConfigurationManager.ConnectionStrings[config].ConnectionString;
                providerString = ConfigurationManager.ConnectionStrings[config].ProviderName;
            } catch {
                throw new Exception("データベース接続設定が記述されていない.");
            }
            try {
                initialize();
            } catch {
                throw new Exception("データベース接続設定が不適切.");
            }
        }
    }
}

CSV出力のクラスと

/*
 * SharpDevelopによって生成
 * ユーザ: hoge
 * 日付: 2014/03/01
 * 時刻: 16:01
 * 
 * このテンプレートを変更する場合「ツール→オプション→コーディング→標準ヘッダの編集」
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace ODBC2CSV
{
    /// <summar>
    /// Description of CsvRow.
    /// </summary>
    public class CsvRow : List<string>
    {
        public string LineText { get; set; }
    }
    
    /// <summary>
    /// Description of CsvFileWriter.
    /// </summary>
    public class CsvFileWriter : StreamWriter
    {
        public CsvFileWriter(Stream stream)
            : base(stream)
        {
        }

        public CsvFileWriter(string path)
            : base(path)
        {
        }
        
        public CsvFileWriter(string path,bool append,Encoding encoding)
            : base(path, append, encoding)
        {
        }
    
        /// <summary>
        /// Description of WriteRow.
        /// </summary>
        public void WriteRow(CsvRow row)
        {
            StringBuilder builder = new StringBuilder();
            bool firstColumn = true;
            foreach (string value in row)
            {
                // 最初は付けない
                if (!firstColumn)
                    builder.Append(',');
                // カンマとダブルクォートの処理
                if (value.IndexOfAny(new char[] { '"', ',' }) != -1)
                    builder.AppendFormat("\"{0}\"", value.Replace("\"", "\"\""));
                else
                    builder.Append(value);
                firstColumn = false;
            }
            row.LineText = builder.ToString();
            WriteLine(row.LineText);
        }
    }
}

相変わらず、エラー処理はいい加減だけど、一発屋だからいいんだよ、こんなもんで。