for Push.
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
using KssSmaPlaLib.Commons;
|
||||
using KssSmaPlaLib.Exchange.Interfaces;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace KssSmaPlaLib.IO.File
|
||||
{
|
||||
public class CsvUxer
|
||||
{
|
||||
public static bool ExportToCsv<T>(List<T> list, string filePath, out string resultMessage, EncodingUxer.EncodingType encodingType = EncodingUxer.EncodingType.Utf8WithoutBom) where T : ICsvExportableUxer
|
||||
{
|
||||
resultMessage = string.Empty;
|
||||
try
|
||||
{
|
||||
var lines = new List<string> { list.FirstOrDefault()?.CsvHeader ?? "" };
|
||||
lines.AddRange(list.Select(item => item.ToCsvLine()));
|
||||
System.IO.File.WriteAllLines(filePath, lines, EncodingUxer.GetEncoding(encodingType));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
resultMessage = $"CSV出力に失敗しました。[ファイルパス:{filePath},エラー内容:{ex.Message}]";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CSVインポート
|
||||
/// </summary>
|
||||
/// <param name="csvFilePath">CSVファイルパス</param>
|
||||
/// <param name="recordSet">[出力]レコードセット</param>
|
||||
/// <param name="resultMessage">[出力]メッセージ</param>
|
||||
/// <param name="encodingType">[オプション]エンコード</param>
|
||||
/// <returns>成否</returns>
|
||||
public static bool ImportFromCsv(string csvFilePath, out List<Dictionary<string, string>> recordSet, out string resultMessage, EncodingUxer.EncodingType encodingType = EncodingUxer.EncodingType.Utf8WithoutBom)
|
||||
{
|
||||
recordSet = new List<Dictionary<string, string>>();
|
||||
resultMessage = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
// 全行読み込み
|
||||
var lines = System.IO.File.ReadAllLines(csvFilePath, EncodingUxer.GetEncoding(encodingType));
|
||||
|
||||
// データ行0件
|
||||
if (lines.Length < 2) return true;
|
||||
|
||||
// ヘッダ行項目分割
|
||||
var header = Regex.Split(lines[0], ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
|
||||
for (var cnt = 0; cnt < header.Length; cnt++) header[cnt] = header[cnt].Trim('\"');
|
||||
|
||||
// データ行件数分
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
// 項目分割
|
||||
var values = Regex.Split(lines[i], ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");
|
||||
for (var cnt = 0; cnt < values.Length; cnt++) values[cnt] = values[cnt].Trim('\"');
|
||||
|
||||
if (values.Length != header.Length)
|
||||
{
|
||||
resultMessage = $"CSV読み込みでヘッダの項目数とデータの項目数が異なります。[CSVファイルパス:{csvFilePath},行番号:{i + 1},ヘッダ行項目数:{header.Length},データ行項目数:{values.Length}]";
|
||||
return false;
|
||||
}
|
||||
|
||||
var record = new Dictionary<string, string>();
|
||||
|
||||
// 全項目
|
||||
for (int j = 0; j < header.Length && j < values.Length; j++)
|
||||
{
|
||||
var key = header[j].Trim('\"');
|
||||
var value = values[j].Trim('\"');
|
||||
record[key] = value;
|
||||
}
|
||||
recordSet.Add(record);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
resultMessage = $"CSV読み込み処理でエラーが発生しました。[CSVファイルパス:{csvFilePath},エラー内容:{ex.Message}]";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string Escape(string value) => $"\"{value.Replace("\"", "\"\"")}\"";
|
||||
public static string Join(params object[] values) => string.Join(",", values.Select(m => Escape(m == null ? "" : m.ToString())));
|
||||
|
||||
/// <summary>
|
||||
/// CSVファイルを読み込み、ディクショナリに変換します。
|
||||
/// </summary>
|
||||
/// <param name="path">CSVファイルのパス</param>
|
||||
/// <param name="dic">出力されるディクショナリ(ファイル無しの場合は空)</param>
|
||||
/// <param name="resultMessage"></param>
|
||||
/// <returns>処理が成功した場合はtrue、例外発生時はfalse</returns>
|
||||
public static bool TryGetDictionaryFromCsv(
|
||||
string path,
|
||||
out Dictionary<string, string> dic,
|
||||
out string resultMessage)
|
||||
{
|
||||
resultMessage = string.Empty;
|
||||
|
||||
// 1. 最初に出力変数を空のディクショナリで初期化
|
||||
dic = new Dictionary<string, string>();
|
||||
|
||||
try
|
||||
{
|
||||
// 2. ファイルが存在しない場合は空のままtrueで返す
|
||||
if (!System.IO.File.Exists(path))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. BOM付きUTF-8を指定してファイルを開く
|
||||
// (Encoding.UTF8 はデフォルトでBOMの有無を自動判別して正しく読み込めます)
|
||||
using (var reader = new StreamReader(path, Encoding.UTF8))
|
||||
{
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
string line = reader.ReadLine();
|
||||
|
||||
// 空行はスキップ
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// カンマで分割 (単純な2列前提)
|
||||
string[] parts = line.Split(',');
|
||||
|
||||
// 最低1列(キー)があれば処理する(2列未満の対策)
|
||||
if (parts.Length > 0)
|
||||
{
|
||||
string key = parts[0];
|
||||
|
||||
// 2列目があればその値、なければ空文字
|
||||
string value = parts.Length > 1 ? parts[1] : string.Empty;
|
||||
|
||||
// 重複キーは後勝ち(インデクサを使うことで上書き保存)
|
||||
dic[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO: あたしがのちほどエラーメッセージ処理を入れる!
|
||||
resultMessage = $"CSVファイル読み込みに失敗しました。[詳細:{ex.Message}]";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user