>>>スミマセン、C#コードをちょっと修正します(翌日)<<<
実は今悩んでいます。
先日カミさんのラップトップ(C:ドライブが64GBしかない!)にWin 11を入れ、サブドライブとしてD:に1TBのMicroSDカードを入れたのですが、やっとD:に膨大な写真データを入れられるとなったものの、ファイル名がデジカメやスマホのシステム作成ファイル名なので「任意の複数ファイルに同一の名前を付けて末尾にシリアル番号を振る(例:"私の車(1).jpg"、"私の車(2).jpg"、...)」ソフトを(カミさんも「そう言うソフトがあれば使いたい」といったので)ネタとして思いつきました。
で、
普段ならすぐに仕様決めに移るのですが、既にSampleBCCSkeltonにANSIベースでRenamerというソフトがある(注)ので、こいつとの棲み分けをどうするか、なども考えなければならないと考えました。
注:これは2020年にBCCSkeltonを再度使い始めた際に、BCCSkeltonの5つ(Project.rc、ResProject.h、Project.h、ProjectProc.h、Project.cpp)の名を一挙に変える習作として作ったので、あまり出来栄えは良くないし、またANSIベースなので面倒なUnicodeファイルパスだと読み込めない可能性がありました。ということで、実はBCC2ECCを使ってUnicode対応版を既に作ってしまいました。
が、
ECCSkeltonにせよ、bcc32c.exeコンパイラーは32bitソフトしか作れないし、C++よりもすでに部品が山ほどそろったC#で作る方が簡単(しかし、簡単すぎて面白くもないのだけども...)なこともあり、C#で新たに作ろうかな?とも考え、ちっとも前に進みません。
ということで、
現在何をしているかというと、
(1)C#でファイルを扱ったことがない(注)ので、「どんな塩梅やろか?」ということで、調査、学習を兼ねて習作を作ってみました。
注:ResWriterとResReaderはファイルの読み書きをしますが、それは特定のファイルを特定の専用メソッドを使っただけで、ファイル一般の処理はしていない、という意味です。なお、今日作ったC#のサンプルのコードを末尾に載せておきます。
(2)ECCSkeltonのUnicode対応Renamerを機能アップさせるなら「こうするぜー」というリソースファイルを遊びがてらに作り始め、現在BCCFormで弄っているところです。
という「二股」で遊んでおり、まだ決めかねています。
どうなるんでしょうか?
【Test_FileOpe.cs】
//////////////////////
//C# Test_FileOpe.cs
//////////////////////
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using System.Linq; // EnumerateFiles を使用するのに必要
using System.Text; // Encoding.GetEncoding を使用するのに必要
public partial class AppForm : Form
{
TextBox txtBox;
Button clrBtn, rdBtn, wrtBtn, extBtn;
[STAThread] //ファイルを開く(保存)ダイアログを使うのでこれは必須
public static void Main()
{
AppForm ap = new AppForm();
Application.Run(ap);
}
public AppForm()
{
this.Size = new Size(640, 480);
this.MinimumSize = new Size(320, 190); //翌日修正箇所
this.Text = "TextBox Test";
this.Load += AppForm_Load;
}
private void AppForm_Load(object sender, EventArgs e)
{
//Clearボタン
clrBtn = new Button();
clrBtn.Location = new Point(ClientSize.Width - clrBtn.Width - 10, 10);
clrBtn.Text = "Clear";
clrBtn.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
clrBtn.Click += Button1_Click;
this.Controls.Add(clrBtn);
//Readボタン
rdBtn = new Button();
rdBtn.Location = new Point(ClientSize.Width - rdBtn.Width - 10, clrBtn.Height + 20);
rdBtn.Text = "Read";
rdBtn.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
rdBtn.Click += Button2_Click;
this.Controls.Add(rdBtn);
//Writeボタン
wrtBtn = new Button();
wrtBtn.Location = new Point(ClientSize.Width - wrtBtn.Width - 10, clrBtn.Height + rdBtn.Height + 30);
wrtBtn.Text = "Write";
wrtBtn.Anchor = (AnchorStyles.Top | AnchorStyles.Right);
wrtBtn.Click += Button3_Click;
this.Controls.Add(wrtBtn);
//Exitボタン
extBtn = new Button();
extBtn.Location = new Point(ClientSize.Width - extBtn.Width - 10, clrBtn.Height + rdBtn.Height + wrtBtn.Height + 40);
extBtn.Location = new Point(ClientSize.Width - extBtn.Width - 10, ClientSize.Height - extBtn.Height - 20); //翌日修正箇所
extBtn.Text = "Exit";
extBtn.Anchor = (AnchorStyles.Bottom | AnchorStyles.Right);
extBtn.Click += Button4_Click;
this.Controls.Add(extBtn);
//テキストボックス
txtBox = new TextBox();
txtBox.Text = GetFiles();
//位置
txtBox.Location = new Point(10, 10);
txtBox.Anchor = (AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Bottom | AnchorStyles.Right);
//サイズ
txtBox.Width = ClientSize.Width - clrBtn.Width - 30;
txtBox.Height = ClientSize.Height - 20;
//その他
txtBox.Multiline = true;
txtBox.ScrollBars = ScrollBars.Both;
txtBox.WordWrap = false;
//FormにTextBoxを追加
this.Controls.Add(txtBox);
}
//終了時処理
protected override void OnFormClosing(FormClosingEventArgs e)
{
base.OnFormClosing(e);
DialogResult dr = MessageBox.Show("終了しますか?", "確認", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if(dr == DialogResult.No)
{
e.Cancel = true;
}
}
private void Button1_Click(object sender, EventArgs e)
{
//txtBoxをクリアする
txtBox.Clear();
}
private void Button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofDlg = new OpenFileDialog();
//ファイルフィルターの指定
ofDlg.Filter = "テキストやC#ファイル(*.txt, *.cs, *.resx)|*.txt;*.cs;*.resx|すべてのファイル(*.*)|*.*";
ofDlg.FilterIndex = 1;
ofDlg.RestoreDirectory = true; //初期ディレクトリへ復帰
ofDlg.CheckFileExists = true; //ファイルの存在チェック
ofDlg.CheckPathExists = true; //ファイルパスの存在チェック
ofDlg.InitialDirectory = "."; // デフォルトのフォルダーの指定
ofDlg.Title = "ファイルを開く"; //ダイアログのタイトルを指定する
if(ofDlg.ShowDialog() == DialogResult.OK) //ダイアログを表示する
{
//txtBoxにファイルを読む
txtBox.Text = FileRead(ofDlg.FileName);
}
else
{
MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
// オブジェクトを破棄する
ofDlg.Dispose();
}
private void Button3_Click(object sender, EventArgs e)
{
//ファイル保存ダイアログによるファイル名取得
SaveFileDialog sfDlg = new SaveFileDialog();
sfDlg.Filter = "テキストやC#ファイル(*.txt, *.cs, *.resx)|*.txt;*.cs;*.resx|すべてのファイル(*.*)|*.*";
sfDlg.FilterIndex = 1; //ファイルフィルターインデックス指定
sfDlg.RestoreDirectory = true; //処理後ディレクトリ復元
sfDlg.CheckPathExists = true; //存在しないパスの指定警告
sfDlg.InitialDirectory = "."; //デフォルトのフォルダ指定
sfDlg.Title = "リソースファイルを保存"; //ダイアログタイトル指定
//ファイル保存ダイアログの表示
if(sfDlg.ShowDialog() == DialogResult.OK)
{
//txtBox内容をファイルに書く
FileWrite(sfDlg.FileName, txtBox.Text);
}
else
{
MessageBox.Show("キャンセルされました。", "キャンセル", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return;
}
//sfDlgインスタンスの破棄
sfDlg.Dispose();
}
private void Button4_Click(object sender, EventArgs e)
{
//終了する
Close();
}
private string GetFiles()
{
string str = Directory.GetCurrentDirectory();
// カレントフォルダ内のファイル名だけ表示(子以下を含めるならSearchOption.TopDirectoryOnlyの代わりにSearchOption.AllDirectoriesを使う)
IEnumerable<string> files = Directory.EnumerateFiles(str, "*", SearchOption.TopDirectoryOnly);
str = "現在のフォールダーは\"" + str + "\"です。\r\nここには\r\n";
foreach (string file in files)
{
str += file + "\r\n";
}
str += "というファイルがあります。";
return str;
}
private string FileRead(string fn)
{
string text = "";
/* 出力UTF-8 :Encoding.UTF8;
出力UTF-16LE:Encoding.Unicode;
出力S-JIS :GetEncoding("shift-jis") */
using (StreamReader file = new StreamReader(fn, Encoding.UTF8))
{
//ファイルを読む
text = file.ReadToEnd();
// ファイルを閉じる
file.Close();
}
return text;
}
private void FileWrite(string path, string data)
{
/* 出力UTF-8 :Encoding.UTF8;
出力UTF-16LE:Encoding.Unicode;
出力S-JIS :GetEncoding("shift-jis") */
using (StreamWriter file = new StreamWriter(path, false, Encoding.UTF8))
{
//ファイルを書く
file.Write(data);
// ファイルを閉じる
file.Close();
}
}
}
/* ご参考-その他ファイル関係メソッド
//フォールダー内のファイルを調べる
Directory.EnumerateFiles(folderpath);
//新規ファイル作成
File.Create(string (filepathname);
//ファイルの削除
File.Delete(filepathname);
//ファイルの移動(ファイル名変更もこれを使う)
File.Move(fromfile, tofile);
//ファイルのコピー
File.Copy(fromfile, tofile);
//ファイルの存在確認
File.Exists(filepathname);
//フォールダー内のフォールダーを調べる
Directory.EnumerateDirectories(folderpath);
//新規フォールダー作成
Directory.CreateDirectory(folderpath);
//フォールダーの削除
Directory.Delete(folderpath);
//フォールダーの存在確認
Directory.Exists(folderpath);
//パス文字列の@-以下が等価となる(エスケープシーケンス\が文字\となる)
string path = "D:\\files\\sample.txt";
string path = @"D:\files\sample.txt";
*/
ps. しっかし、C#って簡単!あまりに簡単すぎて「調べて、試行錯誤する」プログラミングの醍醐味がなくなっちゃいそう。
