雑多なブログ

何を書くか決めていません。IT関係が多いかも

BingAI に C# で使える csvファイル読み込み用の関数を考えてもらいました。

BingAI に C# で使える csvファイル読み込み用の関数を考えてもらいました。(しかし、正常には動かなかったので、途中から自分で完成させています)

何回かやり取りして、最終的なプロンプトは以下のような感じになりました。

下記の条件を満たすC#用のcsv読み込み関数を教えて。

・空行を無視しない。
・項目内にカンマや改行、ダブルクォーテーションがあるデータにも対応。
・sr.Peek()を使用しない。
・最初にcsvファイルを全部読み込んでおく。

ソースは以下です。(BingAIに考えてもらったのは、ReadCsv関数)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CsvRead
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            List<string[]> result;

            result = ReadCsv(@"test.csv");

            Output(result);

            OutputGrid(result);
        }

        List<string[]> ReadCsv(string csvFilePath)
        {
            List<string[]> result = new List<string[]>();
            List<string> line = new List<string>();
            StringBuilder value = new StringBuilder();
            bool dq_flg = false;
            char lastCh = ' ';

            string allText = File.ReadAllText(csvFilePath);

            foreach (char ch in allText)
            {
                if (ch == '\"' 
                    && dq_flg == false
                    && lastCh == '\"')
                {
                    dq_flg = true;

                    value.Append('\"');

                    continue;
                }

                if (ch == '\"')
                {
                    if(dq_flg == false)
                    {
                        dq_flg = true;
                        lastCh = '\"';

                        continue;
                    }
                    else
                    {
                        dq_flg = false;
                        lastCh = '\"';

                        continue;
                    }
                }

                if (ch == '\r' && dq_flg == false)
                {
                    lastCh = '\r';

                    continue;
                }

                if (ch == ',' && dq_flg == false)
                {
                    line.Add(value.ToString());
                    value.Clear();
                    lastCh = ',';

                    continue;
                }

                if (ch == '\n' && dq_flg == false)
                {
                    line.Add(value.ToString());
                    value.Clear();
                    result.Add(line.ToArray());
                    line.Clear();
                    lastCh = '\n';

                    continue;
                }

                value.Append(ch);
            }

            return result;
        }

        void Output(List<string[]> result)
        {
            foreach (string[] row in result)
            {
                for (int i=0; i<row.Length; i++)
                {
                    string col;

                    col = row[i];

                    if(i == row.Length - 1)
                    {
                        System.Console.Write(col);
                    }
                    else
                    {
                        System.Console.Write(col + ",");
                    }
                }
                System.Console.WriteLine();
            }
        }

        void OutputGrid(List<string[]> result)
        {
            string[] colName;
            DataTable dt = new DataTable();

            colName = result[0];

            for(int i=0; i<colName.Length ; i++)
            {
                dt.Columns.Add(colName[i]);
            }

            for (int r=1; r < result.Count; r++)
            {
                string[] row;

                row = result[r];

                dt.Rows.Add(row);
            }

            dataGridView1.DataSource = dt;

            dataGridView1.Columns["名前"].DefaultCellStyle.WrapMode = DataGridViewTriState.True;
            dataGridView1.Columns["住所"].DefaultCellStyle.WrapMode = DataGridViewTriState.True;

            dataGridView1.AutoResizeRows();
        }
    }
}

画面のデザインは以下です。ボタンとDataGridViewを1個ずつ配置しています。

test.csv の内容は以下です。

名前,年齢,住所
山田太郎,25,東京都 新宿区
"鈴木


花子",32,"神奈川県
横浜市"
"佐藤,次郎",41,"大阪""府""大阪市"

実行結果は以下です。一応 意図通りに動いているようです。

以上です。