野鳥紀トップページへ 野鳥の写真集・総合目次へ 観察野鳥一覧表へ 制作メモのページへ ご案内のページへ 一シギ二タカ三ツグミへ移動 動画集「ビデオカメラと野鳥」のサイトへ移動

VisualStudioメモ

VisualStudioCommunity2019,2022

(200506)フリーのVS2019をインストールしました。
事の始まりは、いつも使っているHSPで、テキストファイルの操作に11分かかる
スクリプトを作った事でした。
これではどうしようもないと思い、C言語か何か、コンパイラを探しました。
結局、VSに挑戦してみる事にしました。
色々かじってみたのですが、Cでは画面が作れない、C++は難しい、
という事で、現在、C#で右往左往しています。
以下は、極めて個人的なドタバタの記録です。
なお、先の11分の件、今は解決しています。
CやC#を調べていくうちに、HSPでの私のスクリプトの欠陥に気付きました。
改良した結果、HSPでも500ミリ秒で終わります。
(220723:)VS2022をインストール


230331
テキストボックスの表示クリアが遅れる

LinkCheckのプログラム実行中、具体的には、
一回チェック作業をして、結果が出まう。
結果の一部は、小さなテキストボックス二つに作業ページ数とリンク数の数字が書き込まれます。

前回のプログラムの改編作業で、何か所かあるローカルフォルダの指定をコンボボックスのプルダウンメニューで選択できるようにしてあります。
以前は、対象フォルダを変える場合は、設定ファイルを書き変えて再実行する必要がありました。
まあ、便利になりましたが、そのせいで問題点が出てきました。

作業ページのボックスには、作業しているページ数が、リンク数は調べたリンク数が表示されます。
一つには、待ち時間を退屈させないための措置です。
1から始まってチェック作業終了時にはその調べたページ数などが表示されているわけです。

この状態で、つまり一回検査した後、再度、検査開始ボタンを押すと、
ほんの一瞬ですが、前の数字が残ったままで作業が始まります。
いえ、感覚的には、他の表示が先で、このテキストボックスの表示の方が遅れているように感じます。

対策は、作業開始ボタンを押した際に、まず最初に、ボックスをクリアして、本来の作業を始めればいいはずです。
冒頭に、textBox1.Clear()を入れるだけの作業です。

これで、毎回、クリアして始まるようになったはずですが、結果は変わりません。なぜかやはり遅れます。
textBox1.Text="";も試しましたが変わりません。

仕方がないので、一旦、他の作業を止めようかと思いました。
この件、以前に調べたことがあって、止めると、その間何も受け付けなくなる、みたいなことが書いてありました。
そこで、クリアした直後に、Application.DoEvents()を入れて見ました
これで改善しました。ような気がします。


230304
観察メモ生成プログラム書き換え

観察メモ生成プログラム書き換えが終わり、こちらを使おうとしています。
ただ、この間の作業が複雑で、総合的なメモを作っておきます。先々、独立したページが必要かもしれません。
万一、この作業の先が見えず、元に戻す場合にも、詳しい作業のメモが必要と思います。
以下、別途ページを作りました。半自動化プログラム書き直し、サイト用のローカルフォルダ変更


230227
FTP、HSP、コマンドオプション

観察メモ関係の自動化プログラムを、C#で作り直そうとしています。
現在、HSPで作ってあるものを使っています。ただ、少し古くなっていて、いまいち勝手がよくありません。
合併写真集など、サイトに後で追加したページなどを処理するために、追加でプログラムを組んでいます。
その追加の実行ファイルを次々に呼び出す形にしているのが気に入りません。一つにまとめた方が管理も楽なはずです。

ページの生成、関連ページの更新など、ページに関する物は作り上げました。
次の段階で、その作ったページをFTPする段階で止まりました。
C#でのFTPがうまくいきません。
FTPはC#では初めての事で、色々ネットを参考にしたり、ChatGPTからコードをもらったりしましたが、一回も成功しません。

そこで、やむなくHSPに戻ることにしました。
HSPでは現在もFTPまで実施しています。
作った観察メモのとその関連のページをアップロードまで実施しているのです。

その既存のプロクラムを利用して作り直しました。
C#のプログラムからHSPで作ったプログラムを呼び出す形にします。
本来は、このようにプログラムを分離しないで仕上げたかったのですが、やむをえません。

変数の伝達は、現行のHSPではファイルにして読み書きしていました。
結構な伝達事項があるのです。
今回はコマンドオプションでやっています。
調べてみたら、コマンドオプションの文字数に制限は見当たりません。
7個のファイル名を渡します。
全部正しく受け取れています。

230220
空白のlabel

VS2022のフォームのlabelは書き込みのできないテキストボックスとして使ってもいます、これが結構重宝します。
ですが、今回は慌てました。

必要な時だけ文字を表示する目的で、初期値をっ空白にしました。
不要な時は画面に何も出ませんのですっきりします。
色々進行していくうちに、少し位置を変えようとしました。
現在位置が出てきません。
大体の位置は分かっていますので、マウスで探しても、位置を動かす十字のカーソルになりません。

今回はネットのおかげにならずに対策を発見できました。
プロパティウインドウの最上段にコントロール名が表示されています。
そこを開けます。開くとコントロールのリストが出てきます。
目的のラベルもありました。番号は憶えていました。
それを選ぶと、位置が分かります。マウスを持っていくと移動用の十字カーソルも出てきました。

今後の為に、当たり障りのないテキストを初期値に入れておきました。

一応、事後でChatGPTにも聞いてみました。
質問、
VS2022のフォームで初期値を空白にしたlabelの位置が見つからないのですが、どうしたらいいでしょうか。

答え、
Visual Studio 2022のフォームで、初期値を空白にしたLabelの位置が正しく表示されない場合は、以下の手順を試してみることができます。

Labelコントロールを選択します。
プロパティウィンドウを開きます。
TextAlignプロパティを"TopLeft"に設定します。
AutoSizeプロパティを"False"に設定します。
テキストを空白に設定します。
フォームを実行してLabelが正しい位置に表示されるか確認します。

これらの手順に従ってLabelの位置が正しく表示されない場合は、フォームのレイアウトに関連する問題がある可能性があります。
その場合は、フォームのレイアウトを調整するために、レイアウトマネージャーを使用することができます。
例えば、Labelコントロールを含むパネルを作成し、そのパネルを適切な位置に配置することで、Labelの位置を制御することができます。

これを試してみましたが、やはりフォーム上では消えます。
下の3行の意味は、残念ながら理解できません。
230212
ChatGPT
巷で騒がれているChatGPTを導入してみました。無料の方です。
アカウントを登録しないと利用できません。
登録にはメアドと電話番号が必要です。
抵抗がありましたが、キーコード類がメールやSMS経由で来ます。やむを得ず登録しました。

当初、質問を入れてもページがバグったりしていました。どうやら無料版だとアクセスが集中することがあるようです。
それでも、しばらく待ってページを再開すると質問への回答が出ています。
状況としては、ネットの検索と同じような感じです。
検索だと、候補がずらーっと出てきて、適当なページを自分で開く必要があり、開いたページの中を自分で探して、回答を見つける、という段取りになります。
ChatGPTでは、まあそのうちの一つが、しかも肝心な部分が表示される、という感じでしょうか。
巷では質問の方法にも工夫が必要とかありましたけど、今のところ、意図しない答えが帰って来たことはありません。間違いだな、と思う事はあります。

ただ、私が思うに一番の利点というか、便利な事は、巷に出回っている、おとりブログ(私の勝手な命名です))に悩まされることがまずない、という事です。
例えばの話です、検索で、有名人の年とか配偶者を調べた時、結果が何ページも出てきます。
結果の上位に、それこそなんでも分かっているようなタイトルのページが並びます。
そこを開くと、延々とページを読まされ、無用な広告を見させられた上に、ページの最後に、質問の答えはよくわかりませんでした、などと書いてあります。
あることが多いのです。あくまで個人的な感想です。
この腹立たしい経験が少なくなるのと思います。

今、VSのC#で、このサイトのページの自動化のプログラムを作成中です。
現在、このサイトの作業の大半は、観察メモのページを追加することです。
観察メモの自動化は、以前、HSPで作ってあり、使用中です。
規格に合わせて写真さえ準備したら、観察メモのページからリンク先のページまで全部作ってくれます。
全部で13ページ程のページを自動的に作成、更新しています。

ただ、古いので多少の不満があります。
これを、C#でやり直しています。
作り方は相変わらずで、ネットでの記事を参考にしてつぎはぎしていきます。
そこで、便利だと言われているChatGPTを導入してみた、というわけです。

以下、一つの例です。
質問は、
「C#でテキストファイルを読み込んでListに変換する方法を教えて」
と打ち込みました。

これまで、自己流のやり方は、
まず、ページを構成しているHTMLファイル、つまりテキストファイルを読み込む。
それを、配列に分解する。
さらに配列をListに変換する。
という段取りでやっていました。

もっと簡単な方法がありそうなものだと思っての事です。
回答が出ました。回答は以下の通りでした。
コードをテキストボックスにしたのは、直接ページにコピーすると、タブが無視され、体裁が悪くなるという一点です。
なるほどと思いました。
私は、ファイルを、File.ReadAllTextで読み込んでいました。
File.ReadAllLinesだと最初から結果を配列に入れ、
それをTolistすれば一行で処理が完結する、のでしょう。

確かに、便利なものです。
検索との違いは、結果のリストから、あれこれ探さなくていい事です
質問の仕方にもよるのかもしれません。
これまで、幾つか質問して、検討違いの回答が出たことはありません。

ただ、今回の結果を利用したかというと、しませんでした。
元のまま、配列、Listという変換手順のままです。
理由は、特に私の作業などでは速さに違いはないだろうという事が一つ、
それに、多分ですが、コンパイラの中では、同じような処理になるのでは、という想像です。
また、配列に変換しておくことで、配列での使い勝手がいい場合もあります。あくまで私の知識の範囲内での事ですが。
元もと、Listとか構造体とかは私の概念にないのです。配列で出来ることは配列でやります。
同じ構造の配列とListがあると便利なことも多いのです。あくまで私の個人的な見解です。

ただ、File.ReadAllLinesというコードがあることと、File.ReadAllTextとの違いなど勉強になりました。

230218
C#で文字列の大小を比較する方法は、と聞きました。
答えは、以下の通りです。これは多分エラーでしょう。

ただ、もう一つの回答も出ていました。こちらは正しく動きました。
どうも、ChatGPTは自信がないときは幾つか答えを出してみる様です。
230221
作業結果を表示するコードを作りました。結果、下のような文字列が帰って来ました。

・・・
・・・
8:sp_mlindex.htm済
9:zyoubitaki.htm済
10:sakura.xml済
11:rss5.xml済

これが気に入りません。桁数を揃えたいと思います。しかも頭に空白を入れて揃えたいと考えました。
昔、文字列の左に"000"や"空白文字"を追加して、右側から切り取る、という方法があったのを、かすかに憶えています。
今は、文字列指定子みたいなものがあるはずだが、と、おぼろげな知識があります。
そこで、聞いてみました。

質問、
C#で頭に空白を入れて数字の桁数を揃えたい
答えは幾つか出てきましたが、私の求める物はこれでした。、
numberにある数字を左に空白込みの5桁で表示するものです。
この書式を使えば数字の桁数を揃えられます。
結果は上のボックスに書き入れました。

ChatGPTは、相変わらず、帰ってこない事も多いです。しかし、再度ページを呼び出すと答えは出ています。

230201
ショートカットキー

まとめてコメントアウト、Ctrl+K、 Ctrl+C
まとめてコメントアウトを外す、Ctrl+K、 Ctrl+U

230118
掲載写真数の計数

我が野鳥紀に掲載している写真がどのくらいあるか、その計数の方法を各種、下のメモに書いています。
一番確実なのは、今作っているC#のプログラムによる計数です。
これについて、再度メモしておきます。

実際の作業は、以下、サイトを構成しているローカルのフォルダで実施します。
サイトの有効なHTMLファイルを全部収集し、リストします。
そのHTMLファイルを順次読み込み、srcタグのある行を調べます。
srcタグの後ろに記述してあるJPGファイル名を収集します。
この時、ファイル名が重複しないようにリストします。
このJPGファイルのリストの要素数が現在の写真集に他なりません。

この作業は文字列の操作になりますが、この作業がC#だととても簡単です。
各種至れり尽くせりのコマンドが用意されています。
C#と限定するのではなく、VSというべきなのでしょうか。それとも最近のプログラミングツールというべきなんでしょうね。多分。

残念ながら、私が知っているのは、他にはHSP程度です。
(過去の単なる経験では、BASIC、COBOL、Z80アセンブラ、C、は使ったことがあります。いずれも趣味の範囲です。)

少し、段取りの細かいことを書いておきます。
本来の写真へのリンクになっているサムネイル写真もあります。
これは計数しません。
サムネイルは元の写真と同じ名前にして、サムネイル専用のフォルダに置いています。
このフォルダ名を調べて取捨選択しています。
作業時間短縮の為に、あらかじめHTMLファイルのあるフォルダを指定しておきます。

指定のフォルダには使用していないHTMLファイルも残っています。
これも分かる範囲で指定しておき、この分は計数から外してあります。

ここ結果が、本日の計数で、
検査したHTMLファイル数:3554
重複なしJPG数(Listの要素数):8043
重複ありJPG数(累計):8341
となっています。

COBOLの思い出(記憶違いがあるかもしれません)
COBOLは勤めていた会社で経理処理だったか売上処理だったかを導入することになって、会社に導入されました。
そこで、少し憶えようという事になって、勉強しました。
確かBASICと違ってコンパイルが必要で、たまに導入元のNECの事務所に行ってオフコンを使わせてもらっていました。
その頃は媒体は8インチFDでした。

COBOLは計算が苦手で、平方根の計算をニュートン法をヒントにしてコードを書きました。
平方根には必要な精度があります。小数点以下5桁まで必要とか、です。
平方根だから、どうせ0とその元の数の間に答えはあります。
COBOLでも割り算掛け算は問題ありません。
その元の数の半分を計算して二乗してみる。
答えが元の数より大きかったら、元の数の1/4で試す。
小さかったら、3/4で試す。
これを繰り返して、必要な小数点以下の桁まで上下が同じになるようにする。
です。
当てのないループですが、結果が出るまでにさほどの時間はかかりませんでした。
意外と大したループの回数にはならなかったと思います。

このコードを見たSEの人がコピーさせてくれとのことで、持ち帰っていきました。
その後何年かして、銀行の金利計算の計算書を見たとき、私の計算方法と同じ誤差が出ていたのに驚いたことがあります。
まあ、どのように計算しても同じ結果になるのだろうと思いますけど。

230116
キーボードショートカットキー

文書の先頭に移動:Ctrl+Shift+Home
文書の末尾に移動:Ctrl+Shift+End
最近は膨大なテキストファイルを開くことが多いので。
テキストエディタ、VSやHSPのエディタ、ブラウザ、このHPBでも効く。

他は知らず、わがPCのキーボードには独立したHome、Endのキーがない。
テンキーの一部と併用してある。Numlockオフの時はShiftが必要ない。
カーソルキーにも書いてあり、多少使い方が違う。

230103
このサイトの掲載写真の計数

わが野鳥紀のサイトに記載している写真の数の結論が出ました。
その前に、この懸案事項に関して、今までに幾つかの計算方法で出した数字があります。
これを、もう一度まとめると、

合併写真集に出している写真の数が、今日の時点で7388枚です。
これは、毎回ページを作りながら計数しますので間違いのない数字です。重複を調べて、同じ写真は掲載していません。
合併写真集は、鳥種別の目次に掲載している316種の野鳥の写真について、野鳥の写真集と観察メモに掲載している写真をまとめたものです。
その際、目次に鳥種ごとの写真の合計を表示しています。プログラムではそれらの合計も計算しています。それが上の数字です。
しかしながら、このサイトには、この他にも写真があります。
写真集には動物などの写真も載せています。この分が上の数字には含まれていません。
細かい所では、このページでも、最下部にVSCodeのエディタの写真を取り込んでいます。この分なども未収集です。

次の計数は、昔作った写真数を数えるプログラムがあります。HSPと最近VSでも作り直しました。この結果が7931枚です。
これは、ローカルフォルダのJPGファイルを数えるものです。
そのままだと、重複、未使用の写真も数えてしまいますので、この数字を別途計算して差し引いています。
ただ、重複数や未使用数を直接は数えていません。誤差があるはずです。

もう一つ、エクスプローラで直接の計算もしてみました。
サイトのローカルフォルダで、「*.jpg」で検索して、その数字からサムネイルと分かっているもの、未使用のもの等を引いたものです。
8071枚となりました。
同じ方法で以前にもメモを作っています。その際の数字が少し違うのは、その時以降追加した写真があるからでしょう。
サムネイルについては、手計算でわかる範囲です。サムネイルだけを置いているフォルダが五つあり、計算しました。1234枚でした。

さて、今回、完璧といえる計数ができました。VS2022のC#で新しくプログラムを作りました。
この昔からのこの懸案の解決には、前に作っていたリンクの検査のプログラムLinkCheckを転用するといい事に気付きました。
LinkCheckではherfとsrcタグを見つけてその対象のファイルがあるかどうかを調べていました。
LinkCheckでは、各ページのタグをひたすら探して対象のファイルがあるかどうかを調べていきます。重複の事はまったく考えていません。
更にはsrcタグの先には、同じ写真もありますし、JPGだけではなく、GIFやサムネイルなども含まれています。

具体的に説明します。
ページでは、
<TD><IMG src="syasin/aigamo020706.jpg" width="640" height="480"・・・
こんな感じのスクリプト?、コード?、行?、になっています。未だに正確な用語を知りません。

リンクチェックのプログラムでは、このsrcというタグを探し、その後ろの写真ファイル名を抜き出し、実際のファルダにそのファイルがあるか調べました。
今回は、その写真ファイル名を抜き出して数えるだけです。その写真があるのはリンクチェックのプログラムで確認出来ていますので。
ただ、今回重要なことは、重複して数えてはいけない、という事でした。

調べてみたら、この問題の解決には新たなプログラムを組む必要もありませんでした。
なんとC#のListに重複を避けて収集してくれるものがあります。HashSet<string>です。
この指定をすると、重複分は取り込みません。本当に便利な世の中になりました。Listの定義を変えるだけなのです。
なお、重複込みList、重複なしListでの速度の差はありません。8000個程のリストですけど。

閑話休題、
前回は、フォルダ内のファイルの収集に再帰で探してくれるコマンドを発見して驚いたものです。
Directory.EnumerateFilesです。
ここまでは、BasicやHSPで再帰の問題に直面しても全部諦めて、総あたりで解決していました。
C#では、VSでは、という事でしょうか、いとも簡単に解決です。
ただし、今回はやはりファイルの収集にDirectory.EnumerateFilesを使いますが、再帰のオプションは使いません。
再帰で探すと、不必要なファイルまで集めてしまいます。必要なフォルダをピンポイントで指定していきます。

話を戻します。
このHashSet<string>のリストに、scrの後ろのjpgとあるファイルのパスのうち、ファイル名だけを分離して取り込んでいけば、重複なしのリストが出来上がります。
幸い、私のサイトの写真は全部に日付を入れています。同じ日の同じ鳥種の写真には枝番を付けています。つまり、同じファイル名の写真はありません。
あと、細かい所で、srcの後ろでjpgとなっていても、除外するものがあります。
サムネイル、バナーとして使っているものなどです。これは集計してはいけません。
幸い、この手のファイルは専用のフォルダを作って置いていましたので、簡単に区別分離できました。

さて、その結果です。今日の段階で掲載写真が8046枚となりました。
走査したHTMLファイルの総数は3562ページ、
結果が出るまでの時間は23秒です。キャッシュでしょうね、2回目からは5秒程度です。

210106
プログラムを使って単年度の観察メモのページを調べ、エクスプローラで直接JPGファイルを数えたものとの比較をしてみました。

観察メモの写真はフォルダを年ごとに分けてありますので分かりやすいです。。
エクスプローラの数字が若干多い場合は、使用していない写真が残っているという事になります。
使用していない写真がある原因は、途中で写真を入れ換えた場合です。削除するのももったいないので残してあります。

写真集のエクスプローラの欄は、写真集の写真があるフォルダを合計してみました。未使用分が含まれています。

ルートのプログラムの欄は、正確にはルートに置いているページに掲載している写真の数です、175枚です。
ルートのエクスプローラの欄は、上で調べたフォルダ以外を大まかに指定してみました、あまり意味はありません。

合計の欄は、上の数字を単純に合計した数字です。

全体のプログラムの欄は、今回の結論となるプログラムで数えた数字で、重複分なし、未使用分なしです。
全体のエクスプローラの欄は、ローカルのサイト全体のJPGの数です。重複分未使用分が含まれています。

   年  プログラム  エクスプローラ  備考
観察メモ           2023 6 6  数字が微妙に違う場合は、未使用分です。以下同じ。 
2022 340 340  
 2021 453 453  
 2020 504 504  
 2019 546 548  
 2018 562 563  
 2017 551 551  
 2016 455 458  
 2015 535 539  
 2014- 2929 3009  
 写真集  1218 1224  
 ルート 175 351  
 合計  8274 8546  ここは、単に上の欄の合計です。重複分が考慮されていません。
   
全体  8048 9973(参考) プログラムの数字が今回求めた数字です。
エクスプローラの数字には、サムネイル専用のフォルダ等、
個別には調べていないフォルダが含まれています。

以下、参考までに、
現在は三日間隔で観察メモを一ページ作り、通常3枚の写真を掲載しています。
2021年の7月以前は二日に一ページに写真3枚のペースでした。

ですので、2021年より前は一年に550枚前後、今後は一年に360枚前後の写真になるはずです。
9000枚になるのは3年後でしょう。

総合的に見て、プログラムの結果を裏付けるものになりました。

230108
観察メモを一ページ追加しました。写真は3枚です。
追加の前後で枚数を調べました。
前、8048枚
後、8051枚、
となりました。
正しく動いています。

懸念材料に気付きました。
プログラムでは指定フォルダのHTMLファイルを全部収集して調べています。
HTMLファイルで使っていないものが幾つかあります。
原因は、HTMLファイルを手書きで変更することがたまにあり、その際に、元のページを名前を変えて残しておく時があります。
普通は、同じ名前でバックアップ専用のフォルダにコピーしておきますが、面倒な時、簡単な変更の際にそうしています。
これが収集されJPGがカウントされます。
こういう場合のJPGファイルは同じものになります。プログラムでは重複しているJPGは無視しますので問題ないはずです。
ただ、未使用のHTMLが古くなってくると、古いHTMLが未使用のまま残っていると、結果が狂うという事があり得ます。

230110
スマホ版のページも調べてみました。
今回、本体のこのサイト用に作ったC#のプログラムでスマホ版のローカルサイトを読み込ませます。
スマホ用に作った独立したサイト用のフォルダです。
結果は重複なしの枚数が7384枚、重複ありで計算すると7391枚とでました。

もう一つは、毎回の観察メモで使っているHSPのプログラムで計算させます。7391枚となります。

さらに、PC版にある合併写真集のページの合計です。
結果は重複なしの枚数が7384枚、重複ありで計算すると7392枚とでました。

困りました。本来は同数になるはずです。
双方の結果から、HSPの結果は合併写真集には7枚か8枚の重複がある、という事になります。


230102
Visual Studioにサインイン、 Community 2022

VSを起動する際、時々、Visual Studioにサインイン、というダイアログが出ます。

同期、共同作業がどうのこうのと、私には関係がありませんので、いつも無視しています。

ネットには、ライセンスの認証をしないと、30日間の試用期間しか使えません。という記事を見かけます。
VSC2022は昨年10月にインストールしました。しかし、まだ使えています。
意味不明です。
Win11自体はMSアカウントで使っています。そのせいでしょうか。
だとしたら、あまり意味のない事のように思います。

230116追記
同じダイアログがまた出ました。
そのままにしておいて、再度調べてみました。
今回は正解を見つけました。
このページです。
ここに、Visual Studio Community を使う場合にサインインする必要はありません。
と書いてありました。

確かに、Win11や10のPCを複数登録しています。PCが幾つかある状態です。
Win11をMSアカウントで使っているのだから、ついでに同期したらどうだ、という事でしょうね。
しかし、VSを使っているのはこのPCだけです。


230101
写真処理、Kabview

元旦、Kabviewで写真の処理をしようとしたら、
今月分のフォルダ:
F:\・・・
等が作ってありません。
先月のフォルダで作業します。
とのダイアログの御託宣でした。

完成が22年8月なので、やむを得ないか。
チョットコードを見てみた。
場所は分かったが、考えるのも面倒、
一年に一回の事なので、記録ファイルを手書きで書き換えることで対応する。
記録ファイルの、17最新のフォルダを探すフォルダ:の項の、2022を全部2023に書き換えるだけ。

221225
掲載写真数の計数

このサイトのトップページにサイト内の総写真数を表示しています。今、概数で8000枚としています。

わが野鳥紀のサイトに何枚のの写真を掲載しているかは、幾つかの方法で算出しています。
サイトもいたずらに膨れ上がってしまい、事実上、正確には計数出来ないのです。

合併写真集の写真の計数
最も厳しい計数は、合併写真集のページを作る際に計数しているものです。
合併写真集は、普通の写真集の写真と観察メモに掲載している写真をまとめたページです。

このページで、各鳥種ごとの写真数を各鳥種の目次に掲載しています。
通常の写真集と観察メモの写真との双方に同じ写真を重複して掲載しているものがあります。
合併写真集を作る際には、その重複分は除いています。
ですので、各鳥種ごとの合計を手計算で足してしまえばいいのです。現在316種あります。

この総計はもっと簡単に分かります。総計は合併写真集を更新する際に、そのプログラムで毎回計算しています。
この合計の枚数が今日の時点で7382枚です。
これが合併写真集全体に掲載している写真の総計です。
また、プログラムでは重複している写真は省いています。重複分も重複分の合計も同時に計算しています。

ここでの問題は、合併写真集に掲載していない写真もあることです。
通常の写真集にはある動物の写真などは合併写真集を作っていません。
それに、単独のページの写真なども計算していません。
ですので、実数はもっと増えます。

写真数を計測するプログラム
そこで、合併写真集とは別途に全部の写真ファイルを計数するプログラムを作ってあります。
2年ほど前にHSPで作りました。
ローカルで写真を置いてあるフォルダを調べ、そこのJPGファイルを逐一計数していくものです。
この結果が今日現在で8590枚です。
こちらではサムネイルの入っているフォルダなど計数していけないフォルダは除外してあります。

こちらにも問題があります、
先の重複分も計算されてしまいます。
重複分は先に計算してあります、178枚です。

他には、未使用分、サイトに掲載していない写真の事です、がフォルダにあれば計数されてしまいます。
写真を入れ換えた際等に古い写真を削除せずに残してある場合があります。
実用上はバックアップの意味もあり、何の問題もありません。ただ、ローカルやサーバーの容量が無駄に増えるだけです。
しかしながら、今回の計数ではこれを除外する必要があります。

この未使用分は、HPBのビジュアルサイトビューで集計できます。大変ですけど。
このHPBの機能の一つで未使用分が集計されます。
ただ、出てくるのは写真ファイルに限らず、HTMLファイルとか要するにサイトでリンクのないものが全部列挙されます。
そこで、その中のJPGファイルだけ手計算で数えていきます。
この分が最新で487枚でした。この分も差し引きます。

つまり、差引で掲載数は7925枚です。
そういう事で、トップページの掲載数を8000枚としています。

VS2022
今回、このプログラムをVS2022で作り直して見ました。
アルゴリズムはHSPとまったく同じです。結果も全く同じです。

まず、ローカルサイトの全フォルダを列挙します。
その中で計数対象のフォルダ、写真集と観察メモなど写真のあるページにある写真のフォルダを抜き出します。
これは手作業なので、作業一回目は面倒ですが、そんなに変わるものではありません、記録が残りますので二度目からは簡単です。
それに、HSPのプログラムの動作結果に、記録として残っています。
これを拡張子がjpgとなっているもの、という条件で集計していきます。

HSPとVSの違いは、VSの方にはフォルダ内を再帰で探すコマンドがあることです。
例えば、観察メモのページは年次別にフォルダが分かれていて、更に一ページの観察メモごとに写真のフォルダが分かれています。
このサブフォルダの数は、今年の分で、現在、115個あります。
これを計数する際にHSPではいちいちフォルダを探して計算しています。
VSでは、一つのフォルダを指定しておくと、その下のフォルダは全部探してくれます。
とても楽ですし速いです。
あ、HSPでも再帰を組めばいいのだと思います。私には理解できませんけど。

HSPとVS2022の実行時間の比較
実行時間を比べてみました。
CPUは、Core i5-10400、OSはWin11、
フォルダは通常のHDDに入っています。多分、キャッシュは効いているのだと思います。

24のフォルダから約8000枚程のJPGファイルを計数する時間です。
HSPでは40秒かかります。
VS2022では1秒か2秒です。

直接の計算(221227)
以上の事を踏まえて、少し手間を踏めば、直接計算できる事がわかりました。

まず、ローカルサイトのフォルダで、エクスプローラーの検索窓で、*.jpgで検索します。
この結果では、今、9961枚となりました。
これは間違いなく写真ファイルの総数なのですが、困ったことに、上にあげたサムネイルとか重複分、未使用分の写真も含まれています。

今回の問題はサムネイルです。サムネイルは各種の目次に置いてあります。
幸い、これは実数を計数出来ました。サムネイルが5つのidxフォルダにまとめてありました。
442+327+12+112+341=1234枚です。これが実数で、これを差し引きます。
また、逆に普通の写真集のページには1234枚の鳥の写真があるとも言えます。

重複分は、普通の写真集と観察メモに同じ写真を使っているケースです。
これも別途計算してあります。合併写真集の更新時に副産物として算出されます。重複しているものは178枚です。

未使用分はページに掲載していない写真です。
未使用分は、上で説明しある通り、HPBで集計しました。今、487枚です。
ですので差引、総数は8062枚となります。
まあ、いずれにしろトップページの8000枚でいいでしょう。

221227追記
この写真数の計数は、前に作っていたリンクの検査のプログラムLinkCheckを援用するといい事に気付きました。
LinkCheckではherfとsrcタグを見つけてその対象があるかどうかを調べていました。
今回は、そのsrcの対象の数を数え、重複分を外すだけです。
こうすると、直接の写真数が出るはずです。
現在、その作業中です。

221222
アンケート

いつものようにVSを起動したら、突然アンケートのウェブページが開いた。
英語だった。
Google翻訳を使って答えていった。
途中、文字入力の質問では、何が欲しいか、というような内容だったので、Japanese versionと答えた。
途中、メアドを要求されたが空白にした。

2212118
新規プロジェクトの作成

久しぶりにVSを立ち上げてみたら、新規プロジェクトの立ち上げの段取りを忘れていた。
下のメモを見て、何とか作り上げたが分かりにくい。
よって再度メモ。
(230124再確認した。)

VS2022(Community)を立ち上げる。
新しいプロジェクトの作成をクリック

テンプレートを選ぶ画面になる。
ここで、C#、Windows、デスクトップ、
を選択しておく、と選択肢が減るので楽なのだと思う。

数ある選択肢の中で、
C#、Windowsフォームアプリケーション(.NETFramework)、
WindowsForms(WinForms)ユーザーインターフェイスを含むアプリケーションを・・・、
C#、Windows、デスクトップ、
を指定して、次へをクリック、

新しいプロジェクト云々の画面になる。
そこで、プロジェクト名(今回ならJpgCount)を書き込む、
場所は、今なら、G:\・・\VS2022\CSを指定する。
ソリューションとプロジェクトを同じディレクトリに配置する、はチェックしない。
その下に、フレームワークを選ぶプルダウンメニューがあり、これまで4.7.2を選んでいた。
プルダウンには,4.8もあり、プログラムと機能を調べたら、4.8も入っている模様だったので、
4.8、にしてみた。

これで作成すると、
G:\・・\VS2022\CS\Kansatum\Kansatumの下にbin等のフォルダができる。
slnファイルは、G:\・・\VS2022\CS\Kansatumの下に(このフォルダ内に)出来る

 注意点、
 場所の欄に、G:\・・\VS2022\CS\Kansatumと指定すると、binフォルダはG:\・・\VS2022\CS\Kansatum\Kansatum\Kansatumの下に作られる。
 フォルダ名が三つ並ぶ、これは無駄、バックアップするときはKansatum\Kansatum\binでいい。多分。230124確認。

途中、サインインしろとダイアログが出たが、今のところ無視している。その後は出ない。
ネットではサインしないと30日しか使えないとあるが、ちょうど2か月前にインストールしています。

221219
たまに、フォームウインドウでツールボックスとプロパティウインドウがあるのに、中身が何も表示されない時がある。
一回、コードを出してフォームのウインドウに戻ると中身も表示される。

221220
ツールボックスが画面を占有していて、フォーム画面にツールをドラッグできない。
解決方法はボックスをドラッグすると、例の配置画面が出てくる。右側のボックスにドロップ

220831
イベントハンドラーコードの削除

この項、正しい用語が分かりません。的外れな事を書いているかもしれません。私はいつも試行錯誤なのです。

要するに、例えばボタンをクリックした時の動作を記述する関数を削除したい時の段取りです。
ボタンの動作なら百パーセント使いますので問題はあありません。ところが間違ってラベルにこれを作ってしまった場合です。
ラベルをクリックした時の動作です。

フォーム画面で、部品をダブルクリックするとその部品をクリックしたときのイベントが作られます。
確認の為、再度、恐る恐る試してみました。
private void label2_Click(object sender, EventArgs e){}
というような関数が作られています。Labelに、です。イベントハンドラーと言うのでしょうか。

こうなると、生成された関数を削除するだけではうまくいきません。他にも色々コードが生成されているみたいで、まずいことになります。多分。
そのままにしておいて、コードを書き込まなければ、何も起こりませんので、見ないふりをする手もあります。
ただ、ちょっと抵抗があります。
以前にも何度かこれをやっていて、確か正しい削除方法が有ったはずだがと調べました。

そこで、正しい削除方法は、
プロパティウインドウにあるイベントボタンをクリックし、プロパティウインドウをイベントウインドウに変更します。
その中にある問題のイベントを見つけます。
このイベントの右クリックメニューにリセットという項目があります。
これをリセットすると、コードとその関連の物が消えます。多分。
先の関数は消えています。終了時、実行時にもエラーが出ませんので、これでいいのでしょう。


220826
C#、Directory.EnumerateFiles
Directory.EnumerateFilesというとても便利なメソッドがあります。
指定のフォルダ以下のファイルを全部収集してくれるものです。
普通は私の理解の外の再帰を使ってやるものです。多分。
これを使うと、一発で指定のフォルダ以下のファイルを収集できます。

これを私はLinkChexkのプログラムで使っています。
調子に乗って色々試していたら、突然例外を吐いてしまいました。
調べてみたら、アクセス権のないフォルダがあると発生するとの事です。
ゴミ箱がこれに当たります。ゴミ箱のあるフォルダを指定すると発生します。つまりルートです。

対策も調べました。
つまり、ルートではこのメソッドと使わないようにしたらいい訳です。
directoryInfo.Rootを使うと処理できるみたいです。
使えばいいのでしょうが、今いち良く分かりません。
そこで、フォルダ名が3文字以下ならルートが指定されているとして対応する事にしました。
ルートはC:/みたいな形式ですので3文字以下なら警告を出すで、必要十分だと思います。

一応の対策は出来ましたが、ここで冷静に考えたら、サブフォルダにアクセス権のないフォルダを作られたら駄目だと気付きました。
その様なことはめったにないでしょうから、まあいいかと思います。
一応、Application.DoEvents()をあちこちに配置していますので、めったな事はないと思います。


220824
C#、マイコードのみに関する警告

VS2022で警告が出ました。
Releaseモードでビルドした時です。同じ状態でDebugモードの時は出ません。
内容は、
「リリースビルドLinkCheck.exeをデバッグ中です。コンパイラによる最適化を使用するリリースビルドで[マイコードのみ]を使用すると、デバッグ機能が低下します。(例:ブレークポイントがヒットしない)。」
となっていました。
ネットで調べてみると解説が見つかります。しかし分かりません。
対策は、[マイコードのみ]を無効にして続行、を選べばいいとの事で、その様にしました。意味不明です。

220820
C#、実行ファイル名、x64

プロセス名と言うのでしょうか、タスクマネージャーでプロセスタブの所にリストされるアプリの名前です。
これが、コンパイルした(?ビルドした)実行ファイル名と違っています。

原因は良く分かりませんが、古いプロジェクトをコピーして、名前を変更して新しいプロジェクトとして作業すると発生する様です。
元のファイル名がそのまま残ってしまっています。動作などに支障はありません。
修正方法は、以前調べて下にメモしています、再掲すると、

プロジェクト名のプロパティから入ってアプリケーションというタブがあります。
そこに、アセンブリ情報というボタンがあり、
クリックすると、タイトル、と、製品、という項目があり、そこに旧ファイル名が残っていました。
見た感じ、変えても構わないかな、という風に見えました。
恐る恐る、新しいファイル名に変更して、実行してみました。
この状態でタスクマネージャーを見ると、めでたく新ファイル名に変わっていました。
この変更に関する影響については、全く見当が付きません。

VS2022は64ビット番だとどこかで見た気がしますが、実行ファイルは相変わらず32ビット版で出来上がっています。
同じくタスクマネージャーのプロセスに32ビットと表示されています。
古いプロジェクトをコピーして使っているからでしょうか。
64ビット版に変更しました。
やり方は、メニューのビルド、構成マネージャー、プラットフォームでx64を指定する、です。

220806
C#、プロパティウインドウ
コードを見直している際、プロパティウインドウを見たい時があります。ボックスがどこに配置されているかを確認したいときです。
これが簡単ではありません。
いえ、私が知らないだけだとは思います。それらしい所をクリックしても出てきません。
ウインドウそのものは出てきます。起動時に出ていたりするのです。ただ、各項目が表示されません。
プロパティウインドウはメニューの表示にあります。
多分、表示メニューで表示させるのだと思います。表示されるときもあります。表示されない、枠は出るけど項目が何も出ない事があります。
消したり出したりしているうちに項目も出てきます。

試行錯誤の結果、大体の動きが分かりました。
フォーム画面で終了すると、ほぼ、プロパティウインドウなども前回の画面が保持されます。
コード画面で終了して、再度立ち上げると、コードが表示され、プロパティウインドウなど空白のままです。これは仕方がないかもしれません。
続いてフォームを表示させます。
プロパティの枠はありますが、やはり中身は空白です。内容は表示されません。
そこで、一度、コードのウインドウを表示させ、再度フォームを表示させます。
すると、プロパティの各項目が出てきます。
ツールボックスも同じです。

220723
Visual Studio Community 2022

VS2022が出ています。2019との競合を心配しましたが、共存できるそうです。思い切ってインストールしてみました。
丁度、下のメモで書いている自作の写真ビューアを作り変える事にしましたので、この際、導入してみることにしました。

インストールは簡単に終わります。途中、インストール項目(コンポーネント、ワークロード、機能)を選ぶ画面があります。
このインストール項目、という言葉が素人には分かりにくいものです。
まあ、VSで何のプログラムを使うか、という事だろうと思います。この機能は後で追加できるみたいなので、.NETデスクトップ環境だけ選びました。
多分ですが、フォーム付きのC#を使うにはこれで充分だと思います。
インストールは数分で終わりました。

インストールが終わっても、デスクトップアイコンが生成されていません。何か見落としたかもしれません。
まあ、これは手動で作れます。
Windowsのスタートメニューにある全てのアプリにVS2022も登録はされていますので、そこからファイルの場所を探します。
そこにそれらしいショートカットが有ったので、デスクトップにコピーしました。正解でした。
この時気付いたのですが、VS2022はProgram Filesに、VS2019はProgram Files(x86)にインストールされています。64ビットでしょうね。
結果、2019と2022のアイコンが並んでいる状態です。

2022、2019、それぞれのアイコンから起動してみました。起動画面のどちらにも同じslnファイルがリストされていました。
つまり、それぞれのVSから起動したい場合は、このアイコンから立ち上げ、リストからslnを指定すると良いわけです。

直接、slnファイルから起動すると、一回目、どちらかを選ぶよう促されました。2022を指定しました。
しかし、これが固定されません。2022が立ち上ったり2019だったりします。
混乱していますが、脈絡なくデスクトップアイコンで立ち上げたりしています。そのせいでしょうか。
slnファイルの右クリックメニューから選ばないといけないのかもしれません。

一回立ち上げてしまうと、次回からはVSの起動画面にリストされます。
この時、ファイル名やフォルダをよく見て指定すると、意図するVSで編集できます。

無事起動しても、当初、2022の場合、コード画面が出てきませんでした。
コードを開いた状態で終了し、再度立ち上げたとき、そのコード画面が消えています。
これは、タブの端にある釘みたいなやつをクリックすることで解決しました。

当初は、slnファイルを含む作業フォルダを2022と2019用とに分けて作り、それぞれのslnファイルを右クリックメニュー等で2022か2019を指定しておけばいいのだろうと思っていました。
つまり、フォルダを分けることでVSのバーションを変えられると思っていました。
違います。slnファイルから起動すると、ファイルがどこにあろうと最後に指定したVSが起動します。
こうなると、フォルダを分ける意味がありません。

まあ、今更、無理に古いVSを使う事が意味のない事で、新しい方を使え、という事なのでしょうね。

220804
ツーボックスやプロパティウインドウが出てこず、困りました。
コードを見直していて、テキストボックスなどの位置を調べています。この際、プロパティ云々が出ていれば簡単です。
表示メニューにいありました。配置はドラッグで適当な位置に置けます。その際、画面に十字架みたいな模様が出て来るので、これにドロップすると、基本的な配置が決まります。

220820
リンクチェックのプログラムの見直しをVS2022で始めました。
全て試行錯誤なのでなかなか進みません。
まず、VS2019とVS2022は独立しているようです。

今回は同じフォルダを使って作業しました。面倒だったので。
VS2019で立ち上げると、具体的には、VS2019を立ち上げ、最近開いた項目にリストされているLinkCheck.slnを指定すると、2019で作業していた状態で立ち上ります。
VS2022で同じ様にリストから立ち上げると、初期状態というか何もタブが出てきません。
どうやら、作業状態は全く独立して保存されている様です。
そして、タブの状態は全保存すると、次回再現されます。全保存が大事です。
Vs2022のリストから立ち上げて、終了。次にそのslnファイルから立ち上げるとVS2022で立ち上ります。

あとは、フォームのプロパティウインドウですが、何度か書いていますが、メニューの表示にあります。
今回、出るには出たのですが、画面全部を占領していて困りました。
以前のメモで、タブの配置はCtrl+ドラッグで指定できるとしていて、おぼろげな記憶もあったのですが、これがうまくいきません。
今試すと、単にドラッグだけで良いようです。マウスカーソルをタブの最上部でドラッグを始めると、画面中央に位置を示す十字架みたいなマークが出てきて、カーソルをその位置に当てて放します。すると、該当する位置に配置されます。

64ビッ
そういえば、実行ファイルを64ビット版にするために、メニューのビルド、構成マネージャー、プラットフォームでx64を指定する必要がありました。
2022の場合はどうなるのか調べてみました。2022で実行してもタスクマネージャで32ビット版となっています。

LinkCheckのプログラムでは、2019の時x64の指定をしていましたのでそのまま残っています。
実行ファイルもx64/binのファイルが更新されています。
作業フォルダをコピーして、2022版で始めたプログラムはx64フォルダは出来ていません。

220923
古いものは2019で、と思っていましたが、久しぶりにslnファイルを動かしてみると2022が起動しがちになっている。
いや、2022しか動かない。2019から呼び出すと2019も使えるが、この際全部2022で動かすことにする。
最初に、コードなどのタブが表示されない状態で起動するが、何とかなるだろう。
せっかく2022というフォルダを作ったが、無意味なった。2019のフィルダでもVS2022を起動させる。

どこかにメモしたつもりだが見つからない。
フォーム(フォームデザイナー)を表示させる方法は、
ソリューションウインドウ(左側の関数類がリストされている窓)のform1.cs部分の右クリックメニュー
にデザイナー云々がある。


220722
C#、写真ビューアを任意のディスプレイで、プロジェクトのフォルダのコピー
多分、現在の写真ビューアは私の23インチのディスプレイにのみ対応になっているはずです。
これを買い換えることもあるかもしれません。そうなると、今一番活用しているプログラムが使えなくなります。
この際、多少ディスプレイを変えても動くようにしておこうと思います。

そこで、現行のソリューションを、というのかプロジェクトというのか、要するに元のプログラムの作業フォルダをコピーして、そのコピーしたものを新しい名前に変更して、これを修正変更していこうと思います。
作業フォルダをコピーする、フォルダ名を変える、実行ファイル名、ソリューション名、プロジェクト名を変える、という作業です。
このあたり、どうにもこうにも、未だに用語が分かりません。

この作業は、以前、何度か実行していて、偶然かもしれませんが、うまくいっています。
フォルダごとコピーして、フォルダ名を変更して、最終的にそのフォルダ名で実行ファイルが生成され、実行されるようにしました。
下にその時のメモ(201022他)があり、今回もその通り実行して、結果うまくいきました。
途中、エラーが出ることもありますが、修正、保存を繰り返すと、最終的には問題なく起動できるようになります。
slnファイルは、作業の途中で自動的に作り直されます。古いslnファイルは残っています。消えることもあります。

単に、バックアップを作るのはもっと簡単です。
slnファイルのあるフォルダごとコピーするといいです。slnファイルを変なフォルダに作らないようにします。
プロジェクトのあるフォルダの上のフォルダごとコピーすると大丈夫です。


220304
リンクチェックと鳥名の変更

今回、鳥名を変更する必要が出てきました。
発端は、このサイトをご覧になった方からの指摘で、ハジロコチドリとある物の一部がミズカキチドリだという事でした。
調べてみるとその通りで、私としても嬉しいことに一種追加です。

ただ、サイトの修正作業が大変でした。
自動化のプログラムがほとんど使えません。手書きでの修正になりました。
都合38枚のページを書き換えました。
私のサイトは、とにかく目次が多いのです。50音順、分類順、スマホ版、PC版と、細かく分かれています。

この作業の際、少し前に作ったリンクチェックのプログラムがとても役に立ちました。
HPBにリンクチェックの機能があります。しかしこの機能がうまく動かなかったり、時間がかかったりします。
ですので、それならとC#で作りました。
このプログラムが出来上がったタイミングでこのミズカキチドリの作業が発生しました。
具体的な作業は、ハジロコチドリとしていたものの一部をミズカキチドリへ移動します。
当然、新規の鳥種です。何種類もある目次に新しい鳥種を追加していきます。
この作業の過程で、リンク切れがないか調べます。
リンク切れがあるところが必要な修正箇所です。
我ながら良くしたもので、エラーがあればページ名と行位置を表示するようにしています。
これを数回繰り返して、リンク切れをなくしました。


220123
C#、文字コード、SJIS、UTF-8
リンク切れチェックのプログラム中で、20行ほどのテキストファイルの文字コードを判定する必要がありました。
ネットを調べると、色々参考になる記事やメソッドが紹介されていますが、残念ながら私には理解できません。
ただ、完璧に判定するのは難しい、という解説もありました。
また、HTMLファイルは最近ではUTF-8Nが基本です。
ただ、わたしのサイトは開設当時の主流でしたShift_JISで作っています。
そこで、この二つ、文字コードはShift_JISとUTF-8Nしかないと限定して判別することにしました。
これ以外の文字コードだったら中断することになります。
こうしてしまうと簡単です。
しかも、調べる対象は20行ほどの小さなファイルです。中の文章も決まっています。

まず、Shift_JISと仮定して、System.IO.File.ReadAllText(, )で読み込んでみます。
読み込んだテキストに、特定の文言があるかないかで判別します。本来、必ずあるべき文字列です。
その特定の文字列が見つからない場合は、文字コードが間違っているか、その文字列がミスで間違っているかです。
この際は、一応、文字コードが違うと判断して、もう一回、今度はUTF-8Nで読み込んでみます。
これで、その特定の文言があれば、UTF-8Nだと判断します。
こちらでも文字列が見つからない場合は、第三の文字Iコードだと判断することにしました。
もちろん、比較する文章が書き間違っているという事も考慮には入れます。

この状態で、色々と試しました。
Shift_JISとUTF-8Nの判定は期待通りに出来ました。
例えば、作為的にEUCで試すと、どちらでもないと判定します。

ところが、UTF-8(BOM付き)で試すとShift_JISだと判別されます。
読み込んだファイルを表示させても文字化けしていません。
UTF-16でも同じです。Shift_JISと判断されます。

つまり、文字コードがUTF-8(BOM付き)のテキストを、Shift_JISモードだとして読み込むと、正しく読み込まれます。
これは、System.IO.File.ReadAllText(, )がShift_JISでもUTF-8N以外のUTFでも、正しく読み込めているという事になります。
正しい結論かどうかは、私の知識では分かりません。


220122
GB,MB,1024

1B=1024Bというのはよく聞くことですが、
自分で作っているプログラムで、枝葉末節ではあるのですが、特定のフォルダの容量を表示する部分がありました。
プログラムでの表示は0.828GBとなっています。
ある時、ふとそのフォルダのプロパティを見ました。
容量が表示されています。こちらでは848MBとなっています。
一瞬と言いますか、いえだいぶ長い時間考えました。同じ数字になるのでは、と思ったのです。
どちらかが間違っていないかと何度もやり直してみましたが変わりません。

そこで気付きました。小数点表示でも一方の単位はGBなんだという事です。
先の数字を掛けるか割らないといけません。
0.828GBX1024=848MBです。


220118
C#、リンク切れチェック、全角、文字コード
文字コードで試行錯誤しています。
文字コードは、Shift_JISとUTF-8Nには対応させました。
ここまで試した事で、文字コードが違うHTMLファイルを読みこんだ時でも、動作に問題はなく、結果の表示で文字化けするだけだと思っていました。

色々と試しているうちに、例外が発生しました。
原因を調べると、全角のURLのリンクの正誤を調べた時、発生しています。
厳密に書くと、指定と違う文字コードで全角URLをチェックしようとすると例外発生する場合があります。
漢字コードの中にコントロールコードとみなされるものがあったのでしょうか。
文字コードが正しければ、全角URLでも正しく判定します。

そこで、思い当たることがあり、例外の発生する検査前に、URLの形式チェックをしてみました。
URLに使っていけない文字などがあればその時点でエラーとしました。
結果、これで、例外は発生しなくなりました。
全角URLでも、正しく判定します。


220117
リンク切れチェック、サーバー応答なし

今作っているリンク切れチェックのプログラムで突然、帰ってこなくなりました。
debugモードでもrelease版でも同じです。
release版では応答なしになります。強制終了です。
場所は分かります。外部リンクの正誤を始めて二つ目の位置で止まってしまいます。

例によって、外部リンクチェックの直前で止めて、収集してある外部リンクのリストを調べました。
リストの二つ目に我がサイトのトップページのURLが並んでいました。

そこで、ブラウザで表示させようとすると様子がおかしいのです。
Chromeでは何とか表示されますが、いつまでも読み込みが続いています。
Edgeでは表示されません。
そこで気づきました。
サーバーが落ちているようです。
知り合いで、さくらサーバを使っているところを知っています。やはりそこも表示されません。

原因ははっきりしました。サーバーが応答しないので帰ってこないのです。
サーバーはその後、小一時間で回復しました。

ただ、疑問が残りました。
今まで、外部リンクのリンクミスがいくつかあって、このプログラムで発見して、逐次修正してきました。
ただ、その時は、ちゃんとエラーを確認でき、エラー分のリストに入れて表示することが出来ています。
現在も、プログラムの動作確認用に架空のURLを組み込んだページを作っています。
これは、はっきりエラーが帰ってきて、分類でき、応答なしになることはありません。
さくらのサーバーが中途半端に落ちていて、返事待ちを続けていたのでしょうね。
これは勉強の必要な問題ですが、どうしようもありません。保留です。

220114
C#、リンク切れチェック、文字コード、リンクタグ
リンク切れチェックのプログラムは、既に稼働中なのですが、改善点が色々出てきます。
直近では、2点、UTF-8N(文字コード)への対応と、リンクタグの整理、です。

文字コードの判別は、調べてみたら、完璧にはなかなか対応できない、と書いてあります。
更には、付け焼刃の知識で、コードを引用させてもらったりして試しても、当初はうまくいきませんでした。
仕方がないので、Shift_JIS前提で作業していたものを、UTF-8Nだけには対応させたいと考えました。
改行コードはどちらもCRLFです。(この改行コードを同じにする、事はとても大事です。)
現在ではHTMLは、このUTF-8Nが主流と書いてありますので。
Win10もUTF-8Nが標準、とかの記事もあります。

設定ファイルをフラグとして使う事にしました。
考えた方法は、まず、設定ファイルをShift_JISで読み込んで、失敗したらUTFで読み直すことにしました。
この二つに限定しましたので、UTFで失敗したら終わりです。
更に、HTMLファイルの文字コードは、設定ファイルの文字コードと同じだと推定します。

この点、画面で選択するのが本筋ではないかと考え、色々試したうえでの結論です。
設定ファイルを作っているので、HTMLファイルの文字コードは画面で指定したとしても、前段階の設定ファイルの文字コードはどうするのか、となります。
それなら、設定ファイルの文字コードをHTMLに合わせたら簡単です。

ここまでは何とか出来ました。
色々試してみて驚くことに、UTFのHTMLファイルをShift_JISで読み込んでも結果は変わらないのです。
思い出しました。asciiコードはShift_JISでもUTFでも変わらないという事です。
つまり、HTMLファイルのタグ部分は当然asciiですし、URLなどもほとんどasciiです。
HTMLファイルは表示すると当然文字化けでしょうが、抽出したリンク部分は、大半、asciiである限り、正常に表示されます。
例外は、ファイル名、フォルダ名に全角文字を使っていた場合です。
この場合、ファイル名などは文字化けして表示されます。結果は全部エラーとして表示されます。

ここまで書いてみて、疑問点が出てきました。
それは、C#内部では、VS2019の内部では、文字コードはどういう扱いなのか、という事です。
C#ではデータがUTFで保管されていて、Shift_JISのファイル名と照合したら、どのような扱いになるのか、心配します。
研究の余地ありです。
ここまで、C#内部での文字コードに起因するような事象は出ていません。

もう一つ、リンクタグの指定です。
リンク先を探す際のキーワードとして、a href=、img src=、link rel=という3個の文字列を探して、その後ろのファイル名などを収集していました。
これでも何とか探し出してはいました。link rel=等はもう一段作業があって面倒でしたが。

最近になって、jsファイルがscriptタグの中にあって、これも収集する必要があることに気付きました。
ここではscriptのあとのsrcタグの後ろにリンク先があります。
ここで、気付きました。
実際のリンクタグはhrefとsrcの二つだけだという事です。(極めて個人的な見解です)
HTMLファイルの中の先の二つの文字列を探せばいいのです。
実際には出来るだけ紛れがないように、href="、src="で探しています。
srcだけだと、例えば、scriptという文字列も収集してしまいますので。

どうやら、これ(href=")で紛れはなさそうです。
一つだけ、FC2関連のページでurl=というタグがありました。
何やら特殊な扱いになっているようで、チェックするとエラーになります。
実際の表示は意図通り表示されています。
見つけたのは一件だけですし、これは無視することにしました。


220106
C#、ページのリンク切れチェック

リンク切れのチェックのプログラムがほぼ完成しました。
当初、ごく普通のリンク、ローカルフォルダににある別のページへのリンクだけをチェックするものでした。
その後、内部リンク、つまり、同じページの別の行へのリンクもチェクックできるようになりました。
この際、同じような形式で、違うページの特定の行を指定するリンクもあることに気付き、これも成否を判断するようにしました。
更に、もう一つ、外部リンク、別のサイトのページへのリンクも調べることにしました。
これは、どのようにするのか見当もつきません。ネットに紹介されているコードを利用して何とか完成しました。
要はエラーが発生した時の処理のようです。
肝心な事は、ネットからの応答になるはずです、どのくらいの時間が掛るのか、ということです。
試してみた結果、私のサイトにこの手のリンクは延べで2500個ほどあります。
この数はプロクラムで全ぺージを捜査して引き出しました。
もうひとつ、大半のリンクはリンク先は同じです。ですので、重複しない分も調べます。これが49個でした。
これを、先ほど引用させてもらったコードを使って検査します。結果、かかった時間は15秒ほどでした。
このくらいの時間だと使用に耐えるものだと思います。


220104
C#,相対パスを絶対パスに変換

またしても便利な関数に気付きました。
System.IO.FileInfo(System.IO.Path.Combine(stra, strb))です。

リンクの正誤を調べるプログラムを作っています。
一応作動しています。
現時点で、フォルダ内にあるファイルへのリンクとページ内の別の行へのリンクについては、正誤の判定をしています。

このリンクの表記に相対パスというものがあります。
../index.htm、というような表記のリンクです。
普通には、カレントのフォルダ名とリンク表記のファイル名とを連結して絶対パスにして、そのファイルがあるかどうかで判定しています。
ここに、この相対パスがあると、普通に文字列の比較ではファイルがない、同じものではない、という判定をしてしまいます。
そこで、相対パスを絶対パスへの変換が必要になります。

ここまで、手書きで関数を作っていました。
二段の相対パスまでは変換できるように作りました。
ここにきて3段の相対パスが有ったらどうする、と心配するようになりました。
この3段目を考えていた時、先に再帰でフォルダ内のファイルを収集する関数があったことに気付き、この関数もあるかもという考えにいたりました。
これがあるのです。
先に書いた関数というのかメソッドというのか、用語はわかりませんが、これを使えば一発で変換してくれます。
ちょっと試したら、3段の相対パスも変換してくれます。
ただ、苦情をいうと、パスが\表示です。
今、全部/表示に変えたばかりでした。
そこで、下に書いているReplaceの出動でした。



211227
str.Replace("a", "b")

下にメモしているページのリンク切れチェックのプログラムで、トラブルでした。
ページ内リンクを探しているとき、探す対象のリンク先がid="zidoukidou"だったのです。
結果、見つかりません。
ただ、私のサイトには古いページも残っています。
昔はa name="zidoukidou"でもラベルとして使えていたようです。これが残っているページがあります。
これは新しく組み立てるより、id=をa name=に置き換えた方が簡単です。
そこで、str.Replace("id", "a name")、としました。
結果は、a name="za nameouka nameou"、となりました。
対象文字列の全てのidとあるところを置き換えるのですね。

211208
プロジェクトのバックアップ
VSのプロジェクトのバックアップに関して、過去にいくつかメモしてあります。
全部無駄な作業でした。無知でした。
バックアップは単純で簡単でした。
その方法は、一つ上のフォルダごとバックアップする、事です。
こうすると、プロジェクト名のフォルダをバックアップ先でも変えないでおけます。

今回、リンクチェックのプログラム?プロジェクト?を作る際に、最初の設定、プロジェクト新規作成の途中で、
ソリューションとプロジェクトを同じフォルダに置くか、みたいなチェックボックスがありまして、そこをチェックしませんでした。多分。
その結果でしょう、slnファイルはプロジェクトのあるフォルダの上に(フォルダの中ではなくフォルダと同じ場所に)に出来ていました。
出来あがったフォルダ構造は、プロジェクト名/ピロジェクト名/bin/・・、という形になっています。
バックアップするときは、上のプロジェクト名フォルダからコピーしました。
その後、上のプロジェクト名フォルダを変えても(バックアップと分かるような名前にしています)実際のプロジェクト名フォルダの名前は変えません。
そのまま、slnファイルを実行しても、bin以下にある実行ファイルを実行しても、問題なく動いています。

多分、slnファイルを同じフォルダに作った場合でも、フォルダを別に用意して、そこに全部(フォルダもslnファイルも)をコピーするといいのだと思います。

実行ファイル名とプロジェクトフォルダ名が同じになるので、過去に何回もメモしているような色々な変更の必要がありません。
ただまあ、過去の分は、プロジェクト名を変更する際には使えるかもしれませんので、注釈付きで残しておきます。

211202
ページのリンク切れチェック

Win11に換えたところ、HPB15のリンク切れチェックが使えなくなりました。
多少のファイル数のサイトでは動いていて、結果も出るのですが、私のこのサイトはファイルが約16000個あります。動きませんでした。
(この自作のプログラムで正確にカウントした結果が、全ファイルが16651個、htmlファイルが5709、その中のリンクの総数は160695個です。数字は日々の更新で変わっていきます。)

それでも、これまでWin10でのHPB15では動いていました。
この機能はビジュアルサイトビューにあります。これを開くと(実行すると)、結果としてリンク切れ等が表示されます。
この結果が出るまで10分ほど掛かっていました。
このWin11(Corei5_10400)では、5分ほど掛かった挙句、エラーになったり、HPB15自身が落ちたりしています。
文句は言えません。HPB15が古すぎるのです。

そこで、一念発起、自分で作ることにしました。
今、使える環境はHSPかVS2019のC#です。
C#の方が早いことは分かっていますので、これを使いました。

C#、つまりVS2019です。これはHSPと違って、初期設定が大変です。高機能との裏返しでしょう。
とにかく複雑です。ちょっと使わないで間をあけると、分からなくなります。
カタカナの用語が多くて、多岐にわたります。
まず、プロジェクトを作らないといけません。
これの決定までの選択肢がまた多くて、苦難の道です。
まあ、過去に成功した時のメモを残していましたので、その通り選択して何とかVS2019のエディタでコードを作る所までは行きました。

現在、この作業を始めて、半月ほどになります。
ですが、もし、新しく別のプロジェクトを始めるとすると、またこのページのメモを見ながらになります。
複雑です。覚えられません。

VSの高機能の内蔵エディタ、これの窓がまた複雑です、多岐にわたります。
自分のやり易いように配置するのも大変です。
まあ、何とか記憶をたどったり、このページのメモを探したりして、作業開始の状態まで作りました。
ただ、このエディタには少しバグがあるようです。
フォームのプロパティウインドウが出ないことがあります。
何度か開き直すと正常に表示されます。正しい操作方法を知らないだけかもしれませんが。

話がずれていきますが、このVSのエディタはとても便利なものです。
多分、その機能の大半は使い切れていないと思います。しかし、分かっている機能だけでもとても助かっています。
例えば、
サブルーチン(メソッド、関数)の引用元と引用先へのジャンプがあります。
ショートカットキーで簡単に移動できます。
また、サブルーチンのリストは常時窓に出でいますので、必要ないかな、と思うようなものまでサブルーチンにしがちです。
サブルーチン名は日本語で作っています。長々とした名前です。
例えばこんな感じのサブルーチン名です。「ファイルリストから除外指定フォルダのファイルを削除する();」
コードの海で彷徨うものにはとても便利な機能です。
また、変数名の一括での名前変更も便利な機能です。
右クリックメニューにあります。

作業では、サイトを構成しているローカルフォルダ内の全ファイルを収集します。
これは、当初悩みました。私は再帰を理解していませんので。
ループで何とかなるのかと悩んでいたら、C#にはとてもありがたいコマンド?メソッドがありました。
SearchOption.AllDirectories(これはメソッドの全部ではありません、オプションというものかもしれません。)です。
これを発見して、このプログラムの目途がつきました。
何しろ、これ一発で、サブディレクトリを含むファイルのリストが取れてしまいます。しかも早いのです。
私のサイトのローカルフォルダ以下には、16707個のファイルがあります。(211215時点で)
これのファイル名を先のコマンドで収集するのに2.6秒です。
普通に右クリックメニューでフォルダのプロパティを取ると出てくる数字です。当然、同じ数字になります。
あの、再帰の構造に悩んだ時期は何だったのでしょうか。
私としては、これ一つで、C#を使う意義がありました。

もう一つ、今回有益だったのに、StringComparison.OrdinalIgnoreCase、があります。
これで大文字小文字の区別なく文字列の比較ができます。
作業の中で、ファイル内の例えばa href=という文字列を調べないといけません。
これがページによってはA href=となっていたりします。私のぺージで実際にあります。
このメソッド?、オプション?で細かい場合分けの必要がなくなりました。

さて、最初に画面を作ります。フォームでしょうか。
これは、HSPに比べたら、このVSの方が楽です。というか高機能の画面が作れます。
HSPにも画面を作るツールがあったようにも思いますが、このごろは面倒なので、前に作った画面のコードを丸写しして使っています。
目的に言うように配置を変えて使います。

VSでは、実際に画面を見ながら作ります。
ただ、高機能な故に、細かいところで色々な選択肢を探すのに苦労します。
その一つ、画面を拡大縮小したとき部品のバランスが壊れないようにするにはどうするか、に関しては、
splitcontainerとかdockとか便利なものがあります。
部品に色を付けるにはどうするか。
テキストを右寄せで表示するには。
テキストを複数行表示させるには。
など、プロパティウインドウで、いくつも細かい設定が可能です。
まあ、細かい動作が可能ということです。

肝心のプログラムの流れは、
上のコマンド一発で、フォルダ以下の全ファイルを収集します。
次に同じフォルダ内のHTMLファイルを収集します。
上と同じコマンドで拡張子を指定して収集します。
これで今度はHTMLファイルだけをリストアップできます。
ただ、ローカルのフォルダにはアップロードしていないファイルやフォルダもたくさん有ります。
バックアップとして残してあるものや古いページなどです。
こういったものを読み込んでしまうと手数だけ増えて無駄です。当然、調べたらリンクエラーになりますし。
こういうページの為に、収集作業の際、収集しないフォルダを指定しておきます。
そうして残ったものが検査対象のファイルです。私のフォルダにはこの検査対象のTMLファイルが5700個ありました。
指定してあるリンク用のスクリプト(どうやら正式にはタグというらしい)を検出していきます。
そして、検証するリンク先のファイル名を取り出します。
取り出したリンク先のファイル名がローカルのフォルダ内の全ファイルのリストの中にあるか照合します。
照合できなかったものがリンクエラーだということになります。
この間、相対アドレスとかフルパスとかの処理が必要です。

リンク先は、 今のところ、a href=、と、img src=、link rel=を調べて、この文字列が出てくると、その後ろがリンク先だと判断して取り上げていきます。
このリンク先をフルパスに変更して、先に収集した全ファイルの中にあれば、エラーなし、としています。
ちょっと調べたら、リンクダグには他にも有るようです。しかし、私のサイトでは使っていませんので、無視しておきます。

プログラムの動作に必要な条件は、設定ファイルを作って、そこから読み込んで使います。
何を持ってリンクかと判断するか等、設定ファイルに書いておきます。
こうするといつでも条件の追加ができます。

ここで、例えば、a href=については、a href_=など、スペースの問題があります。
ただ、HPBでは構文の補正機能が有りますし、半自動化のプログラムで生成したページにはこのようなスペースが入り込む余地がありません。
そこで、スペースについては無視しています。そのようなタグは無いという前提です。
ここまで書いて気づきました。上の設定ファイルに、a href_=を書き込んで実行してみるといいのです。
結果、a href_=も、img src =も、余分なスペースを含むものは一個もありませんでした。
プログラムでは、収集した全ファイルを読み込んで、先のタグがあれば知らせる、という事をしていますので。

実際に仕上げていく途中の段階で、ファイルが16000枚もあるフォルダで試すのは身の程知らずです。
テスト用のフォルダを作って作業していきました。
最初は数枚のページだけが置いてあるフォルダからです。

これはまあ、テスト用のプログラムです。途中経過をテキストに記録しながら実行させています。
多分、高機能のVS2019なので、わざわざ面倒なことをしなくても、デバッグの機能にこのようなものがあるのでしょう。
しかしながら、残念な事に、私には分かりません。そこで、HSPの頃から、この方法を使っています。
変数の値や分岐の行方を、その都度この記録用の文字列に記録していき、終了時や適当な時期にクリップします。

このような作業では、この文字列がものすごい大きさになり、当然作業時間にも影響します。
私が管理しているもう一つのサイトにはファイルが11000個あります。
途中経過を残す方式で、先の11000枚のサイトで試すと、86分掛かりました。
無理もありません。
そういう事で、動作試験用のフォルダが必要なのです。

プログラム作業が安定してくると、このような面倒な事はやめます。
フラッグで簡単に、途中の記録あり、無しを選定できるようにしてあります。
無駄な記録を作らず、普通の結果だけ求める方式で試すと、同じサイトが25秒程度で終わります。

実際、現在の私のサイトに置いてあるファイルは16000枚程、HTMLファイルが5700枚程です。
ローカルのサイトです。
このフォルダを対象にして実行すると、現在では、70秒で結果が出るようになりました。
途中、数分とかかかる時代もありましたが、コードを改良したり、経過を省いたりした結果です。

ただ、16000枚のローカルフォルダで、PC再起動直後の作業で70秒ほど、もう一回試すと40秒弱で終わります。
HDDのキャッシュでしょうね。2回目はキャッシュが効いているのでしょう。
それにしても、これだけ早いと本当かと動作を疑ってしまいます。
5700枚ほどのHTMLファイルを読み込んで、一行ずつリンクタグがあるか調べているはずなのですが。
結果は以前と同じですので、間違ってはいないと思います。
念のためと思って、わざとエラーのリンクを作ったページを作ってあります。
ちゃんとエラーを指摘してくれます。

また、試しに、旧PC(corei54600)でも実行してみました。
一回目が120秒、2回目は50秒でした。
まあ、CPUの数値通りの結果と思います。

それにしても、実際に検査したファイル数5700個(つまり、HTMLファイルの数)、その中にあったリンクタブの数160000個です。
本当にこれだけのことをしているのか疑いたくなります。

なお、先の経過を記録する方式で実行しても、記録しない場合の2倍までは時間がかからなくなりました。
まあ、詳しく記録しないようにしたいうだけではあります。

HPBのビジュアルサイトビューでは色々な成果が取れます。
私の場合は、これに比べると手抜きです。
リンクの作業だけですし、
外部リンクの分はリンク先を調べていません。
一応、リストアップはしてあります。しかし、これを調べるととてつもない時間がかかるだろうと思います。
まあ、方法もよくわかりませんし。
あと、ページ内リンクです、これも調べるのが面倒だったのと、まあ大丈夫だろうとして無視しています。
あと、JavaScriptの分もありました。多くはないのですが、JavaScript:history.go(-1)という構文をいくつか置いてあります。
戻るボタンと同じ動作です。
これは動くかどうかの話で、調べることはできません。
CGIも困ったものです。リンク先に実際のファイル名以外にオプションでしょうかね、色々飾りみたいなものが付いています。
このため、フォルダ内のファイル名と照合してもうまくいきません。

ここまでの、リンク先を調べることが面倒なもの、調べ方の分からないものは、それぞれリストにして返すことにしました。
必要なら、自分で調べれば済みますので。




211130
32ビットプラットフォーム

どうやら出来上がったC#の実行ファイルが32ビットで実行されているようです。
タスクマネージャーでプロセス一覧を見てみたらファイル名の後ろに(32ビット)と表示されています。
過去のC#のプログラムを見てみても、全部(32ビット)となっています。
実行経過や結果に支障はないのですが、見栄もあって64ビット版にする方法を調べてみました。

MSのページに説明がありました。
メニューのビルド構成マネージャーにあるアクティブソリューションプラットフォームボックスの新規作成を選びます。
出現する新しいソリューションプラットフォームダイアログx64を選択しOKをクリックします。

作業フォルダを見てみたら、binの下に新しくx64というフォルダが出来ていました。
このx64フォルダの下にdebugフォルダがあり、そこに実行ファイルができていました。
完成した後のことを考えて、実行ファイルの位置に実行に必要な設定ファイルを置くようにしています。
これを元の32ビット用のフォルダから移さないといけません。

さて、変更したばかりですが、変わりなく動いています。
タスクマネージャーでは(32ビット)の文字が消えました。
それに、どうなのでしょう、少し早くなりました。
今、ローカルのフォルダでリンク切れをチェックするツールを作っています。
目的のわがサイトのローカルのフォルダには16000個のファイルがあります。
これで直接試すのは冒険すぎるので、試験用に数個のファイルを置いたものから数百、数千のファイルを置いたフォルダを作ってあります。
これで試して、32ビットの時の作業時間を記録していました。
そして今、64ビットで実行してみました。
64ビット版の方が70%から50%程度の時間で終わります。
まあ、キャッシュの問題もあるかもしれません

タスクマネージャーで気づきました。
デバッグ中ですが使用メモリが8GB前後を行き来しています。
最前のメモリ増設は意義があったのかもしれません。8GBを16GBに増やしました。



211127
ドット演算子
ドット演算子というのかどうか分かりませんが。
ドットの使い方でまた迷いました。以前、同じことで迷ったことが当たっと思います。
ホームページでリンク先のフォルダの記述を、temp21/211119er.htmの様に、/でしています。
自作のプログラムで生成している部分です。
プログラムを作る観点からは\より/が圧倒的に楽です。
\だとコントロールコードの扱いで、ひとひねりいります。
/だと普通の文字扱いで考える必要がありません。
ブラウザ側からはどちらも同じ扱いです。

ところが今回、リンクチェックのプログラムを考えているとき、これが問題になりました。
リンク先のフルパスを作るとき、temp21\211119er.htmみたいな形になるのです。
これではプログラムで照合ができません。

そこで置換です。
temp.Replace("/", "\\");でいいだろうと思って実行すると、
エラーにはなりませんが、同じものではないと言ってきます。
正確には、変換されないのです。

正解は、temp2=temp.Replace("/", "\\");です。

一方で、
str.ToString()などは、受け皿がなくても大丈夫です。
基本的な勉強をしていない辛さかもしれません。


211122
C#、特定のフォルダ以下のファイルの取得

HPB15でのリンク切れチェックの代替プログラムを、C#で組もうとしています。

まず第一に、ローカルのフォルダー、トップページ以下のファイルを置いてあるフォルダー、のファイルを全部リストアップしないと始まりません。
たくさんのサブフォルダを含みます。
当初は、この為に、ループか、噂に聞く再帰か迷っていました。

調べていたら、
C#にはこの為の専用のコマンドがあるようです。メソッドというのでしょうか。
Directory.GetFilesとかDirectory.EnumerateFilesとかです。
Directory.GetFilesの方は、今までもファイル一覧を作るとき、使っていました。
これに、オプション(SearchOption.AllDirectories)を付けると、その下のサブフォルダ全部を走査してくれるそうです。
なんという便利な世の中になったものでしょうか。

しかも早い。
5805個のファイルが有って、収集は一秒そこそこで終わる。

問題はこれから。
このファイルを全部調べて、リンク先があるか調べることになる。


211117
C#、プロパティウィンドウ

HPB15のリンク切れチェックの為のビジュアルサイトビューがうまく動きません。
重宝していたリンク切れの検査が出来ません。
最新のHPBはアップグレードで9000円と出ています。
そこで、フリーのツールを探しましたが、適当なものがありません。

そこで、作ってみることにしました。
久しぶりのVS2019のC#です。
下のメモの通りでVS2019は起動にも苦労します。
何とか画面らしきものまでは出来ました。
しかし、何やら不自然な事があります。
ツールボックスの項目が出てこなかったり、プロパティウインドウが出てこなかったりです。
たいていは、あちこち触ったり、再起動したりで何とかなってはいます。

まあ、付け焼刃で、試行錯誤で、作っているからでしょう。
本来は系統立てて勉強しないといけないものですから。

時には、VS2019自体が危うい時があります。
一瞬、ブラックアウトしたり、エディタが出てこなかったりです。
HDDの回転の関係か、起動時に作業を急ぎすぎたか、みたいな感じです。

プロパティウインドウがおかしいです。
ソリューションでしたかslnファイルを立ち上げる時、プロパティウインドウが空白の場合があります。
フォームのデザイン画面で立ち上がると、つまり前回、デザイン画面で終了していると、正しくプロパティも表示されます。
しかし、コード画面で立ち上がる場合、プロパティウインドウは空白です。
ここまでは当然です。しかし、デザイン画面に変えれば、プロパティも表示されるはずです。
表示されません。空白です。
これは、もう一回、コード、デザインと切り替えると正しく表示されます。



211116
C#、新しいプロジェクトの作成

何度もメモしていますが、どこに書いていたか探すのに苦労します。
新しいプロジェクトの作成方法の再掲です。

Visual Studio 2019を起動します。
新しいプロジェクトの作成(N)を選びます。
次のページに、たくさんの選択肢が出てきます。プロジェクトの種類なのでしょう。
上の方にある、多分、分類を整理するものでしょう、ボックスが3個並んでいて、
C#,Windows,デスクトップ、を選んでおくと、選択肢が絞られます。

その中の、
C#、Windowsフォームアプリケーション(.NETFramework)、
WindowsForms(WinForms)ユーザーインターフェイスを含むアプリケーションを・・・、
C#、Windows、デスクトップ、
を指定、選択します。

つぎのページです。
素人には分かりにくい項目が並んでいますが、
プロジェクト名を指定します。この名前が実行ファイル名になりますので、目的にあった適当な名前を指定します。
ソリューション名はこのプロジェクト名と同じになります。
(大きなプロジェクトだとこのあたり違うのかも知れません。)
場所、を指定します。場所とは、フォルダを配置するフォルダの事です。(1)
フォルダはプロジェクト名で作られます。
実際のフォルダ名はプロジェクト名になりますので、そのプロジェクトのフォルダを配置するフォルダを指定します。(2)
結果、「場所」というボックスで指定したフォルダ名の下に、プロジェクト名、というフォルダが作られ、
そこにソリューションファイル等が作られます。(3)
(上の(1)(2)(3)は同じことをくどくど説明しています。)

フォルダ(=プロジェクト名)はあらかじめ作っておいてもいいです。
と思ったら、今回は、フォルダが既にあるとエラーになります。
フォルダだけ残して、フォルダ内のファイルやサブフォルダを全部削除してやり直そうとしましたが、駄目でした。
そこで、そのフォルダも削除しましたが、何度か失敗しました。
フォルダがあると言われて、先に進みません。
キャッシュみたいなものがあるようです。
何度か試すと、進むようになりました。

今回、以前作ったプログラムとslnファイルの位置が違っていました。
前回まではbinフォルダがあるフォルダにslnファイルが出来ていましたが、今回はその上に配置されています。
プログラム名/プログラム名/bin/以下、となっていて、2番目のプログラム名のフォルダにslnファイルだけがある状態です。
プログラム名のフォルダが2重になっていることも予定外、と言いますか、今気づきました。
プロジェクト作成の途中で、ソリューションとプロジェクトを同じフォルダに置くか、みたいなチェックボックスがあったような気がします。
そこの間違いだったのでしょう。
これがどういう効果があるのか、まったくの不明です。

効果が分かりました。
いえ、どうやら私が知らなかっただけなのでしょう。バックアップが簡単になりました。
上のフォルダごとバックアップすればいいのです。
そして、その上のフォルダ名だけを変えてます。フォルダ構造次第では変える必要も無いのでしょうが、日付とかバージョンとかの名前に変えておくと探すのが楽です。
この結果、slnファイル以下のフォルダの構造はバックアップ元と変わりません。
slnを実行してみると、何の問題も無く動きます。何しろフォルダ構造が元と変わらないのですから。
今まで、あれこれ苦労してバックアップしていたのはまったくの徒労でした。


211115
ユーザー登録

VS2019は無料ですが、ユーザー登録が必要なようです。
あと5日で期限切れみたいな通知がありました。
いままで使っていたWin10の方を見てみたら、MSのアカウントで登録しています。
同じように登録しました。

211022
Win11に変わって

PCを新しくして、OSをWin11に換えました。
動いています。
画面のサイズは変わらない、と思っていたら、タスクバーの高さが大きくなっていました。
Win10では、画面の有効な高さが1017でした。
Win11では1009になっています。
この差がタスクバーの高さの差です。多分。

写真処理のプログラムを作って動かしています。
HSPで作ったものと、C#で作ったものがあります。
用途が少し違います。
HSPで作ったものは、起動時にエラーになりました。
C#の方は動きます。
HSPでは、有効幅を調べて全画面で作業していました。
これが違うと止めるようにしています。このせいでした。

C#の方は全画面ではなく、有効高さを調べて、高さを合わせて開くようにしていたようです。

210507
C#、二重起動防止
ビューアでの作業中に、たまに二重起動する事があります。よくあります。
写真の整理作業中に別の作業が入り、ビューアを最小化して他の作業をしてしまい、この事を忘れてビューアのショートカットをダブルクリックしてしまった時です。

今迄、作業中の写真やプログラム付随のファイル類に支障が出た事はありません。
ちょっと調べたら、簡単に予防できそうです。
Mutexを使ってのもので、5、6行のコードを追加するだけでした。

210414
C#、フォルダのソート

下のメモと全く同じトラブルです。
忘れていました。
月初めに作ったフォルダに動画ファイルが残っていました。
動画は動画専用のフォルダに保存しています。
これを忘れていて、今日移動させました。
直前に、今日の写真をカメラから取り込みました。

HSPで作っているビューアはちゃんと最新のフォルダが表示されます。
ほぼ同じものをC#で作っています。
こちらの方は、動画を移動(削除)したフォルダが最新だと表示します。
原因は下のメモと同じで、削除するとそのフォルダの更新日時が変わるせいです。
忘れていました。
対策は泥縄ですが下に書いています。

ただ、この件、現在、サーバ移転がらみのFTPツールで問題にしています。
参考になりそうです。


210111
C#、フォルダのソート
C#でビューアを作って、使っています。
撮影してきた写真は、まず、日付け付きのフォルダに入れて作業を開始します。
ビューア起動時に、一番新しいフォルダを探して、そこを作業フォルダとしています。
つまり、今日撮ってきた写真の取捨選択をする訳です。

今日も同じ様に作業を始めようとしました。
ところが、何故か、最新のフォルダを開きません。
中途半端な日付のフォルダが選択されます。1月3日のフォルダです。今日は1月11日です。何度やっても同じです。

私のプログラムは、作業経過をクリップボードに転送して終了します。
プログラム作成時に、デバッグが簡単にできるように作ったものです。
完成した後も、この機能は残しています。実行速度に影響がない時の話です。

その経過を見ると、しっかり1/3のフォルダが一番あたらしいとされています。

この、C#で動かす前は、HSPでも同じ様なものを作っていました。
そのHSPでのビューアを動かしてみると、ちゃんと最新の今日の日付のフォルダが選択されます。
同じ様なアルゴリズムのはずです。困りました。

Array.Sortを使っています。いえ、どこかのページからコピーさせてもらったコード、を見よう見まねで使わせていただいています。
理屈が分かっていません、こういう時は困ります。

ここで、ひらめいた事があります。
HSPでは、なんと、サブフォルダのリストを取ると、一番新しいフォルダが先頭にリストされます。何もしていません。
で、結果オーライです。

C#でのソートは更新日時でソートするものだった。わざわざ、更新日時を指示しています。
Win10のエクスプローラでソートを更新日時にすると、1/3のフォルダが先頭に来ます。
ファイル名でソートするとちゃんと日付順の並びになります。日付込みでフォルダ名を作っていますので。

ここに至り、原因が分かりました。直前に手書きで削除したファイルがあるのです。1/3のフォルダの中のファイルでした。

つまり、削除するとそのフォルダの更新日時が変わるという事です。
対策も分かります。
新しいフォルダの中のファイルを一つ削除するといいのです。




201210
C#、サーバー移転に関して

先月末に思い切ってレンタルサーバーを移転しました。
移転作業、移転作業に伴うプログラム類の変更も、応急的な措置ですが、一段落しました。
これまで、サイトのページの追加や更新の作業は、HSPで作ったプログラムで大半仕上げていました。
本来は、これらのプログラムを移転に合わせて作り直す必要があります。
この経緯は、半自動化メモやサーバー移転の経緯メモに書いています。
結果的に、現在、HSPでマップファイルとRSSファイルの旧のURLを新しいURLに置換するプログラムを作って、定型化しています。

ただ、折角VSの環境があるので、これをC#で書き直そうと思います。
面倒なものではないはずです。
気を付ける所は文字コードぐらいだと高をくくっています。

下にメモしていたプロジェクトの作り方に関して、プロジェクト名とフォルダ名の関係を間違えていましたので、書き直します。
新しいプロジェクトの作成方法です。
Visual Studio 2019を起動します。
新しいプロジェクトの作成(N)を選びます。
次のページで、C#、Windows、デスクトップ、Windowsフォームアプリケーション、.netFramework、
を指定、選択します。
次のページで、プロジェクト名は、あらかじめ作っておいたフォルダ名を指定します。
場所は、そのフォルダの一つ上を指定します。
ここで、作っておいたフォルダを場所として指定すると、そのフォルダの下にフォルダが作られてしまいます。
もしくは、
場所にはフォルダを配置するフォルダを指定します。
フォルダ名にはそのプロジェクト名を指定します。(この場合はフォルダはプロジェクト名で作られます。)
結果、配置するフォルダ名\プロジェクト名\というフォルダにソリューションファイルが作られます。

まあ、この時点では、フォームだけがあって、コードは何も無い状態ですので、失敗したらフォルダごと削除してやり直す、です。


201114
.NET Framework、有効、無効
下でメモした.NET Frameworkのバージョンの事で、あれこれ試しました。
目的がエラー処理でしたので、.NET Frameworkを無効にしたり、有効にしたりが大変でした。
ネットには、.NET Frameworkはアンインストールは出来ない、無効にはできる、とあります。
プログラムと機能から処理します。

Win10では有効も無効も簡単に出来ました。
問題は、Win8.1でした。

まず無効化、
機能(Windowsの機能の有効化または無効化)には.NET Frameworkを含む項目が二つあります。
これをひとつずつ無効化しようとすると、失敗しました、となります。
物は試しと、二つ一緒に無効にすると、成功しました。

有効化、
今度は、二つ同時に有効化しようとすると失敗します。
そこで、一つずつ有効にすると、一つは成功、もうひとつが何回試しても失敗です。

困り果てた挙句、
何気なくWinUpdateを見てみました。オプションの更新に.NET Frameworkがらみの更新が二つありました。
これをインストールしました。
その後で、有効化を試すと、見事成功でした。

その後は、恐る恐るでしたが、もう一回試しました。
無効も有効も問題なく成功しました。

ただ、.NET Frameworkのバージョンは無効化しても変わりません。
regeditで調べるレジストリの数字です。
ですので、先のC#のプログラムは無効化しても動きます。エラーになりません。
無効化の状態で、正常に起動し正常に終了します。
中で、そのレジストリの数字を確認して、古いバージョンの場合はダイアログを出すようにしていますが、当然反応しません。

ただ無効にしただけで、アンインストールした訳ではないので、そうなのかもしれません。
そうなると、無効化の意味がよく分かりません。.NET Frameworkが使えなくなる、という事ではなさそうです。
実態は分かりません。


201114
C#、.NET Framework

Visual StudioのC#でプログラムを作っています。
その際、.NET Frameworkを利用しています。フォームを使いたいならコレ、みたいな解説がありました。
最初のプロジェクトの指定の所で、.NET Framework付きの物を選んでいます。

未だに、用語の使い方がよく分からないままです。
現在での理解は、.NET Frameworkとは、関数群で、プログラム上から簡単に利用できる物、
画面作成も.NET Frameworkがらみで、これがあると簡単にフォームが作れます。
いずれにしろ、良くは分からないながら、.NET Frameworkを使っています。
正確には、.NET Framework4.7.2です。

当選、出来上がったプログラムを使う際にも、これ以上のバージョンが必要になります。
VisualStudioを置いているWin10では、問題はありません。

PCにはマルチブートで幾つかのOSを入れてあります。
PCは新旧二つあります。
各々で試してみました。

まず、インストールされている.NET Frameworkを調べる方法です。
バージョンを調べる方法がMSのページに紹介されていました。
レジストリを調べ、
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\Release
にある数字が、
.NET Framework 4.5.1は、378675
.NET Framework 4.7.2は、461808
.NET Framework 4.8は、 528040
だそうです。

実際にregeditで見てみると、
新旧二つのPCのWin10は、528372
Win8.1は、一つが、528049、もう一つは、378675でした。
Win7では、528049でした。
WinXPでは分かりませんでした。レジストリに先の項目がありません。

さて、先のMSのページでは、378675はありますが、他の数字はありません。
違いは細かいバージョンアップのせいで、この数字より大きければいいのでしょう。

実際、動かないのは、378675だったWin8.1と、WinXPでした。
後は、全部正しく起動し、正しく終了しました。
XPの方は、32ビット版で対応していない、というようなメッセージが出ます。

問題は、378675だったWin8.1での挙動です。
実行ファイルは2か所に置いてあります。
一か所は、全く動きません。
起動すると、エラーダイアログだけが出ます。内容は英語で、意味は.NET Framework 4.7.2が必要だと書いてあるようです。
もう一か所の実行ファイルは、置いてあるフォルダが違うだけなのですが、起動はします。
しかし、途中や、終了時にエラーが出ます。

という事で、エラー処理ルーチンをセットしておいても損はなさそうです。
.NET Frameworkのバージョンを調べて、バージョン次第で終了する、だけです。
ただ、終了処理をスキップする必要がありました。
トラップしてある終了処理でエラーが出ているのです。
折角、その旨のダイアログを出して終了しようとしても、通常の終了処理へ飛ぶとエラー、では意味がありません。
そのまま終了する様にしないといけません。
それが、Environment.Exit(0)でした。強制終了です。



201023
C#、フォーム間のデータの受け渡し、自作ダイアログ
二つ目のフォームを作り、データを受け渡しする事について、調べました。
標準のMessageBoxが使いづらく、何か方法は無いかと調べて、フォームを使う方法があることを知りました。

フォームの追加は簡単です。
メニューだったか右クリックメニューだったかで追加できます。
新しいフォームの大きさを適当に決め、縦に二つの領域を作ります。
下に、ボタンを3個配置し、上にはpictureboxを配置します。
pictureboxの中にメッセージを表示する方法があります。これでフォントの大きさなども指定できます。

問題は、データの受け渡しです。
使うダイアログに応じて、メッセージの内容他幾つかのデータを渡さないといけません。
受け渡しの方法がネットに色々紹介されていますが、悲しいことに、どれもこれも今一よく理解できません。

そこで、勝手知ったるグローバル変数です。
C#にグローバル変数は無い、と書いてあります。ただ、それらしきものはある、との事です。
変数に、public staticを付けると、どこからでも読み書きできる、フォーム間でも同じ事、の様です。

ネットで調べ、更に試行錯誤を繰り返し、分かったことが幾つかあります。
ボタンのプロパティに、返り値をセットできるDialogResultがあります。
例えば、DialogResultをYesとすると、そのボタンを押すとYesを返してくれます。
ボタン名を「はい」としておけば、MessageBoxと変わりません。
しかも、MessageBoxと同じ様にフォームが終了し、呼び出し元へ帰ります。
返り値の受け取りも、MessageBoxと同じ要領です。

DialogResultをセットした状態で、ボタン名botton.Textを変えても問題ありません。
ボタン名に関係なく、設定したコードが帰ります。
ボタン自体を見えなくするbutton1.Visible、こともできます。

という事で、当初、ボタンの種類や数に応じて、幾つかのフォームを作る必要があるか、と考えていましたが、
工夫すると一つで済みそうです。
はい、いいえ、キャンセル、というボタンを作ってあるフォームで、
はいとキャンセルを非表示にして、いいえのボタン名をOKに書き換えると、OKボタンだけのダイアログになります。
このボタンで帰ると、Noが帰ってくるのでしょうが、受け取りませんので問題ありません。
Yes、Noだけで、キャンセルがいらないなら、3番目のボタンを非表示にすると済みます。

文字はフォーム一杯にpictureBoxを配置してその中に書き込みます。
一番必要なフォントの大きさも指定できます。
表示する文字数とか行数に応じて、呼び出し側のフォームからダイアログとして使うフォームのサイズと
表示領域RectangleFを指定します。
これをやらないと、表示する文字列が左や上に片寄ってしまいます。

フォーム2の表示位置を決めるために、元のフォームの中心座標も送ります。
まあ、呼び出し元の画面の真ん中に出すのが普通でしょう。

それでも、無駄な余白や偏りを出さない様に、多少の試行錯誤が必要です。
本来なら、表示する行数、文字数を調べて、必要なサイズを計算する、という事でしょうか。
結局、計算するにしても、同様に試行錯誤が必要です。であれば、その都度試しながら数値を決める方を選びました。

文字表示の領域とボタンの領域はsplitcountainerで分割して、ボタン領域を固定します。
こうしておくと、フォームを小さくした時もボタンが消えることはめったにありません。

右肩の閉じるボタンを表示させないcontrolboxことも出来ます。
ただ、このボタンが無いと、万一、作っていたボタンが全部見えなくなってしまった時、終了できません。
ダイアログを終了できないと呼び出し側も何もできません。(タスクバーの右クリックで何とかなるとは思いますが)
よくよく見てみると、普通のMessageBoxにも閉じるボタンは残してあります。
ここでもこのボタンは残すことにしました。

もう一つ、閉じるボタンで終了すると、戻り値はCancelです。

この作業の途中、先に書いたように、受け渡しするデータが多少多いので調べました。
分からないなりに構造体、という感じがしました。
すると、意味不明ながら、構造体よりclassの方がいいとあります。
見よう見まねで、public static class unnun{}、としました。
中の要素にもpublic staticを付けて宣言します。
中の要素に、配列も宣言できます。
こうすると、どちらのフォームからも見たり書き込んだりできます。できるようです。
ただ、表現が面倒で、ドットで並べていかないと行けません。
Form1.unnun.str[0] = "a"、という様な形になります。

と、ここに来て、引数での受け渡しと勘違いしている事に気付きました。
私の理解できる範囲でやります、これに関しては引数は使いません。
引数で受け渡すなら、構造体とかも便利なのでしょうが、単なるグローバル変数で強行突破です。
とすると、まとめる必要はありません。面倒なだけです。
ま、おかげさまで、構造体とかclass変数?とか勉強はしました。

201022
C#、フォルダの変更、ソリューション、プロジェクト、実行ファイル名の変更

211208、この項訂正。
バックアップの方法は簡単でした。
一つ上のフォルダごとバックアップする。事です。
slnファイルをプロジェクトのあるフォルダの上に(同じレベルか)に作って、プロジェクトのフォルダ名を変えないようにします。
実行ファイル名とプロジェクトフォルダ名が同じになるので、下に書いたような色々な変更の必要がありません。
以下はそういうこともあったという事で残しておきます。

作っているプログラム、写真ビューアですが、一応当初の予定通りで一段落しています。
これはこれで良いのですが、細かく見ると不満もあります。
ダイアログが小さくて不自由です。
調べてみると、別にもう一つのフォームを作り、加工して使う方法があるようです。
フォームを使うなら、フォントとか表示場所とか色とかも使えると想像しています。
これに取り掛かるにあたり、ここまでのプログラムは退避しておきたい、
新しい手法に失敗して、元に戻すような時、現時点の状態から再開させたい、という訳です。
バックアップはしますが、もっと確実な方は、現在の分は、そのまま残し、これから加工する分を新しいフォルダで始める。
こうしたい訳です。こうすると、確実に元に戻れます。
そこで、フォルダごとコピーした方を、フォルダ名やファイル名を変えて行きます。
以前、同じことを経験済みで、そのメモを見ながら進めました。

つまり、このメモは201009のメモの再確認です。
今回また、フォルダごとコピーして新しいプロジェクトにしました。前回のメモの通り実行して無事終わりました。
エラーも出ませんでしたので、まとめの部分を再掲、多少の追加です。

2回目のまとめ。
slnファイルのあるフォルダをフォルダごとコピーし、フォルダ名を変更予定の実行ファイル名に合わせて変更。
ここで、slnファイルを実行、VSを立ち上げます。
見慣れない画面(コードが見えません)で立ち上がりますが、アイコンやメニューから、すべて保存。デバッグ実行、またすべて保存。そして終了。
ちゃんと実行されます。

一息置いて、名前類を新しい名前(=新しいフォルダ名)に変更していきます。
sln起動、
ソリューションウインドウの右クリックメニューで、ソリューション名変更、プロジェクト名変更、
プロジェクト名の右クリックメニューにあるプロパティから、アセンブリ名変更、既定の名前空間変更、
コード画面で、namespaceの名前の右クリックから、名前の変更、
です。
全部、目的の実行ファイル名に変えます。

ことによると、この間、ひとつづつ変更するたびに、すべて保存、実行、すべて保存、終了を繰り返す方がいいのかもしれません。
今回、ソリューションウインドウだけは最初の起動から見えていました。
ですので名前の変更は簡単でしたが、最後のコードのnamespaceの名前が見えません。
表示メニューのコードを押しても、コードが出てきませんでした。
保存、終了、起動で見えるようになりました。



201020
C#、文字列補完式
文字列補完式、というものがあることを知りました。
ネットで、それとなく見てはいましたが、これほど便利だとは気付きませんでした。
textBox1.Text = $"{str}を{en]円";
これまでは、ToString()の嵐でした。
7000行ほどのコードに、調べてみたら、ToString()を170個使っていました。
逐次、メモを作る必要があって、数値をテキスト化するのに使っていました。
全部、この文字列補完式で代行できるのだと思います。


201018
C#、アイコンの変更

プログラム?アプリ?フォーム?ウィンドウ?に、独自のアイコンを使う方法を調べました。
アイコンファイルは、このサイトのトップページに組み込む時に作ってあり、それが使えました。
そこで、使えるアイコンは準備済として、フォームへ組み込む方法です。
フォームのプロパティにIconという項目があり、自分で作ったicoファイルを指定できました。
すると、フォームの右肩のアイコンが指定したものに変わります。
同時に、実行時のタスクバーのアイコンにも反映されます。

実行ファイルのアイコンは、ソリューションエクスプローラーのプロジェクト名のプロパティにアプリケーションというタブがあります。
そこで外部ファイルを指定できます。
エクスプローラーのファイル名の先頭に表示されるアイコンです。
実行ファイルと実行ファイルのショートカットにも反映されます。


201011
VS、ソリューションウインドウの位置変更
下のバックアップからの復元というかフォルダの変更というかの騒ぎで、何やら設定がリセットされるみたいで、ソリューションウインドウが右側に来ていました。
今まで、左側に置いてありました。最初から左だったか、初期の内に変更したか覚えていません。とにかく左に戻したいのです。
慣れればどちらでもいいのかも知れません。でも今までが左でしたので、何となく抵抗があります。それに勉強のつもりで探しまくりました。

メニューの中を探すと、設定のリセットとかウインドウレイアウトのリセットとかあります。
下のメモで、バックアップからの復元は出来るようになりましたので、気楽に試しました。
全く変わりません。いえ、レイアウト全体は見慣れないものに変わるのですが、肝心のソリューションエクスプローラーは必ず右側です。
この際、ヘルプは何の役にも立ちません。今までヘルプが役に立ったことは数えるほどもありません。
頼みのネットを探しても、簡単にできるとは書いてありますが、肝心のどうしたらいいのか書いてありません。いえ、見つけられません。

考えてみると、バックアップから戻しても、戻したのが現在の状態でした。
分からなければ、このままです。
半日ほど試行錯誤しました。
ネットだったか、ヘルプだったか、MSのページだったと思います。移動するには、Ctrl+ドラッグで移動、好きな場所にドロップ、みたいなことが書いてありました。
試しますが、左側でドロップしても右側に戻ってしまいます。
何度やっても同じです。

そのうちに、ドラッグ中に変なマークが出ることに気付きました。
しかも、Ctrl+ではなく、Ctrl無しの単にドラッグです。(当初はCtrl+だったように思うのですが)
サイコロの展開図みたいな模様が出ます。

その展開図の特定の位置にドラッグしたソリューションウインドウを持っていくと、画面の一部の色が変わる事に気付きました。偶然です。
色が変わるのは、その展開図の特定の位置にソリューションウインドウのタイトルバーを持って行ったときではなく、ドラッグ中のマウスカーソルが、その展開図に乗った時なのです。ここまで気付くのに何時間かけた事でしょうか。やはり偶然です。

要するに、そのサイコロの展開図みたいなものが、ソリューションウインドウの配置を示しているのです。
しかも、決定は、ウインドウをそこに乗せた時ではなく、ドラッグ中のマウスカーソルを乗せた時です。
左側に持っていきたいなら、展開図の左端の模様にマウスカーソルが乗ると、左端の、ちょうどソリューションウインドウぐらいの領域が青色に変わります。
その状態でマウスを離すと、めでたく左側に鎮座して頂けます。

幾つかリセットしたおかげでしょうか、画面がとてもシンプルになっています。
以前は、画面がいくつものブロックに分割されており、肝心のコードの編集領域はとても狭い物でした。
恐ろしいのは、そんなものだろうと思って、今まで続けていたことです。

コードは、まあ極端な話、数行もあればいいのですが、フォームのデザインが面倒です。
大きなフォームを作ろうとしても、大半の部分が隠れています。スクロールバーを操作しないと全体は見られません。
これが、だいぶ改善されると思います。
あれこれいじったおかげで、必要のない窓は、X、バッテンで消してしまえばいいのに気付きました。
復活は、そう面倒ではないことも分かりました。表示メニューにあります。

これからは、ソリューションウインドウとコードウインドウだけ出しておこうと思います。
フォームの編集の際は、そのソリューションウインドウも消してしまえば、ほぼ画面全部を使えます。


201009
C#、フォルダの変更、ソリューション、プロジェクト、実行ファイル名の変更

211208
バックアップに関しては、方法は簡単でした。
一つ上のフォルダごとバックアップする。事です。
slnファイルをプロジェクトのあるフォルダの上に(同じレベルか)に作って、プロジェクトのフォルダ名を変えないようにします。
実行ファイル名とプロジェクトフォルダ名が同じになるので、下に書いたような色々な変更の必要がありません。
以下はそういうこともあったという事で残しておきます。


ビルドで排出される実行ファイル名を変えたくて、色々試しました。
もっとも、実行ファイル名は、ファイル名を直接変えても動きます。
ただまあ、何となく、実行ファイル名と同じフォルダ名、ソリューション名、プロジェクト名の方がいいのかな、と思っての事です。
後々、探すときに、面倒がありません。
単に、出来上がる実行ファイル名を変えるだけだったら、アセンブリ名という所を変更するといいと紹介されています。

以下、細かく試してはいません。単純な構造のおかげで、偶然、うまく行っているだけかも知れません。
普通に立ち上がります、ビルドもデバッグも正常です、ちゃんと実行できます。
結論は、フォルダ名もソリューション名も実行ファイル名も変えられました。

過去のメモを見直してみたら、ソリューションというのかプロジェクトなのか未だに分かりませんが、その全体を入れているフォルダを移すことは問題なさそうです。
作業中のものをフォルダごとコピーして、そのフォルダ名を変えて試しました。
ですので、訳が分からなくなったり、迷ったりした時はフォルダごと削除してやり直しです。

途中、一回だけエラーが出る事があります。
このエラーメッセージは、長いものですが、
ドキュメントはソリューションとして開かれているのでエディタで開けません。
というような内容でした。残念な事に、私には意味不明です。
ただ、エラーが出ても、いったんVSを閉じて、再起動するとちゃんと立ち上がります。

試行錯誤の結果、
普通にフォルダごとバックアップしたフォルダで、そのままslnファイルを実行すると、VSがちゃんと立ち上がります。
多少ですけど、起動に時間がかかっているようです。内部で何やら復旧作業をしている様に感じます。
VSは起動はしても、一見、コードが見えなくなったり、デザイナーが表示メニューから無くなっていたりします。
この場合でも、デバッグ実行させると、普通に実行できます。
コードやフォームは行方知れずのままです。私が探し出せていない、操作方法を知らない、という事のようです。
これは、タブをクリックしたり、ビルドしたり、VS自体を再起動したりしていく内に見えるようになりました。
とにかく、やたらと試しましたので、どれが効果があるのかよく分かりません。
一番効果的だったのは、保存してVSの再起動だったような気がします。

名前を変更した箇所は、ソリューションエクスプローラのソリューションとあるところです。
右クリックメニューから、名前を変更、です。
その下、プロジェクト名でしょうか、これも右クリックメニューに変更メニューがあるので変更しました。
更にプロパティから、アセンブリ名を変更しました。

アセンブリ名を変えると、ビルドで出来る実行ファイル名が変わります。古い名前の実行ファイルは無くなります。
と思ったのですが、不思議な事に、古い実行ファイルが残ることもあります。どういう場合に残るのか分かりません。
ただ、削除しても大丈夫です。debug、releaseのフォルダに古い実行ファイル名の付いたファイルが3個残っています。
この3個は日付が古いままで残っています。新しくビルドしても上書きされていませんので、区別は容易です。

このアセンブリ名の所に、既定の名前空間というボックスがあり、古い名前のままです。
名前空間というのは、よく出てくる単語ですが、私には全く意味不明です。
ここも変えてみました。何の影響もないようです。
これに関して、コードの先頭に、namespaceという単語があります。これと関連がありそうですが。
コードが、namespace旧ファイル名、となっていて変えたいものです。
変えていいようでしたので、右クリックメニューから新しいファイル名に変えてみました。異常ありません。
VSには、変数などの名前を変更する場合、右クリックメニューに一括で変更できる手段があります。便利なものです。
この効果はありました。画面に旧ファイル名.form1というタブがありましたが、これが新ファイル名に変わりました。

この後も、何度か試しました。エラーを出さない方法を調べる為です。
VSに何やら補完機能があるのか、あるいはしばらくプロセスが残るのか、と思ったからです。
ですので、出来るだけゆっくりやりました。
面倒ですが、逐次、立ち上げ、保存、実行、終了、を繰り返しました。どこが肝心なのか分からないので、やむを得ません。
結果、うまく行く時が多かったです。しかし、何度か試すと、やはり、先のメッセージが出ることもありました。
これは多分、急ぎすぎたか、何かの手順を抜かしたかだろうと思います。
逆に、メッセージが出ても、気にしないでいいという事にもなります。

もう一回まとめると、
slnファイルのあるフォルダをフォルダごとコピーし、フォルダ名を変更予定の実行ファイル名に合わせて変更。
ここで、slnファイルを実行、VSを立ち上げます。
見慣れない画面で立ち上がりましたが、アイコンから、すべて保存。デバッグ実行、またすべて保存。そして終了。
一息置いて、sln起動、ソリューション名変更、プロジェクト名変更、アセンブリ名変更です。名前空間変更、namespace変更、です。
全部、目的の実行ファイル名に変えました。
ことによると、この間、ひとつづつ変更するたびに、すべて保存、実行、すべて保存、終了を繰り返す方がいいのかもしれません。
逆かもしれませんが。
最終的に、あるいは、途中から、表示メニューにコードとデザイナーが出ていました。

もう一か所、変更する箇所がありました。
若干、暴走させたことがあって、恥ずかしながら、タスクマネージャーを開く機会がありました。
タスクマネジャーのファイル名が、元の変更前のファイル名のままでした。
これに関しては、参考になるような記事も見つけ出せません。

仕方なしに、あちこち探したら、前にアセンブリ名など変更した所、プロジェクト名のプロパティから入ってアプリケーションというタブです、
そこに、アセンブリ情報というボタンがあります。
クリックすると、タイトル、と、製品、という項目があり、そこに旧ファイル名が残っていました。
見た感じ、変えても構わないかな、という風に見えました。
恐る恐る、新しいファイル名に変更して、実行してみました。
タスクマネージャーを見てみたら、めでたく、新ファイル名に変わっていました。
この変更に関する影響については、全く見当もつきません。

(このメモの当初から、slnファイルをsinとしていました。見間違いです、全部修正しました。)

201011
ツールのオプションにあるフォントのサイズと、Ctrl+マウスホィールでの大きさ変更の関係が分かりました。
マウスで大きさを変えると窓の右下にサイズの%表示が出てくる。




201002
C#、フォルダ指定ダイアログ、commonOpenFileDialog、dllが必要だった
フォルダを指定する際のダイアログがあります。 よく紹介されているもので、FolderBrowserDialog、です。
簡単にダイアログを出せるので、これまで使っていましたが、多少の不満がありました。
小さいのです。
普通にエクスプローラみたいな感じで開けると、慣れた感じで、使いやすいのですけど。

探してみたら、commonOpenFileDialogというものがありました。
これが、使えるようにするのが多少面倒です。

コードをコピーしただけでは動きません。
以前、ゴミ箱へ移動する機能を追加した時と同じような手続きで、なにやら追加しないといけません。
意味は分かりませんが、NuGetパッケージを追加する、段取りを踏みます。
指定された通り実施すると動くようになりました。

これが、エクスプローラの感覚で使えて、しっくりきます。
左側にクイックアクセスも表示されます。

多少の不満は、デフォルトのフォルダが開いた状態で起動する事です。
そのまま決定でいいのですけど、下の段のフォルダが見えた状態ですので、ちょっと気になります。
仕方が無いので、デフォルトは前回指定のフォルダの一段上を指定する事にしています。

FolderBrowserDialogだと、前回と同じなら、ダイアログを開いて、決定、でよかったのですが、
上の変更のせいで、今回のものは、ダイアログを開いて、マウスでクリックが必要です。

201003追記
旧機で試したところ、commonOpenFileDialogが使えません。例外が発生します。
FolderBrowserDialogを使ったものも残してあり、そちらで試すと動きます。
Win102004です。Win8.1でも同様です。

原因が分かりました。
旧機で試すとき、実行フィルだけをコピーしていました。

古いバックアップのフォルダを移動している時、binフォルダの中のファイル数が違う事に気付きました。
commonOpenFileDialogを使い始めたバージョンから、binフォルダにdllやxmlファイルが4個ほど置いてあります。
Microsoft.WindowsAPICodePack云々というファイルです。
原因はこれでした。
フォルダごとコピーして使うと、めでたく新しいダイアログ使えます。
Win10の2004でもWin8.1でも同じです。


201002
C#、テキストボックスに連続で表示

下のメモで、フォルダのサイズ計算の際、場合によっては時間のかかるケースがあります。
そこで、途中経過の表示は難しいので、せめて作業前と作業完了後の表示をしようと考えました。

textBox1.Text = "計算中です・・・";
・・・
サイズ計算処理
・・・
textBox1.Text = "計算が終わりました";

この処理が数ミリ秒で終わることも、10数秒以上かかることもあります。
どのケースでも、計算が終わりました、しか表示されません。
どうやら、表示が早すぎて見えないのではなく、省略されているようです。

少し待たせるといいのかと、方法を探してみました。
await Task.Delay();を置いてみました。
即、エラーです。非同期がどうの、解説があります。意味不明です。

仕方が無いので、他を探しました。
textBox1.Refresh();を置けばいい、とありました。
これで、表示されるようになりました。




201001
C#、フォルダサイズ計算
フォルダのサイズ(容量?)を計算する方法を調べています。
ネットの記事によると、直接計算する方法はないので、
各フォルダの中のファイルのサイズを総当たりで計算していく、という方法が紹介されています。

幾つかコードが紹介されており、どれも同じにしか見えません。
この世界では常識なのでしょうね。どれも私の理解出来ない再帰を使ったものです。
仕方が無いので、丸写しで使わせていただいています。

何故か、ドライブ全体を計測する事は出来ません。ルートを指定すると例外が発生します。
残念ながら、その理由も分かりません。まあ、フォルダのサイズ、と書かれているので、そのようなものなのでしょう。

不思議な事に、同じフォルダを計測した時、計算時間が大きく変わります。
76GB、フォルダ数970、ファイル数7694のフォルダの計測に、
1回目、6016ミリ秒、2回目、75ミリ秒、です。
3回目以降も2回目と同様です。1回目だけが特別時間を要します。
計算結果はどれも同じです。フォルダのプロパティと同じ数字になります。
キャッシュでしょうか。それにしても効きすぎに思います。


200928
C#、ソート、Array.Reverse()

ソートで苦労しました。
理由は単純で、Array.Reverse()を降順でソートするものだろうと勘違いしていました。
正しくは、現在の配列を、ただ、逆さまに並び替えるだけのものです。
ですので、目的の配列が正しく並んでいないと、結果も正しくなりません。

20923でメモした事で、ファイルを更新日時でソート出来て、更にはフォルダも同じようにソートできる事が分かって、喜んでいました。
しかし、これには、細かく見ると問題がありました。
実際にソートした結果を日時と一緒に転記します、
DSC_1083.JPG:2020/09/24 木 12:46:18
DSC_1080.JPG:2020/09/24 木 12:46:18
DSC_1081.JPG:2020/09/24 木 12:46:18
DSC_1089.JPG:2020/09/24 木 12:46:20
DSC_1087.JPG:2020/09/24 木 12:46:20
DSC_1088.JPG:2020/09/24 木 12:46:20
となっています。
何度試しても同じ結果になります。

最近のカメラは、私のカメラでも1秒間に5,6枚は連写出来ます。
更新日時の表記は秒単位までです。撮影時間が秒までだと、同じ日時のファイルがいくつも出来ます。
そこで、時刻でソートすると、このような結果になるのでしょう。

本来は、まず、日時でソート、日時の同じものがあれば、ファイル名でソート、としたい所です。
エクセルなどではソートの優先順位をいくつか指定できます。
その方法がどこかに紹介されているといいのですが、見つけられませんでした。

でもまあ、実用上はあまり問題になりません。
撮影時間が同じ場合、つまり連写した時の写真は、どれもほぼ同じです。
つまり、同じ写真の並びが多少変わっても、さほど困った事ではなく、プログラムの結果がきれいではない、というだけです。

この問題、撮影時間が同じ場合、ソート後の並びが安定しない件、HSPでやっていた対策を思い出しました。
ファイルのリストを作る際、ファイルのフルパスと同時に更新日時も調べておきます。
そして、更新日時とフルパスを連結した文字列の配列を作ります。
更新日時+フルパス、という文字列の配列を作るのです。
この際、フルパスでなく、単にファイル名だけでもいいのですが、フォルダ内の一覧を作る際、受け取るのがフルパスです。
変換すのも面倒ですので、そのまま使います。
ファイル名だけにするのは、作業の最終段階で必要ですので、その時一回やれば済むことです。

具体的には、このような文字列になります。
2020/09/19 土 13:29:16D:\・・・\・・・\DSC_9998.JPG
単純に連結しただけです。実際には70文字ほどの文字列になりました。空白も漢字も\も入っています。
これをソートします。
すると、日時順できれいに並びます。
日時が同じ場合でもファイル名が繰り上がっているからです。
文字列の途中のフォルダ部分は、全部同じフォルダです、同じです。

そうそう、なぜ、こんな面倒な事をするかというと、私のカメラのファイル名は、9999の次が0001になるからです。
撮影した順番は、こうです。
DSC_9998.JPG
DSC_9999.JPG
DSC_0001.JPG
DSC_0002.JPG
DSC_0003.JPG

単純に、ファイル名でソートすすと、こうなります。
DSC_0001.JPG
DSC_0002.JPG
DSC_0003.JPG
DSC_9998.JPG
DSC_9999.JPG

これでは、後で撮影したものを先に見る事になります。抵抗があります。
で、ネットで発見した更新日時だけを使う方法は、最初の例のような事情が出て、若干の面台を残します。
もちろん、うまく行く場合が多いのですが、連写した時、日付が全部同じだったら、偶然、下のような結果になるケースが出てきます。
DSC_9998.JPG
DSC_0001.JPG
DSC_9999.JPG
DSC_0002.JPG
DSC_0003.JPG

そこで、強引に更新日時を連結した文字列でソートする方法を使いました。
最後にソートされたファイル名だけを取り出すのには、
System.IO.Path.GetFileName()を使います。
元の文字列に、日時が入っていようが、漢字の曜日が入っていようが、空白が入っていようが、関係ありません。
ファイル名だけ取り出せます。ありがたいことです。一番右側の¥だけを見ているようです。

ソートに要する時間は、1200枚の配列で実質70ミリ秒でした。70文字の文字列の配列が1200個の要素で、です。
いえ、当初、数秒かかっていました。
そこで、ソート時間を計測しようと思ってコードを見直したら、また冗長な事をしていました。
ソートのルーチン内にループが3つあります。
更新日時とフルパスの文字列の連結、
その文字列のソート結果表示、
ファイル名だけを取り出す、
です。
経過を記録するために、それぞれを書き出していました。
これを全部省略すると70ミリ秒で終わります。

この間、理解できない事が起こっています。
先の3個のループで結果書き出しをしていると、だんだん作業時間が増えていきます。

ボタンを作っていて、昇順と降順を入れ換える様にしています。
最初の入れ換えでは、1秒程度で終わります。
しかしながら、これを繰り返す度に所要時間が1秒程度ずつ増えていきます。
10回10秒ぐらいまで試しました。安定するような気配はありません。
各作業結果を入れる配列を作っているわけですが、これの入れ換えに時間がかかるのでしょうか。
だんだん増えるということは、作業の構造は全く分かりませんが、経過を記録する変数のリサイズが必要で、これに時間を食っているのでしょうか。
いずれにしろ、ソート結果は大丈夫と分かりましたので、途中経過を残す必要はありません。
全部省略すると、先の結果、1200ファイルで70ミリ秒程度で終わります。

途中、もう一つの問題に気付きました。
降順にソートした際、期待した結果にならなかった事です。
これは、最初に書いた通りで、
昇順のソートは、Array.Sort()で、
降順は、Array.Reverse()だろうと思い込んでいた事です。

正しくは、降順は
Array.Sort()をして、
Array.Reverse()を実行しないといけません。

この間違いが問題なるのは、ファイルの数字が9999から0001になる時だけです。
通常はファイルのリストを作る時、何もしないでもファイル名でソートされています。いるようです。
そこで、Array.Reverse()を使えば、降順に並ぶのです。
ファイル名に、9999と0001がある場合には、Array.Reverse()だけではうまくゆかず、Array.Sort()を先に実行しておかないといけません。



200927
C#、NET Framework4.8
C#で作っているビューアが、一応、予定した感じで動いているので、実際に色々と試しています。
何を試すのかというと、どこまでの環境で動くのか、という事です。
作っているのは、Win10proの1909です。ディルプレイは1920x1080です。
もちろん、動きます。

ディスプレイはもう一つ、1280x1024があります。
試してみました。これでも動きますが、表示する写真のサイズの縦横比が、1.5対1という関係で、とても小さく表示されてしまいます。
どこかでこの計算はしているはずです。横幅が1280だと、写真表示領域には900程度しか取れません。
これに合わせると、縦幅は、600ほどです。つまり、900x600ほどの表示になります。これ以上大きくしても無駄なのです。
この点、1920x1080のディスプレイだと1500x1000程度の表示になり、面積で比べると2.7倍程度になります。
画面割をこのディスプレイでしか考えていなかった結果でした。

さて、それでも、条件さえ合えば、動くには動きます。
結論は、NETFrameworkが必須、という事です。
VSでプロジェクトを作る時NETFrameworkを含んだものを選択しました。入っていなければ動かないのは当然のことでしょう。

試せるものの一つが、Win10の2004です。PCは古いのですが、動きます。
NET云々は最新版が入っています。
これは、何年か前までメインで使っていたもの(旧機)で、アプリ類も色々入ったままです。その関係でNET云々も残っているのでしょう。

Win8.1で試してみました。
現在のPC(現機)の方では起動すらしません。
ダイアログが出ます。英語なので断言はできませんが、どうやら、NETFrameworkの4.7.2が必要と書いてあるようです。
入れていません。アプリを何も入れていません。WinUpdateする以外に使っていませんので、やむを得ません。

旧機でwin8.1を残しているものがありますので、そちらで試しました。
実際に使っていたもので、NET云々もインストールしてあります。
試すと、起動はしますが、終了時にエラーを起こします。
メッセージは、「アプリケーションのコンポーネントで、ハンドルされていない例外が発生しました云々」、です。
調べて見入ると、やはりNETFrameworkがらみの模様です。
そこで、何がインストールされているか調べてみました。
NETFrameworkの3.5でした。バージョンが古いという訳です。

新しいNETFrameworkを探しました。4.8がありました。
これをインストールすると、ようやく正常に動きます。

ただ、問題があります。
古いPCです。Core2Duo E8400を積んでいます。遅いのです。
表示する写真は、6144x4080で、10〜15MB程度のものです。
これを表示するのに、850ミリ秒程度かかっています。
これでは、使うのにちょっと抵抗があります。

現機の方は、Corei5_4690で、同じサイズの写真だと400ミリ秒程度です。
この程度なら、何とか使える範囲でしょう。我慢できる範囲です。

時間の計測には、System.Diagnostics.Stopwatchを使っています


200923
C#、フォルダ一覧の更新日時によるソート

現在の階層のフォルダのリストを作り、その中の一番新しいフォルダを選びたい、という段取りです。

フォルダのリストは、Directory.GetDirectories(@path)というファイルのリストを取るものと同じような形で取れます。
試してみると、この結果は、明記されていませんが、フォルダ名でソートされているようです。
文字の大きい方が下になって、結果の配列に入っています。
ですので、全部のフォルダ名が日付の数字で成り立っているなら、この状態でなんとかなります。
例えば、ここのメモの日付と同じ様に200923とかをフォルダ名にしておけば、リストでは一番下が最新のフォルダになります。

しかしながら、この際、一般的にフォルダの配列を更新日時でソートできないかと探してみました。
結果、見つけられませんでした。
そこで、以前調べたファイルのソートの関数が使えないかと思い立ち、試してみました。
使えます。全く同じように使えます。



200923
C#、一つ上のフォルダ名
タイトル通りです。
写真を置いているフォルダがあります。
最近はこれが深いのです。私の場合は、今、フォルダの階層が5個あります。フルパスには、\が6個あります。
年度別、月別、カメラ別、日付別、形式別、などで、
G:\A\B\C\D\E\F.jpg、こんな感じです。
このフォルダの一つ上のフォルダまでのパスを作りたい、という事です。

便利な関数、コマンド?があるものです。
末尾のファイル名だけ取り出す、
System.IO.Path.GetFileName(@path)

ファイル名を除くフォルダ部分を取り出す
System.IO.Path.GetDirectoryName(@path)

このフォルダ部分を取り出す関数が使えます。
要するに、これは、最下層がファイル名であれフォルダ名であれ、一段上までのパスを返してくれるものだ、
という記事がどこかに書いてあった記憶があり、恐る恐る試してみました。
フォルダだけのパスの場合、最下層のフォルダを除いてくれます。ファイル名であれフォルダ名であれ、一緒です。

一回呼び出すごとに、こんな感じになります。
G:\A\B\C\D
G:\A\B\C
G:\A\B

ただ、今回メモしたかったことは、末尾に\があるとうまく行かない、という事です。
\が末尾にあれば、その\だけを除いたパスが帰ります。

そこで、末尾の¥を削除しながら実行します。
これも、ありがたいことに、末尾の指定文字を削る関数があります。
if (path.EndsWith("\\") == true) path = fpath.TrimEnd('\\')
これを組み合わせることで、上の結果になります。

同じことをするのに、HSPには、パスを一つずつに分離するコマンドがありました。
これを使って、一段上のパスを作っていました。
探せばC#にもあるのかもしれません。




200923
C#、ファイル名のソート
ファイル名が入っている配列のソートが必要になりました。

写真のファイル名は連番になっています。
フォルダに入れた写真のファイルを取り出すと、ファイル名でソートされて帰ってくるようです。大きい方が下です。
つまり、普通にリストを作ると、新しいものが下になって並びます。
普通にはこれでいいのですが、私のカメラでは連番が9999の次が1に戻ります。
このケースが困ります。ファイル名でのソートでは新しいものが上になる事もあります。

そこで探しました。ファイル名の入ってる配列を更新日時でソートする関数です。
これを見つけて、使わせていただいています。
しかしながら、この構造が私にはよく分からず、結果、ソートされているからまあいいか、という物です。
あくまで私が理解できないだけです。

丸写しで恐縮ながら、以下、総武ソフトウェア推進所様のページから引用、です。
static int CompareLastWriteTime(string fileX, string fileY)
{
 return DateTime.Compare(File.GetLastWriteTime(fileX), File.GetLastWriteTime(fileY));
}

例えば、フォルダ内のファイルを表示する関数()
{
 ・・・
 ・・・
 Array.Sort(files, CompareLastWriteTime);
 ・・・
}

これで、filseの配列にファイルのフルパスを入れて呼ぶと、新しいファイルが下になって帰ってきます。
丁度、撮影した順番で見ることになります。
更新日時を使うと、連番が1に戻っても大丈夫です。

この時、もう一つ気がかりがありました。
逆順でソートする場合はどうするのか、という事です。
新しいものを先に見たい事もあります。
撮ってきた写真は、大体において、後ろの方に良い写真があります。
まあいいか、という程度のものが取れたら、撮影を終わりますので。

さて、どうしようかという時に、先の関数のxとyを入れ換えてみようと考えました。
何となく、ソートの順番を指定している様に思います。
結果、その通りでした。
逆の順番に表示されます。

新しいファイルが下に来るか上になるのかは、結果を見れば分かります。
しかしながら、これが巷に言う昇順なのか降順なのかが説明を見ても簡単には分かりません。
あちこち調べた結果、1,2,3と並べば昇順、3,2、1なら降順の様です。


200921
C#、描画領域へテキストボックスを置く

今作っている写真ビューアで、困っていた事がありました。
画面が足りないのです。

カメラで撮ってきた写真をPCに写します。
それを、全部チェックする必要があります。
無駄なものは残しておきたくないし、まあ多少写りの良かったものは、バックアップなり、別に整理しておきたいし、なのです。

具体的には、一つひとつ写真を見て、削除する、別のフォルダにコピーする、この作業を続けます。
大体はこの作業は、フリーのツールで、XnViewというものを使わせていただいており、とても重宝しています。
XnViewでは写真の編集が出来ます。もちろん、コピーや削除の作業も簡単です。とてもありがたいものです。

このほかに何が欲しかったかと言いますと、コピーです。
ワンキーでコピーが出来るとありがたいのです。
XnVeiwでも簡単にコピー出来ます。
ただ、同じフォルダにコピーするんだったら、コピー先をいちいち指定しなくてもいいではないか、と思います。
具体的な作業は、まず写真を見ます。すると、取るに足らない写真ですが、偶然、ピントだけは合っています。
そこで、別のフォルダにバックアップしよう、となった時、まずコピー先のフォルダを指定するダイアログを開きます。
私は、後日探しやすいように鳥種別、日付別に分類して保存しています。
XnViewでも、ワンキーと言いますか、Alt+Cですが、ダイアログを開けます。
ダイアログでは、前回コピー先がデフォルトで指定されていますので決定、するだけです。

ただ、そのコピー先も前回と同じなら、コピー先指定を省いてもいいではないか、という事です。
違うフォルダにコピーする時だけ、ダイアログを開くようにすると良い訳です。
写真数が数十枚、というなら別に考えません。
時々、1000枚、2000枚と撮ってくる時があります。こうなると、少しの手間が問題です。

という事で、当初、HSPで作ってみました。数年前の事です。
まあ、動いています。
これが今一なのです。何とか我慢できる速度ではありますが、やはり遅いのです。
それに、よく息をつきます。止まる時があります。ガベージコレクションでしょうか。よく分かりません。

そこで、これをC#で作ろうとしています。
一応、動くものが出来上がってはいます。
ただ、思ったよりは早くなりませんでした。HSPより気持ち早いかな、という程度です。
この速度の問題は改めて考える事にしています。

今は、機能を揃える事に苦労しています。
そこでの問題です。

写真を表示する領域は出来るだけ大きく取りたい。
ただ、補助的なデータで、同時に表示しておきたいものが沢山あります。
ついにその領域が無くなりました。

写真のサイズはどれでもほぼ同じで、1:1.5になっています。
これを、1920x1080のディスプレイに表示します。
ディスプレイの表示領域は、横はそのまま1920、縦はタスクバーやメニューバーにとられて、有効寸法は、1000ピクセルほどです。
タスクバーは残しておきたいのです。
この1920x1000に最大に表示すると、領域は、1000X1.5=1500、差し引き1920-1500=420で、横に420ピクセルほどの余裕が出ます。
実際は横幅にも必要な縦線があったり、完全に全画面にしたくない事情などがあって、残りは390ほどになります。
この390ピクセルに必要なボタンやボックスを作っていきます。

ボタンとかテキストボックスとかが作業が進むにつれ増えていき、領域が足りないという訳です。
ここで、HSPの事を思い出しました。
HSPでは、画像表示領域にも、ほぼ全面を使って、普段は見えないテキストボックスを複数配置しておき、必要な時だけ見えるようにしていました。
C#でも、見えないテキストボックスを作れる事は先日知りました。当然の事だったのでしょうね。
これで何とかなりそうだ、というお話でした。


200917
C#、listboxの選択されていないアイテム取得
listboxで選択されている項目?、アイテム?、を取得する方法はすぐ分かりました。(多数紹介されています。)
しかし、選択されていない項目を受け取りたい場合があり、この方法がなかなか分かりませんでした。(探し出せんでした。)

苦労して、ようやく分かりました。
最初の項目を受け取るには、listBox1.Items[0].ToString()です。以下同じです。

よくよく考えたら、必要なインデックスにまずフォーカスを当てて、その後取り出せばいい、という事にも気づきました。
最初の項目を受け取りないなら、istBox1.SelectedIndex = 0;として、listBox1.Textです。


200915
C#、キーイベント

プログラミングの過程で、当初は、マウスでのボタンクリックから作業を始める、という段取りで行きます。
最近の言語は、全部、そのようにボタン類から作業を始めるようになっているようです。

ただ、プログラムや作業の段取りが固まってくると、操作性の問題になります。
作業が単純で大量の処理が必要なものになると、マウス操作よりキーボードからの操作の方が簡単かつ素早く処理できます。
コードが高速に処理されるという事ではなく、実際の作業が簡単になる、という意味です。
そこで、マウスでボタンクリックから始まる作業を、キーイベントでも代替できるようにしていきます。

例えば、「下へ」というボタンが作ってあって、このボタンをクリックすると、次の写真を表示する、という動作をさせていた場合です。
キーイベントを拾うようにして、キーボードの下カーソルが押された事が分かれば、その「下へ」のボタンのルーチンへ飛ぶようにします。
同様にボタンとマウスで操作していた作業を、どれかのキーの押下げにも対応させ、結局、キーボードでほとんどの操作できるようにします。
こうすると、実際の作業の効率が格段に上がります。プログラムの処理速度の問題ではありません。

このキーイベントの事を色々調べました。
当初は、特殊キーの補足に関して、面倒そうな記事が多かったのですが、まず試してみることにしました。

最初に、フォームのKeyPreviewプロパティをTrueにしました。
これで、Form1_KeyDown等で、大半のキーは取得できました。

しかしながら、色々試すうち、この方法ではうまく行かないと気付きました。
多くの記事にある様に、ボタンにフォーカスがあると、まったく役に立ちません。ボタンにフォーカスがある状態で、上カーソルを押すと、上のボタンにフォーカスが移動するだけです。
下カーソルだと下のボタンに移動してしまいます。
つまり、プログラムでキーイベントを補足できない状態です。

試していく内に、解決策を見つけした。
何故か、フォーカスがボタンではなく、テキストボックスにある状態だと、キーコードを取得出来ます。
(想像ですが、テキストボックスでのイベントを作っていないからだろうと思います。)

そこで、当たり障りのないテキストボックスに常時フォーカスが行くようにします。
private void button1_Click()などのボタンのクリックを拾う関数の末尾に、例えば、
this.ActiveControl = this.textBox3、などと書いておけば、マウスでボタンを押しても、フォーカスはテキストボックスに飛びます。
面倒ですが、これをボタン全部に書きました。大変でした。
これで、キーコードが拾えない事はなくなりました。動作としては、こちらの意図通り動きます。

しかしながら、この状態で使っていく内に、再度の不備に気付きました。
そのフォーカスを集中させているテキストボックスの文字が反転してしまう場合があります。
反転したり、しなかったり、条件は分かりませんが、とても見苦しく、気になります。

解決策にたどり着きました。
フォーカスを集中させるためだけのテキストボックスを作りました。ダミーです。何も書込みません。
これを最小限の大きさにして、目につき難い所に置いておけばいいではないか、という事です。
これでもいいのですが、半信半疑で調べたら、テキストボックスは見えないように出来ます。
プロパティにvisibleというのがあって、falseにすると、実行時には見えません。
何のためにあるのでしょうかね。

そこで、全部のボタンの操作後に、ここにフォーカスを持っていくようにしました。
これで、めでたく、キーコードの取得がいつでも出来るようになりました。

まだ使い込んではいませんので、何か不備が出るかも知れません。

ただ、あと一つ、分からない事があります。
本当は、プログラム側でNumLockのON、OFFを操作する事が出来ると楽なのですが、その方法がよく分かりません。
ONの状態でもOFFの状態でも、それぞれコードは帰ってきます。
どちらのコードでも同じ動きをさせれば、実用上はなんとかなりそうに思います。



200913
C#、削除、ゴミ箱へ移動
ファイルの削除で悩みました。
単なる削除の方法はすぐ見つかります。
欲しいのは、即削除ではなく、ゴミ箱へ移動です。

苦労の末、これも何とか見つけ出しました。
using Microsoft.VisualBasic.FileIO
FileSystem.DeleteFile(@フルパス, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
だそうです。

ただ、これを移しても赤線が消えません。
マウスカーソルを赤線に乗せると、参照がどうのこうのというダイアログが出ます。

この意味が、ようやく分かりました。
いえ、意味は相変わらず不明ながら、対策は分かりました。

メニューから、プロジェクト、参照の追加、でリストが出ます。
その中の、Microsoft.VisualBasicにチェックを入れて、OK、で赤線が消えました。
実際に試すと、確かにゴミ箱へ入ります。



200911
C#、ディスプレイのサイズなど

相変わらず、写真ビューアを作ろうとしています。
その中で、フォームの縦横のサイズとかディスプレイのサイズとか調べる必要がありました。
このサイズ関係は、比較的簡単なコードで取得できます。

で、フォームを全画面で起動して、その結果は、

タスクバーをロックしていたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域のサイズ横:1920
フォームがある画面の作業領域のサイズ縦:1040
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1056

タスクバーを隠していたら、
フォームがある画面のサイズ横:1920
フォームがある画面のサイズ縦:1080
フォームがある画面の作業領域サイズ横:1920
フォームがある画面の作業領域サイズ縦:1080
フォームX座標:-8
フォームY座標:-8
フォーム全体サイズ横:1936
フォーム全体サイズ縦:1096
という結果でした。


コントロールパネルなどで見たディスプレイの解像度は、1920x1080です。
見よう見まねで作ったコードに間違いが無いとして、実際には公称のサイズより若干の余裕がある様です。
具体的には、上下左右に8ピクセルずつ余分に作ってあることになります。



200901
C#、写真表示、拡大縮小、劣化
写真を表示する方法で苦労しています。
ここに来て、ようやく目途が立ちました。

方法は探せば探すほど出て来ます。星の数ほどあるように感じます。
その中で、自分の目的にあったものを探すのは大変な苦労です。
元々、系統的な知識のないままに始めたC#ですので。

やりたいことは、写真の表示と、その拡大縮小表示です。
まず、 pictureBox1.ImageLocation、という、これでいのかというほど簡単な方法がありました。
事前に、ドッキングとかZoomとかpictureBoxの設定がいくつか必要ですが、この一行で写真の表示ができます。
ただ、拡大縮小が思い通りに出来ません。もちろん、私が知らないだけだろうと思います。

そこで、次に、
Image.FromStream()、というものを試しました。
これもうまく行きません。
いえ、表示は簡単に出来ますが、拡大とか縮小とかする段階で、問題が出ます。
拡大縮小していく内に、画像が劣化していくのです。
縮小は良いのですが、次にそれを拡大すると劣化していきます。
縮小したものをそのまま拡大しているのだろうと思います。

更にいくつか試した挙句、
Graphics.DrawImageに行き当たりました。
これだと、引数で写真の表示位置とサイズを指定できます。
未だ完全に理解は出来ていませんが、目的に合いそうです。
いえ、この方法でも、同じ写真の縮小と拡大を続けると、当初は画像が劣化していって、実用上は使い物になりませんでした。
縮小までは良いのですが、それを拡大していくと、g画像が荒くなっていきます。
つまり、縮小表示した画像を単純に拡大しているだけだろうと思います。
本来は、まず読み込んだ画像をどこかのバッファに置いておき、実際に画面に表示する場合は、そのバッファから必要な分をコピーして持ってくる、という形が普通だと思います。

具体的には、ネットの記事の見よう見まねですが、
Bitmap canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = Graphics.FromImage(canvas);
Image img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
img.Dispose();
g.Dispose();
pictureBox1.Image = canvas;
これで、一回限りなら、どんな大きさにも対応できます。

2回目以降、つまり、先に表示した画像を拡大とか縮小する場合はどうしたらいいのか考えました。
極端な話、毎回ファイルから読み込んで表示する覚悟なら、上のサイズ類の数字を書き直して使えば済みます。
しかしながら、それでは抵抗があります。
そこで、上のどれかが、いわゆるバッファ操作だろうと見当をつけ、試行錯誤で確かめました。
Dispose()の説明にリソースの開放、とかあります。バッファを消しているのだろうという個人的な解釈です。

まず、どの関数でも共通して使える様に、勝手知ったるグローバル的領域に、
Bitmap canvas;
Graphics g;
Image img;
を持っていきました。
このうちのどれか、あるいは全部がバッファの設定になっているのだろうという期待です。
グローバル的領域とは、
public partial class Form1 : Formの下です。
ここで定義した変数類は、何故かどの関数でも使えます。理由は分かりません。

エラーを大量に発生させながら試行錯誤していくと、
最初の読み込みルーチンは、
if (img != null) img.Dispose();
if (g != null) g.Dispose();
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でうまく行きました。
ここで、1、2行目のif文は、多分、こうしておかないと、写真が変わった時に、バッファ、リソース、メモリ?の類を消しておかないといけないのだろうという想像です。効果や影響は分かりません。
実行しながら、タスクマネージャーなどで、メモリの使用率などを見ていくと、想像していたようには動いていませんが、少なくとも、メモリを使いっぱなしにはなっていないようなので、これで良しとします。

次に、拡大縮小ルーチンは、
canvas = new Bitmap(pictureBox1.Width, pictureBox1.Height);
g = Graphics.FromImage(canvas);
img = Image.FromFile(@写真のフルパス);
g.DrawImage(img, 左肩の横座標, 左肩の縦座標, 横サイズ, 縦サイズ);
pictureBox1.Image = canvas;
でした。
こちらの1、2行目の、canvas=云々と、g=云々はこれが無いと、前の画像が消えません。何故かはわかりません。試行錯誤の結果です。


200830
C#、SplitContainer、PictureBox

画面を二つに分割する事で苦労しました。
最初に試したのは、TableLayoutPanelです。

本題から外れますが、
大文字小文字の使い方が面倒です。
ツールボックスでは、TableLayoutPanel、SplitContainer、です。
コードの中では、この頭文字が小文字になって、tableLayoutPanel、splitContainerと表記されます。
こういうものなのでしょうが、面倒です。
それに、どこかの時点で変更されたのでしょうか、例文などで、PictureBoxなどと書いてるものがあります。

さて、
写真のビューアを作ろうとして、画面を縦に二つに分割する方法を調べました。
右に諸元、左に写真を表示するという計画です。
一応、HSPでも作って使用していて、使用中の1920x1080のディスプレイに最適なコマ割りが、左側の幅を389ピクセル取ると、右側の写真領域の比率が丁度よくなるという事は計算済みです。

今使っている写真の大きさが、6144x4080と5568x3712の2種類です。
単純な比例計算で左側の幅を389ピクセルにすると、右側の縦横の比率が写真の比率と一致します。
つまり、普通に写真を表示した時に、縦横に隙間ができないのです。

とにかく、起動時に、全画面で起動した時、左側の領域を389ピくセルにする方法です。
まず、TableLayoutPanelというのがあることを知りました。
これの横線を0にすると、縦に二つに分割した画面が作れます。
これには、欠点が(私が知らないという意味です)、二つあり、
全画面をやめて窓表示にしても、縦の分割線に位置を変更できない事と、
左側に置いたボタンなどのコントロールの位置を指定できない事です。

そこで、次にSplitContainerというものを調べてきました。
これで、意図通りの画面が作れました。
Form1のWindowStateをMaximizedに、
splitContainer1のSplitterDistanseを389に、(ややこしいですが、これは、splitContainer1.Panel1ではありません。)
とすることで、所期の目的が達成されます。
全画面で起動しますが、窓にしても、左側は一応固定されています。しして、位置をずらしたければ、マウスでドラッグすると移動出来ます。



200828
C#、ボタン名、関数名

前回のフォームアプリで、ボタン名とそのイベントハンドラというのでしょうか、ボタンをクリックした時のコードを記述する関数の関数名が一致せず、困りました。
確か、コードの中で、button1.Enabled云々とある所で、右クリックメニューから名前を変更すると全部変わると思って、実行しました。
コードの部分は一括で変更できました。しかし、関数名が変わりませんでした。
ややこしい話で、以降はどこにそのボタンの関数があるのか分かりにくい状態になりました。関数名とそのボタン名とが違うのですから。
動きに関しては、意図した通りに動くので、問題はなかったのですが。

ようやく、正解が分かりました。変更する順番が大事です。
ボタン名とその関数名(イベントハンドラー?)の名前を合わせるには、まず、最初に、ボタンのプロパティでnameプロパティを変更しないといけません。
その後で、ボタンをダブルクリックして、そのボタンの関数を生成します。
こうすると、その関数にも書き換えていた名前が使われます。
順番を逆に、関数を先に作っておいて、nameを変更しても、関数名は変わりません。


200827
C#、型変換?
何気なしに、下のようなコードを書いていました。
int a =0;
string b="";
b+=a;
これがエラーになりません。
何やらの型変換が起きています。調べても用語が分かりません。当たり前の事なのでしょうか。



200826
C#、SelectedIndex、SelectedItem

comboBoxのSelectedIndexとSelectedItem、見様見まねで使っています。ようやく、違いが分かりました。

私の理解では、
comboBox1に、always、hourly、daily・・・、とデータ(選択肢)がセットしてある状態で、
comboBox1.SelectedIndexには、数字(int)が入ります。選択肢の先頭から0,1,2です。
選択肢の2番目のhourlyが選択されたら、comboBox1.SelectedIndexは、intの1です。
こちらの方はそのまま代入も出来ます。comboBox1.SelectedIndex=0;とすると、一番目のalwaysが選択された状態になります。
ただ、数字ですので、選択状況をボックス以外に表示する時や、テキストファイルに保存する時にはcomboBox1.SelectedIndex.ToString();、とします。

comboBox1.SelectedItem、には、選択肢の文字列、alwaysとか、hourly、とかが入っています。
こちらの方は、選択肢の文字列が取り出せます。方法が少しややこしいですけど。
直接、string str = comboBox1.SelectedItem;とするとエラーになります。
object型とかキャストとかのエラーメッセージが出ます。
(string)comboBox1.SelectedIndex;か、comboBox1.SelectedIndex.ToString();とすると、選択された文字列が取り出せます。

ここまで、整理してきて、comboBox1.Text、というプロパティ?があることに気付きました。
先のcomboBox1で3番目のdailyが選択された状態だと、dailyが帰ってきます。
目的は、この文字列を取得する事でしたので、comboBox1.TextでOKです。
comboBox1.Textに関しては説明してあるページが少ないように思います。新しく追加されたものかも知れません。


200825
C#、this.Close()
プログラムを終了する時(フォームを閉じる時)は、this.Close()、とあり、各所に置いています。
とにかく、意図通り終了できていました。

今日、変な動作をするケースに気付きました。
終了すると同時に、例外が発生しているようです。
例外が発生せず、期待通りに終了する場合もあります。
終了、というボタンを作って、そのクリックイベントでthis.Close()すると正常に終了します。
フォームにあるXボタンでも正常に終了できます。

this.Close()をあちこちに置いて調べてみました。
原因が大体わかりました。いえ、原因というか、発生する構造というか。
this.Close()の次のコードが実行されています。
次の行に、フォームのボックスに表示するコマンドが置いてあった場合は、
破棄されたオブジェクトにアクセスできません、という例外が発生しています。

並行処理、みたいなもので、動作を止め切れていない様子です。

ただ、この現象は、デバッグモードの時だけで、デバッグ無しで実行、だと発生しません。
多分、Releaseモードでも大丈夫なのではないでしょうか。




200820
VS、ショートカットキー

C#をというか、VisualStudioを始めて二か月半ほどでしょうか。編集中、メニューを開くのが段々面倒になります。
そこで、使い勝手のいいショートカットキーを覚えていきます。

最近、ようやく覚えたものに、
F5キーがあります。デバッグの開始です。
これまでは、いちいちメニューを開いて、ビルドし、メニューのデバッグをクリックしていました。
これを、F5一発で済ませられます。ビルドエラーの時は止まりますので、問題は無いという事に気付きました。

関数間の移動に、F12や、Ctrl+マイナスキーなど、便利ですね。

ショートカットキーの怖い所もあります。
万国共通の、コピーペーストの関連で、Ctrl+A、Ctrl+C、Ctrl+V、Ctrl+X、などは便利な反面、よく間違います。
よくやるのが、Ctrl+V、とすべきところをCtrl+C、としてしまって、クリップボードを空にしてしまう事です。



200819
C#、ボタン名の変更
ボタン類を増やして行くと、コードが読み辛くなります。
button1は何のボタンだったかな、という感じです。

そこで、ボタンの用途に合わせて、ボタン名を変えることを考えました。
button1.Enabled = false、とするより、
Btn_end.Enabled = false、等とした方が、
終了ボタンを無効化したな、と分かります。

これはこれでいのですが、悪影響が出ます。
一つは、ボタンをクリックした時の関数名はそのままです。
そして、変更後に更にボタンを追加すると、button1がまた作られてしまいます。

で、関数はどうなるかというと、
最初のボタン名を変更したボタンの関数は、
private void button1_Click(object sender, EventArgs e)、で
後で作られた、button1の関数は、
private void button1_Click_1(object sender, EventArgs e)
となっています。

動きに矛盾はありませんが、ちょっと分かりにくいです。
私の知らない方法が有るのかもしれません。



200818
VS、二重起動

未だ、分からない事も多いながら、VisualStudio2019のエディタにも多少は慣れたと思います。
ただ、困った事に、油断すると重複して起動してしまいます。困った物です。

新しくプロジェクトを作る時以外は、slnファイルのアイコンを作っておいて、そのアイコンをダブルクリックして起動しています。
このアイコンをダブルクリックしさえすれば、同じものが何個でも起動します。
今、試してみたら、本体を起動して出てくる最近のリストを選択しても同じでした。やはり、重複して起動できます。

TeraPadで試すと、二つ起動は出来ますが、同じファイルを読み込もうとしても読み込みません。
右クリックメニューから、ファイルメニューから、どちらもダメです。

メモ帳は普通に読み込めました。

VisualStudioCodeも試してみました。
こちらは、よくわかりません。肝心な所で英語が出てきたりして、要領を得ません。
読み込めたり、読み込めなかったりします。



200815
C#、str.Contains(s)
strにsという文字列が含まれるか、という所で、str.Contains(s)を使いました。

いえ、特に問題はなかったのですが、ここでfalseを試してみようと考え、
string s="";
if (str.Contains(s) == false){}
としました。
バグ取り、と言いますか、動作試験などで、よくやることです。

しかしながら、これが期待通りに動きません。{}内は通らず、スキップしてしまいます。
冷静に考えると、当然でした。""は、どこにでも含まれています。trueです。


200814
C#、エラー処理

C#、VSの範疇かも知れません、C#でデバッグ中にエラーが発生すると、ブレークポイントみたいな感じで止まります。
発生した行と、原因の説明が表示されます。
心配なのは、これが実行ファイルで発生した時、どういう処理になるのか、という点です。

今回、簡単なエラーが出ましたので、思い切って試してみました。

VSのメニューにあるデバックなしで開始、bin/Debugフォルダに保存されている実行ファイル、bin/Releaceフォルダにある実行ファイル、のいずれの場合も、例外が発生した、という意味のダイアログが出ます。
続行と終了の選択が出来ますが、実質終了するだけです。
終了と言っても、実質は強制終了ですが、平和的な感じで終了できます。

この時のエラーは、ファイルが見つからない、というものでした。
念のためにもう一つ、0で除算しました、となるものを作ってみました。

対応は同じです。
デバッグモードでは、その行で止まり、原因が表示されます。
デバックなしで開始、では、先と同じダイアログが出て、終了させられます。

ありがたいのは、そのダイアログをよく見ると、詳細、というボタンがあり、そこにエラー発生の説明や発生した行番号まで表示される事です。
これはReleaseモードの実行ファイルでも同じです。行番号が表示されます。



200813
C#、forループ
forループをよく使います。
いえ、他にもループがある事だけは知っていますが、使ったことがありません。使い方が分かりません。

いつも気になっていた事です、最初からforの条件式に合わない場合はどうなるのか、という事でした。
c=-1;の状態で
for (int i=0; i<c; i++)、のループに入った場合です。

今まで、適当にやっていて問題は出ませんでした。
今日、しっかり調べてみました。

解説のあるページはネットにも多いのですが、このかゆい所に手の届く説明はなかなか見つけられません。
そこで、最後の手段、F1でMSのヘルプを見てみました。
いつも、このF1で出てくる説明は、訳の分からない事が書いてある場合がほとんどです。
しかしながら、今回は大当たりでした。しっかり書いてありました。
肝心の部分を書き出すと、

conditionセクションの式は、ループの反復の前に毎回評価されます。
式が true に評価される場合、次のループの反復が実行されます。
そうでない場合は、ループが終了します。
だそうです。
conditionセクションとは、上の例では、i<c、の部分です。

実際には、もっとねちねちと書いてあります。要約すると上の様になります。
つまり、最初から条件式に合わない場合はループは一回も実行されない、と解釈できます。

問題は、私の解釈で正しいかどうかなのですが。
振り返ると、HSPでも同じだったような記憶があるかないか、おぼろげですか、思い出しました。
どこでも共通なのでしょう。

実際に、動作がその通りなのか、調べるのは難しいです。
プログラム流れで、実際には、先のループの前の段階で、
if (c<0) return;
みたいなコードを入れるからです。

ここで気が付いて、試してみました。簡単なコードで試せばいいのです。
int c = -1;
for (int i = 0; i < c; i++)
{
MessageBox.Show("内");
}
MessageBox.Show("外");

実行すると、外、だけが表示されます。

200810
C#、エディタ、<>

VSのエディタは機能が多くて便利です。
まだ、記号の意味や操作方法の分からない事も多いです。

その中で、困ることがひとつ、<や>の扱いです。不等号ですね。

今、サイトマップファイルを扱うプログラムを作っています。
そこで、頻繁に出てくるのが、<url>とか</loc>とかいう文字列です。
この文字列をタイプする分には問題ありません。
が、なぜかコピー、ペーストで持ってくると、エディタ側で勝手にスペースを入れてくれます。
< url >というようになります。
//の後に貼り付けるとか、""の間に持ってくるとかだと大丈夫です。
計算式と勘違いするのでしょうね。

もし、文字列の先頭が<url>となっているなら、という様な構文はよく作ります。
タイプミスを減らす為、文字列を引用する時は、出来るだけコピーで持って来るようにしています。
そこで、油断すると、先ほどの変化が起きます。困ったものです。



200809
C#、File.Copy()、更新日時
ファイルのバックアップを作る必要に迫られ、調べました。
System.IO.File.Copy(@path1, @path2, true);という関数を見つけました。
コピー先に同名のファイルがあっても上書きする、というものです。
文字コードの指定とか、宣言とか、前置きも何もいらない(多分)様です。すぐ試してみました。

何かが違います。
ふと気が付きました。
ファイルの更新日時が変わりません。いえ、多分変わらないのだと思います。
普通の事ですが、不便な点があります。
上書きされたかどうか分かりにくいという事です。

実は、HSPでは通常、コマンドでコピーすると更新日時が変わります。これも多分です。
更新日時が変わらないと、実際に上書きされたかどうか分かりにくいのです。
上書きされた際、更新日時がその上書きされた時間になるなら、前回のコピーの後、1分待って試してみると結果が分かります。
コピー元のファイルの日時のままだと、こうはいきません。1分待ってコピーしても、あれ、上書きされなかったかな、と心配になります。
ファイルの中身を変えるなりして、その中身を見てみないと分かりません。

元々、エクスプローラなどでコピーする場合は、更新日時は変わりません。
当たり前で、まあ、慣れの問題かもしれません。



200808
C#、Win8.1、.NET

このPCと無関係の環境で、C#の実行ファイルを起動したいことがあり、マルチブートのWin8.1に切り替えてみました。
これが、立ち上がりません。
エラーメッセージのダイアログが英語ですので断定ではありませんが、意味は、.NETFramework、Ver4.7.2が必要だ、インストールするか、と書いてあるようです。
確かに、C#のプロジェクト云々の時、NET云々が沢山出ていました。必要な物なのでしょうし、私の8.1は飾りみたいなもので、必要最低限と言いますか、何も追加してありません。

Win10の方に、それがちゃんと入っているのか、入っていないはずはないのでしょうが、調べてみました。
これが結構面倒でした。

まず、コントロールパネルなどにあるプログラムと機能を見てみました。
ありません。
Windowsの機能の有効化の所に、.NETFramework、3.5の記述はあります。
これでは足りません。
もう一つ、.NETFramework4.8AdvancedServices、というものもあります。
4.8だからよさそうなものの、その後ろの英語の意味がよく分かりません。

そこで調べてみました。
MSのページにバージョンの確認方法が書いてありました。
regeditから調べられます。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Fullのキーがあれば4.5以上が入っている、あと、その先の細かい数字を調べるとバージョンも分かる、という事です。

で、その通り調べていくと、どうやら4.8が入っています。
これも、4.8と書いてある訳ではなく、適当な5、6桁の数字を見比べて判別する、というものでした。
これで大丈夫だという事になりますが、面倒な話でした。
なぜ、もっとはっきりと出さないのでしょうかね。

それに、普通には.NETは入っているものなのでしょうか。
そこで、旧機を調べてみました。Win10です。
こちらには入っていました。と言いますか、先の実行ファイルがすんなり立ち上がりました。
必要な.NETはインストールされているという事になります。





200808
VS、バージョンアップ
VSのバージョンアップのダイアログが出ました。
バージョンアップは頻繁に出ます。5月に始めて、月に一回以上のぺーズだと思います。記録はしていませんが。
今回は16.7.0です。いつもの様に、すぐ実行しました。

今回は変化がありました。嬉しい事ではありませんが、起動時にダイアログが出るようになりました。
ソリューションを準備しています、とかいうメッセージです。
このダイアログが出ている時間は一秒そこそこです。
出ない時もあります。何度か試している内に、状況が分かりました。
PCを立ち上げ、最初にVSを使う時だけです。2度目からは出ません。
状況はVSを立ち上げ、リストにある目的のslnをクリックして起動する場合でも、直接slnのショートカットから立ち上げても同じです。最初にslnを起動する時、一回だけ出ます。
これが、PCの再起動でリセットされるみたいで、また最初の一回だけ出ます。

起動時のダイアログでは、バックグラウンドタスクがまだ実行中です。というものもあります。
これは、必ず出ますが、ひっそりと出ます。気にすることもないようなメッセージです。
今回のダイアログは、画面の真ん中に出ますので、とても気になります。
何も出さずに待たせる方が良いと思います。その方が、ほんの僅かでしょうが、早いはずです。

私の環境での、ショートカットからの起動に要する時間は、
一回目の起動、その面倒なダイアログが出る場合です、カーソル点滅まで15秒、バックグラウンド云々が消えるまでに更に10秒ぐらいでした。
2回目以降は、エディタのカーソルの点滅が始まるのに約10秒、バックグラウンド云々のダイアログが消えるまでに更に5秒ぐらいです。
あ、この差はダイアログのせいではなく、一回起動すると、何かメモリに残すのでしょうね。
また、この差があるせいで、一回目だけ、間つなぎのダイアログを出す様にしたのでしょう。
面倒な事です。

200812追記
再度、バージョンアップの通知がありました。16.7.1です。
すぐ、アップデートしました。
前回は、確かPC自体の再起動が要求されたと思いますが、今回はありませんでした。
今回の変化は、参りました、起動時の、ソリューションを準備しています、のダイアログが毎回出るようになりました。

起動に要する時間を再確認してみました。
PC起動後の一回目のVSの起動が、15秒+10秒、
2回目以降が、10秒、5秒、程度です。変わりません。
気持ち遅いようにも感じます。気のせいでしょう。


200807
C#、プリプロセッサ命令、#if DEBUG、注釈

デバッグモードの時だけ実行させたい命令があります。
動作確認用にダイアログするとか、テキストボックスに途中経過を表示するとかです。
HSPでは#defineで同じ様な事が出来ていました。
C#でも探していましたが、今日ようやく、このコマンドにたどり着きました。
#if DEBUG
#edif、です。

文字通り、VSのエディタでDebugにしている時だけ有効になるコマンドです。
Releaseにしていると、VSから起動した場合でも、Releaseフォルダにあるビルドした実行ファイルでも、このコマンドに挟まれた部分は実行されません。
逆に、Debugにしている場合は、メニューで、Debugなしで開始、でも実行されます。

この件、と言いますか、条件付きで実行したい場合、色々試しています。
//の注釈行は手軽なのですが、コードが長くなると手間です。
/*・・*/は復数行指定する時に便利なのですが、ネストが効かないというか、よくわからない状態になります。
コメントアウトしたい部分の一部に、既に/**/を使っている場合、よくわからない状態になります。

以前、調べた事で、#if trueがありました。
デバッグに関しては今日の分が便利です。書き直す必要がありません。


200804
C#、int、return
C#では、毎日の様に驚く事があります。

恥ずかしながら、
int aa(string bb)
{
  int cc;
  for (int ctr = 4; ctr < dd; ctr += 7)
  {
    bool tof = ee[ctr].Contains(bb);
    if (tof == true)
    {
      cc = ctr;
      break;
    }
  }
  return cc;
}
という感じのコードを書きました。

最後のreturn cc;に赤い波線、インテリセンスでしたか、が出て消えません。
マウスカーソルを当てると出てくる解説には、未割当云々と出ています。
解決後に考えると、その解説の通りなのですが、発生時には慌ててもいますし、理解不能でした。

原因は、最初の宣言で
int cc=-1、等、初期化?;が必要という事です。
納得は出来ますが、厳しすぎるようで、少し考えていただきたいような気もします。

先日、returnはループの中からでも問題ない、という事を知りました。
それに、trueは省略できますので、
少しスマートに(極めて個人的な感想です。)書き換えてみました。
int aa(string bb)
{
  for (int i = 4; i < dd; i += 7){if (ee[i].Contains(bb)) return i;} return -1;
}
と書けそうな気がします。
いま、試すと、エラーは出ていません。動作は未確認です。
動作も試しました。意図通り動いています。動いているように見えます。

こうなると、関数にする必要もありません。
ただ、分かりにくいし、本当に意図通りなのか、確信が持てませんので、私には使えません。
元に戻して、使っています。

200802
C#、str.TrimEnd()

末尾の空白行を削除するという事で、str.TrimEnd()を使ってみました。
全て手書きで作ってる場合は問題にもならない改行コード(0D0A、CRLF、\n、\n\a、以下改行)ですが、プログラムで行数をチェックしていると、これが問題になります。

そこで、簡単に末尾の改行を消せるみたいで、表題のメソッド?、関数?、を使ってみる事にしました。
どのような動作になるのか、コードの前後を調べました。
・・
・・
</urlset>改行
改行
改行

となっているファイルをstr.TrimEnd()を通すと

・・
・・
</urlset>

となります。
つまり、末尾にある改行は全部削除されます。
末尾の行は</urlset>だけになります。直後の改行も消えます。
これで問題はありません。
行数はちゃんとカウントされます。

なお、最後の行に改行のあるなしは、行数のカウントでは同じです。
つまり、末尾が
</urlset>改行、と
</urlset>、だけの行は、同じ一行です。



200802
C#、throw
try、cacth、throw、構文というのでしょうか、ネットから頂いたコードの中にありました。
指定のページが実際にサーバにあるか調べる為に使わせていただいています。
ページがある場合は、何も問題なく処理されます。
しかし、でたらめなURLを指定すると、throwの所でエラーで止まってしまいます。

on error gotoみたいなものだと思っていましたので、びっくりです。
デバッグモードでしたので、もしかと思ってリリースモードで試してみました。
こちらでは、ダイアログが出ます。続行するか終了するか選択するものです。
続行を選ぶと、すんなり回復します。
自前のダイアログを出す方法があればと探しましたが、見つけられません。


200720
C#、フォームに四角形の描画

フォームで画面を作っていく時、四角形を描画したい場合があります。
ボタンとかボックスとか幾つか配置してあり、このボックス類は一つのグループです、みたいな表示をしたい時です。

調べても、調べても、この方法が分かりません。
その中に、ラベルが利用できる、みたいな記事がありました。
正式に作る方法が分からないので、そのラベルを転用する方法に挑戦しました。

普通にラベルを配置します。
右クリックメニューに最背面へ移動、があります。こうしないと他のコントロールが隠れてしまいます。

そのままでは、文字数に合わせた小さなボックスで、どうしようもありません。
後、プロパティを変更していきます。
文字があるとまずいので、Textを削除します。
AutoSizeをFalseにすると、サイズを自由にできます。これで大きな四角形が描けます。
BorderStyleをFixedSigleにすると枠線が出てきます。
BackColorで色の指定が出来ます。

これで、必要なコントロールを囲うことが出来ました。


200729
C#、カレントフォルダ
レジストリが使えるなら、問題にはならない事でしょうが、そのような知識はありません。
あちこちに、素人は、レジストリをいじるなと書いてありますし。

プログラムでカレントフォルダを調べることは、簡単にできます。
System.Environment.CurrentDirectory、です。
ここにファイルを置きたいことはよくあります。
作業内容を次回の起動時に復元したい時に使う設定ファイルなどです。

さて、C#の場合、多分VS共通だと思いますが、このカレントフォルダが複雑です。
まず、コードが書かれているForm1.csがあるフォルダがあります。
ただ、これはカレントではありません。
ソリューションのフォルダ、あるいはプロジェクトのフォルダというべきものでしょう。
私は、今だに、ソリューションとプロジェクトの違いが分かりません。

さて、カレントは実行ファイルがあるところです。
この実行ファイルが二つあります。デバッグ用とリリース用です。別々です。
\bin\Debug
\bin\Release
となっています。

ですので、先の設定ファイルなどDebugフォルダに置いておかないといけません。
面倒な事です。こうしないと、動作試験ができません。



200726
C#、forループ、return、break、goto

これまで、forなどのループの中で、途中で抜け出すには、breakと覚えてきました。
ですので、ネストされたループから抜け出すのにフラグを使ったりして苦労したものです。

ここまで、C#でも同様に思っていましたが、詳しく調べてみたら、違うようです。
gotoでもreturnでも自由に抜け出せるようです。


200726
C#、false、!
if (!kkk.Contains(rrr) == false){}
このコードが意図通り動いてくれないので困りました。

原因は先頭についている小さな!でした。
ネットで、文字列が含まれているのか調べる構文をコピーしてきて使いました。

元々は、f (!kkk.Contains(rrr)){}、となっていたものです。
これで使わせていただいていたのですが、コードを見直す最中に、やはり、==が欲しくなります。
==が無いと直感で分かりにくい事と、
最近、trueとfalseのスペルを覚えましたので、==false、を付けて、見やすくしようとしました。

すると、突然、動きがおかしくなりました。
先頭の小さな一文字を消し忘れていたのです。



200725
C#、配列のコピー

文字列の配列のコピーに Array.Copy()を使いました。
この動作が、参照なのか値のコピーなのか分からず、困っています。
ネットでは、参照渡しになっていて、コピー先を変えると、コピー元も変わってしまう、と書いてあるようです。
逆にそんなことはない、と書いてあるように見えるものもあります。
一番の問題点は、私が専門用語を理解できない事なのですが。

そこで、実際に試してみました。
Array.Copy()で、配列kkから配列mmへコピーした直後です。

1行目を表示させると、
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm[0]は、<?xml version="1.0" encoding="UTF-8"?>

次に
mm[0] = "test"、としてみた結果です。
kk[0]は、<?xml version="1.0" encoding="UTF-8"?>
mm0]は、test
となっていました。

念のため、
kk[0] = "testtest"、としてみた結果は、
kk[0]は、testtest
mm[0]は、test
でした。

これで、はっきりしました。
参照ではない、という事です。

string型の配列の場合、参照ではない、と書いてある記事も見ました。
これだろうと思います。



200725
C#、バックアップ
プログラムを作りながら、ここでバックアップを作っておきたいと思う時があります。
やみくもに発展させてしまって、どうにもならなくなって、元のちゃんと動く状態まで戻そうとするときの為です。

HSPなら、単純にファイル名を変えるなり、フォルダを変えるなりして、毎日でもバックアップしておけました。
どうやら、VSでは単純ではないようです。
設定ファイルみたいなものがあって、バックアップから単純に戻しても動かない、みたいです。
でも、一応、節目節目で、フォルダごとバックアップしてあります。
しかしながら、これを戻してみた事はありません。
戻す場合は、フォルダごと戻さないといけないでしょうし、そうすると、現在のファイルをどこかに退避する必要がありそうです。
その退避した方が使えるか不明です。
バックアップも現在のファイルも同時に使えないと、怖くて使えません。

200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまうとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。

201009追記
ついでがあり、少し前にバックアップしたもので、slnファイルをクリックしたらどうなるか試してみました。
つまり、別のフォルダにコピーしたものがそのまま使えるか、という事です。
使えます。
フォルダごとコピーしたものです。
当初、コードを出すのに苦労しました。起動はしますが、コードが出てきません。
いえ、出ることは出るのですが、コードを開いた状態が保存されません。
slnファイルを起動すると、画面が空白状態になっていて、コードを見るには左側の何たらから、関数名などをクリックする必要がありました。
再起動しても同じ操作が必要でした。

そこで、実際に使っているものと見比べて、コードのタブのピンを縦にする必要がある事に気付きました。
こうしておくと、再起動しても、同じコードが見られる状態で開きます。
何やら、初期化されているようです。
この件、8/28にも試していますね。


200724
void、boid

boid サブフォルダ変更()
今日作った関数名です。これがエラーになって、原因が分からず、気が付くのに1時間以上かかりました。

赤い波線が出て、消えません。
関数内のreturn;の所にも波線が出ています。ヒントには型が違うみたいな表示だったと思います。

このヒントがよく出来ていると思います。赤い波線、インテリセンスの事です。
マウスカーソルを波線の上に持ってくると、エラーの原因やヒントが出てきます。
残念な事に、それを読んでも理解できる程の知識がありません。
ヒントの中に、解決策出ています。クリックしていくと、その案に沿ってコードを書き換えてくれます。
この方法で解決する場合もあります。

今回は、四苦八苦した挙句、スペルミスに自分で気付きはしました。
後で確認したことです。先のヒント、いくつかの解決案が箇条書きに出ているのですが、その最下段に、
boidをvoidに変更、という項目も出ていました。

あらためて感心すると同時に、最下段での案内です、そんな間違いはまずないだろうと思われているようです。

200723
VS、フォントサイズ
エディタのフォントサイズは、Ctrl+マウスのスクロールボタンで簡単に変更できる事に気付きました。ただ、多少の不便さがあります。
VSのメニューとCtrl+のショートカットが連動していません。
設定が維持されない時があります。

VSの使い始めの頃、フォントサイズの変更に苦労した覚えがあります。設定は、ツール、オプション、環境、フォント及び色、にあります。
どうやら、Ctrl+は規定外かもしれません。

メモ帳でも試しました。
メモ帳でも、Ctrl+マウスのスクロールボタンで変更できます。
つまり、Win共通のショートカットなのでしょう。

ただ、やはり、安定しません、と言いますか、設定が維持されません。。
メモ帳では、メニューの、書式、フォントで簡単に設定できますので、行き来して調べました。
ショートカットと連動していません。
ショートカットでの変更は、その場限りの変更の様です。
メモ帳を再起動すると、メニューで設定したサイズに戻ります。

VSでは、どうやら、すべて保存を実施した後では、設定が残るようです。
それでも、設定メニューの数字は、つまり、メニューに表示されるフォントサイズは実際と合いません。
ショートカットで変更して、そのサイズが維持される場合でも、ツールオプションの中のフォントサイズは変わりません。
多分、です。何しろ再確認が面倒なので、好みの大きさからもう変更したくありません。



200723
サイトマップファイル

このサイトは、一応、サイトマップファイルが作ってあります。HSPでの半自動化の一環です。
この作業がここまでの懸案で、半自動化のメモに書いていますが、何しろ30000行、600KB程のテキストファイルです。
ファイルを更新するのに50秒程かかっていました。
ページの更新はほぼ一日おきにしていますので、この作業も一日おきです。少し辛い物がありました。
この問題は、こちらのC#などを勉強する過程で原因に気付き、現在では3秒程度で終わる様に改良しました。

更に、このC#をかじっていく内に、C#がコンパイラと同じ程度に高速だという事を実感する様になりました。
そこで、このサイトマップファイルの更新作業をC#で組もうとしています。
現在、このページのメモは、大半、この作業に絡むものです。

そして、今、大まかなところで出来上がりました。後は、エラー処理と操作性の改良だけです。
そこで、実行時間を測定してみました。
やはりC#だと、ミリ秒の世界です。
実行時間は、ソートが入れてある関係で、ファイルの先頭近くに追加するか、末尾近くになるかで大きく違います。
一番手間を食うような状況、つまり、ファイルの末尾に追加するような作業で、500ミリ秒程度で終わります。


200722
C#、フォルダ選択ダイアログ、プロパティ
フォルダ選択をマウスで指定出来るように、と調べると、これが出てきます。
FolderBrowserDialog fds = new FolderBrowserDialog();

ただ、これは必要最低限と言いますか、まあ、意図通りには動きますが、操作性はよくありません。
本来は、普通のエクスプローラと同じ操作性で、左側にクイックアクセスやドライブなどが表示され、右側で目的のフォルダを選択するものです。

先のダイアログだと、その左側部分がありません。
それに、どうやらデスクトップが既定になっているみたいで、これが選択リストの最上段に出てきます。
必要なフォルダは、データドライブの中の、かなり深い位置にあり、スクロールしないと出てきません。

せめて、初期のフォルダだけでも見える状態で出てこないかと調べました。
fds.RootFolder = Environment.SpecialFolder.MyComputer;
とすると、何とか目的のフォルダが見える状態でダイアログが開きます。
これが確実ではなく、たまには別のフォルダが出てくるときもあります。
どうやら、前回の動作を覚えているようです。

200722
C#、テキストボックスの自動スクロール

複数行のテキストボックスの表示が、自動でスクロールする事に気付きました。
HSPではこれが無くて、苦労しました。システムコールか何かで実現させていました。
ボックスのプロパティに可否があるのかもしれません。
ま、うまくいっている所は探しません。

200720
#if、#endif、プリプロセッサ命令
#if true
#else
#endif
が使えます。

今まで、変数類を大幅に入れ替えて試したい時、
/*
*/、で囲んで、切り替えていました。
#ifの方が楽です。
trueをfalseに書き換えるだけで済んでしまいます。


200719
str.Remove(0, 1)

文字列の先頭ある「/」を削除したい時の処理、正しくは、
if (str.StartsWith("/") == true)
{
   str = str.Remove(0, 1);
}
なのですが、この=の前のstrを忘れて、
str.Remove(0, 1);だけにしてしいがちです。
困ったものです。
確かに、解説には、作業後の文字列を返す、と言うような事が書いてあります。

左側のstrに入る様だったら、右側にも入りそうなものですが、そうはなりません。

ただ、これとか、文字列の末尾の一文字を削る関数もあり、C#の便利な所です。


200717
C#、フォーム表示後にダイアログ表示、Form1_Shown()
フォームを表示させた直後の作業で、例えば、ファイルのあるなしを調べて、目的のファイルがない場合に、ダイアログでメッセージを出します。
この際、最初に配置されているpublic Form1()という関数がそれらしく、最初に実行されるのだろうと思い、ここにこの段取りを書き込んでいました。
ファイルの読み込みや、ボックスへの表示など、普通にはこれで予定通りです。
しかし、先の様にエラーのダイアログを出す様にしたら、肝心のフォームが出てきません。ダイアログだけが表示されます。

これでは、多少見苦しいので、調べました。
Form1_Shown()、という関数がそれで、ここに書き込むと、フォームの表示後にダイアログが出るようになりました。

正確には、private void Form1_Shown(object sender, EventArgs e)、です。
フォームのプロパティで、Shownという項目をダブルクリックすると出現します。



200717
C#、関数、引数、参照渡し、値

関数について、少し勉強してみました。
ここまで、使わない訳にもいきませんので、使ってはいますが、全部、引数無しの、Void関数名()、です。

必要な変数は、試行錯誤で全体にスコープされる場所を見つけました。
classの下です。
ここに置いておくと、これ以下のどこからでも参照?(言葉については不明)できています。

ネットの記事では、C#にはグローバル変数はない、と書いてあります。
多分、classとかnamespaceとかを超えられないという意味だと思います。
そのような大掛かりなものは、私には作ろうにも作れません。

そこで、折角なので勉強してみました。
引数について、参照渡し、値渡し、配列は参照渡しになる、という事は、昔読んだ記憶があるC言語と同じです。

ただ、そこまで厳密な区別は出来ず、肝心な変数はどこからでも参照できた方がしっくりきます。
これは、グローバルな変数しかない言語から入ったものの欠点だと、やはりどこかの記事にありました。


200712
C++、デスクトップアプリ
C++をまた少し触ってみました。
簡単にフォームが作れないかと思っての事です。過去何度も挑戦して、失敗しています。
なんのことはない、プロジェクトの所でデスクトップアプリを選択すると、簡単にできます。
出来ると言っても、初期画面のままです。どこにコードを書き込むのかさえ分かりません。
分かったとしても、これまでに知識はほとんど役に立たないと思います。そんなコードが並んでいます。

とにかく、フォームでしょうかデスクトップ画面というのでしょうか、窓は、初期状態でビルドしさえすれば表示されます。



200712
VS、プロジェクトのバックアップ、再利用

C#でプロジェクトかソリューションか、とにかく今作っているコードを利用して別のプロジェクトを作りたい場合があります。
普通には、ファイルをコピーして、それを使えばいいはずです。
バックアップでも同じです。ちょっと作業が一段落して、一応ちゃんと動いている。これから先の作業でどうなるか分からないので、バックアップしておく。最悪、これからの作業が行き詰ったら、そのバックアップに戻ってやり直せばいい、はずです。

調べたら、VSの場合、これが通用しない様です。
何やら設定ファイルみたいなものがあって、絶対パスになっているのでしょうか、フォルダを変えてしまうと、うまくないみたいなのです。
試してみて、元も子もなくなるのが心配なので、この件は試していませんが。

フォルダごとのコピーもバックアップも通用しない様なのです。困ったものです。
200829追記
フォルダごとのバックアップは有効でした。
プロジェックトを作って、被害が少ないように、比較的早めに試してみました。
フォルダごとバックアップしていたものを、元のフォルダに、そのまま何も変えずに戻すと、普通に動きます。
ついでに、フォルダを変えてしまううとどうなるかも試しました。
動きます。起動に少し時間がかかったような気がしましたが、何事もなく動きました。



今回も、そのようなケースで、新しくプロジェクトから始めます。
作るのは、C#、Windows、デスクトップ、Windowsフォームアプリケーション、.netFramework、です。
(次回の為に、プロジェクトの選択項目をメモしておきます。)
予めフォルダを作っておいて、そこを指定します。プロジェクト名はフォルダ名にします。根拠は、その方が面倒がなさそうなので。
フォルダは、新規の際のプロジェクトの場所を決めるボックスでも指定できます。
これが間違いやすいのです。
例えば、G:\data\cs\map、というフォルダで作業したいのに、出来上がって調べてみると、G:\data\cs\map\mapとなっていた、という事が起きがちです。
なので、あらかじめフォルダを作っておいて、プロジェクト名にそこを指定する、と失敗はありません。



200710
関数、メソッド、一覧、移動、日本語
関数への移動方法で悩んでいました。
関数を呼び出している所からなら、F12で移動できることは最近分かりました。
元の呼び出し場所へ戻るのは、Ctrl+-です。

いつもHSPを引き合いに出しますが、HSPでは編集メニューに関数一覧があります。ここから実際の関数の場所に移動できます。

今日ようやく、同じような方法を見つけました。
ソリューションエクスプローラーのform1という項目の横の小さな右三角をクリックです。
ここに関数一覧+αがズラーッと出てきます。
似たような名前がいくつも出てきて迷いますが、よく見ると自分が作ったものもあります。
で、目的の関数名をクリックで、コードの場所へ移動します。
200818追記
これに気付くのに一か月と8日かかりました。
関数等への移動の方法です。エディタの右上に小さなボックスがあり、そこの小さな三角をクリックすると、上と同じような関数類のリストが出てきます。
関数と変数定義と他にも何やらあるようですが、とにかくジャンプテーブルになっています。
上の方法だと、リストを表示させるまでに幾つかクリックが必要ですが、こちらならワンクリックです。
それに、懸案だった、今どこにいるか、カーソルの位置も分かります。
ただ、先の方法だと、常時リストが見えているので、連続して移動する時には、まだ使えそうです。
もう一つ、右上のリストは、ソートされています。これでは多少使い辛いです。
この点、どこかに設定があるといいのですが、あったとしても探すのが大変です。
200818追記ここまで。

更に調べたら、C#でも関数名や変数に日本語が使えます。今日初めて気づきました。
変数は何度も使うので日本語は面倒ですけど、関数には使った方が便利です。
HSPでは、よく使う、というか、重要な関数や区切りの場所に日本語のラベルを使う様にしています。
すると、関数の一覧を出した時、探しやすくなります。
C#でもラベルが自由に使えるといいのですが。
いえ、使えるみたいです。
ただ、使いたいのは、例えば、ボタンのクリックの所です。

ファイル読込ボタン:
private void button1_Click(object sender, EventArgs e){}
このように、関数の宣言の前後に日本語のラベルが使えると、関数を探すのがとても楽になるはずです。
残念な事に、関数の内側ならラベルは使えますが、ラベルは一覧には出てきません。

それに、今いちなのが、これで現在の位置が分からない事です。
HSPのラベル一覧では、現在のカーソルの位置のラベルが反転して、自分が今どこにいるのかが分かります。
これは重宝します。


200709
VSのヘルプ

常々、Visual Studioのヘルプは貧弱だなと思っていました。
まあ、フリーの物にはよくあることだからと観念して、ネット検索に励んでいました。
今日、気付いた事が1件、プラス2件あります。

まず、ファイルなどのフルパスからファイル名だけを取り出す(メソッドというのか関数というのか)方法について、
System.IO.Path.GetFileName()は、ファイル名だけではなく、最下層のフォルダ名も取り出せる、という事です。
つまり、文字列の一番右にある\から先の部分を切り取ってくれます。とても便利です。

これを利用する状況は、フォルダの一覧を作る時です。この時の試行錯誤で、便利なヘルプの機能について気付きました。
まず、単語の上にカーソルを置いてF1でヘルプが出てきます。
これは、HSPにも同じF1でヘルプが出てきますので同じでした。
ただ、VSのヘルプは、読んでみても私にはよくわかりません。専門家向きなのでしょうかね。

フォルダの一覧を作るので、下の様に書いてみました。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", SearchOption.TopDirectoryOnly);
ところが、例の赤い波線がSearchOptionの所に出て消えません。
しかし、その赤い波線の所にマウスカーソルを持っていくと、ヘルプみたいなプルダウンが出ます。
考えられる修正内容を表示してくれるのです。
その内容の中にSystem.IO.とか、using System.IO、とかいう項目が出てきます。
ああ、これだと気づきます。で、クリックすると補完されます。
using System.IOの方がスマートなのでしょうか。何故か私はこれを使っていません。

で、こうなります。
string[] dirs = System.IO.Directory.GetDirectories(backdir,"*ks", System.IO.SearchOption.TopDirectoryOnly);
波線が消えます。実行すると意図通りに動いてくれます。

もう一回、System.IO.Path.GetFileName()について、
フルパスから一番右側のファイル名だけ取り出すものですが、とても便利です。
ファイルやフォルダのリストを取ると、全部フルパスで帰ってきます。
必要なのはファイル名だけです。この時に使います。
HSPでは、これが無いので、関数など作ったりしていました。
strrepとかsplitとかこれに近いものはあります。それでも面倒です。
一番ありがたいのは、文字数などのカウントが必要ないことです。
0から始まるのか、1からカウントするのか悩む必要がありません。



200708
true、false、if (!a)
未だにif文の書き方がおぼろげです。

まあ、間違っても、その場で赤い波線になるので、何とか処理出来ていますが。
よくやるのがこれ、if (a = fales)、です。
2か所も間違っています。
==とfalseのスペルです。

これに気が付かないので、どうしても赤い波線が消えません。
やむを得ず、例文などからそのまま、if (a)とかif (!a)とか書き直して凌いでいます。
もちろん、!を付けるのが正しいのか、付けないのか分かりませんので、試行錯誤します。
それぞれ実行して、どちらか予定通りの行動になる方を採用する、という段取りです。

これを回避する為に、a=bの形式にしたいのですが、一方がtrueかfalseの場合、先のスペルミスがあります。
何しろ、いくつもの選択肢があります。
まず、引用符""が必要なのか、大文字なのか小文字なのか頭文字だけ大文字なのか、等、無限に試行錯誤が続きます。

長年=一つで済ませてきましたので、==に気付かないのはやむを得なかったと思います。
false、trueは、最近、こう書けばいいと気づきました。
if (a == false)、です。
ネットでは、ほぼ全部、if (!a)、と書いてあります。
if (a == false)、と書いてもらうと分かり易いのに、なぜ省略するのでしょうかね。

今日、気付いた事が2点、
falseは、フェイルスではなく、フォールスと発音する事、
VSのエディタでは、正しくfalseとタイプすると、文字が青色に変わる、という事です。
これで、今後は大丈夫でしょう。多分。


200707
C#、テキストボックスへの表示にかかる時間

200705付けでメモした事で、全く同じ作業なのですが、2度目の方が作業時間がかかってしまう、という現象がありました。
かなり大きなテキストファイルの更新作業です。670KB程度、行数は30000行ほどのファイルです。
このファイルの適当な位置に、新しく10数行の文字列を挿入します。挿入位置は末尾や先頭ではありません。途中です。

フォームで画面を作ります。テキストボックスを数個、ボタンを数個です。
テキストボックスのmaxlengthは0にしています。
こうすると、表示サイズの制限がなくなるとの事です。

起動時に、目的のファイルを読み込んで、表示までしておきます。
ボタンにコードを埋め込んで、実際の作業、文字列の挿入です。
具体的には、以下の作業になります。
まず、念の為、ファイルはもう一回読み込み、表示します。
読み込んだテキストに、文字列を挿入して、再度表示、保存です。
念のため、上書きしないように、保存する時のファイル名は変えています。
ですので、何度でもボタンを押して、同じ作業が出来ます。

いつも作業時間を計っています。
HSPでは3秒かかる作業で、C#で代替えして、もう少し早く出来ないかという事が動機でした。
結果、320ミリ秒程度で終わります。

ただ、ここで問題があって、ボタンをもう一回押して、同じ事を再実行させると600ミリ秒かかってしまいます。
これは何だ、となって、時間の計測を細かく分割しました。
ファイル読込に何ミリ秒、表示に何ミリ秒、という感じです。

これで、簡単に原因が分かりました。
一回目の実行では、読み込みに要する時間は10ミリ秒程度でした。これが2回目以降は270ミリ秒程かかっています。

この結果は、こう考えるよりありません。
C#では、テキストボックスに再表示する際は、表示してある内容と同じテキストだったら、表示を省略する。
どうしているのでしょうかね。チェックサムみたいな物があるのでしょうか。
コードを読み切っているのでしょうか。このコードなら再表示の必要なし、という判断をしているとは思えませんが。
だとすると、向こうが偉いという事になります。
まさか、文字数とかファイル名だけで判定しているはずもないでしょうし。

更に、もう一つ、大事なことに気付きました。
C#で、ファイルが大きい時など、テキストボックスへの表示をさせなければ、圧倒的に速くなる。
今回のケースでは、表示を省略すると、50ミリ秒で終わることになります。
比較の為に挙げた、HSPでの3秒という時間には、表示時間が含まれていませんでした。
つまり、C#が圧倒的に速い、ということです。

さらに、ずーっと下のメモで、色々な比較をしています。
この時、表示に時間がかかるという事は考慮していたのか気になります。
やはり、正確な比較をするなら、C#は、C言語といい勝負をするのかもしれません。



200705
C#、文字列の分割と結合
テキストファイルの途中に文字列を挿入する作業に苦労しています。
文字列の末尾ではなく、途中に小さな文字列を追加しようとしているのですが、なかなかうまく行きません。
HSPだと、noteadd 追加するブロック,追加する行番号,0、という一行で済む作業ですけど。

C#で、文字列の途中に文字列を挿入する手段を探しましたが、簡単な方法が分かりません。
簡単ではないというような記事もあります。

分かったのは、
元の文字列を、行単位に分割する。
追加する位置を境にして、前後のブロックに分けた文字列を作る。
前のブロックの末尾に今回挿入するブロックを追加する。
その後ろに、先に分けておいた後半部分のブロックを追加する。
という手段です。これ以外にはなさそうです。

上の方法で試しますが、すんなりとは行きません。
分割する時、前半のブロックの末尾が改行だけの行になっていて、これを連結すると、その改行だけの行が消えてしまいます。
一行短く仕上がってしまいます。
やむを得ないので、連結する時、改行を一行追加して辻褄を合わせました。

この作業、現在、HSPでは3秒強かかります。
サイトマップファイルに新しいページを登録する作業です。
ファイルは30000行660KBあります。
一応、同じ種類のページはまとめておきたいものですから、末尾に追加とはいきません。
今のところ、出来上がったテキストを保存する作業を入れていませんが、C#だと、300ミリ秒ほどで終わります。
C#に変える効果がありそうです。

どうやら正解が分かりました。
途中で配列にしたものを文字列に戻して、その文字列同士を連結したのがまずい様です。

完成後の行数、文字列を挿入した作業後の行数は分かります。
最初に、その長さの配列を宣言しておきます。
元の文字列も挿入する文字列も配列に変換します。
完成後の長さ分確保していた配列に、前半部分の配列、挿入する部分の配列、後半部分の配列を、位置を指定してコピーします。
最後に配列を文字列に変換します。
これで、改行だけの行も残ります。

完成したとして、ファイルの読み込み、連結、ファイルの書き込み、までの時間は330ミリ秒ほどです。
HSPでは3秒かかっていました。

ただ、連続して実行すると、2度目には600ミリ秒かかります。原因不明です。
原因が分かりました。テキストボックスへの表示時間です。これについては、改めて、項を変えてメモします。




200702
tt.Replace("\\", "/");

とあるフォルダのファイルリストを取ると、次のような文字列が出てきます。
G:/main-data/code/VS2019/CSDATA/temp20\200625mg.htm
\を/に変えたいのですが、うまく行きません。
tt.Replace("\\", "/");
が言う事を聞きません。

200701
C#、降順のソート
listBoxを使ってみる事にしました。
フォルダにあるファイルの一覧を作って、リストボックスに表示させます。

まず、ListBoxではなく、listBoxですね。まずここでエラーと言いますか、例の赤い波線です。
どうやら規定では、昇順にソートされる様です。
私の希望では降順でソートして表示させたいのです。
基本的に、ファイル名に日付を付けていますので、一番新しいファイルを一番上に置きたいのです。

全くの付け焼刃です。例によって、ネットを探しました。
これが面倒でした。様々なソートの方法が有るようですが、どれも分かりません。
構文が長くて、意味不明です。2行に渡る物もあります。
C#のバージョンによっても違うのかも知れません。
やはり系統立てて勉強していない事へのしわ寄せでしょうね。
目的は、単純に文字列の配列を昇順に並び換えたいだけです。
HSPだと、簡単に、sortnote files,1、とするだけなのですが。

ようやく、見つけました。
Array.Reverse(files);、で目的達成でした。



200623
VSエディタの起動時間

VSのエディタの起動にかかる時間が気になってきました。
C#で、デスクトップにslnファイルのアイコンを作って、そのアイコンをダブルクリックしてVSのエディタを起動しています。
これが、開き終わるまでの時間です。

編集しているテキストは、Form1.csだけです。これが30KBで、あと、Program.csというファイルがあります。1KBです。
csファイルはこれだけです。
そこで、時計を横目で見ての計測ですので、正確さはありませんが、ダイアログで、準備が完了しました、と出るまでに8秒ほど、
そのダイアログで、バックグラウンドで云々とあって、ダイアログが消えるまでに更に8秒ほどかかります。

エディタに慣れてくると、この辺りも気になってきます。


200620
C#、byte[]

昨日発見したbyte型ですが、ある程度の文字列を扱うので、大きめに確保しておきました。
byte[] aa = new byte[1000000];
そして、文字のアスキーコードを順番に入れていき、終わった所で終端の0を入れます。
その後で、Shift_JISの文字列に変換します。
string tt = System.Text.Encoding.GetEncoding(932).GetString(aa);

当方の目論見通りです。ちゃんと表示され、保存も出来ます。
ですが、よくよく調べてみると、ファイルの大きさが、最初に確保した1000000バイトのままです。
それこそVSCodeで強引にhexダンプしてみると、文章が終わった所から以降には全部、0が並んでいます。
Shift_JISでは考えられない世界です。これがUnicodeなのでしょうか。私の無知なのでしょうか。

やむを得ず、完成後のバイト数をしっかり計算して、必要十分な領域を確保して、回避しました。
それにしても、byte型に関しては、もう少し勉強が必要かもしれません。
一番の原因は付け焼刃でやっている事なのですけど。


200619
C#、char、byte、Shift_JIS
C#のcharは16ビットです。8ビットはbyteという型があります。
これは許せません。これに気付くまでに3日かかりました。

普通は一文字ずつメモリというか配列に収めるならcharでしょう。
そのつもりでやっていったら、どうしても型変換のところで止まります。
char m[0] = 65;
char m[1] = 66;
char m[2] = 0;

これをstrngに変換しようとしても出来ません。
強引に変換しても、結果は文字化けしています。
VSのエディタの警告やブレークポイントでのデータを見ると、UTF-8になるよ、みたいな表示です。
理解はできません。

正解は、
byte m[0] = 65;
byte m[1] = 66;
byte m[2] = 0;
です。
これで期待通りのShift_JISの文字列”AB”を作れます。
(何故か、末尾の0?='\0'は必要なし。)

このところ、文字列の連結で試行錯誤です。
言語も、C、C#、HSPを右往左往しています。
C#の速度がどうにも遅いので、調べたら、StringBuilderクラス、というものがありました。
これを使うと、Cに近い速度が出ます。
よく見たら、Cではcharの配列を使っていました。
文字列を連結するのではなく、インデックスを指定して直接書き込んでいます。
そこで、HSPに戻って、pokeを使って書き込みするようにしたら、こちらもC#並みとはいきませんが、かなりな速度になりました。
そこで、戻ってC#です。
C#でも配列に書き込んだら、訳の分からないStringBuilderクラスなど使わなくてもいいのではないかと考えました。
そこで、当然、私の知識ではchar[]を使えばいい、はずです。
この間、3日悩みました。
正しくは、byte[]でした。

文例などに、byte型とかあるので、何だろうかとは思っていました。




200619
C#、型

C#の変数の型について、大して違わないだろうと、これまで何も調べずに使っていました。
と言いますか、どこに書いてあるか分かりませんでした。
最近、型変換がうまく行かないので、探していて、ようやく、分かり易いページを見つけました。

思っていたものと違いますね。
charは16ビットです。Unicodeのせいでしょうかね。
byteという型があって、これが8ビットです。1バイトですね。
intは32ビット、とあります。

Cでは、
charが8ビット
intが通常32ビット、
shortが16ビットとあります。ただ、Cはコンパイラ次第のようです。

念のため、VSのCではどうなのか、調べたのですが、見つけられません。
いえ、検索すると、intが4バイトというページがあります。32ビットですね。
ただ、残念なことに、これがどの言語の規定なのかが分かりません。
考えると、OSの32ビットと64ビット違いによる関連はないのでしょうかね。少し心配です。

HSPでは、
変数の宣言がありませんので調べるのに苦労します。
intは型変換です。小数点を切り捨てるのに使います。多分。
基本が整数なので、普通に割り算すると整数が帰ります。多分。
10進数の範囲は32ビットと書いてあります。これが制限なのでしょう。


200617
VS、上書き保存
Cの編集中、VSのエディタで上書き保存のアイコンをクリックするとダイアログが開いて、出力-デバッグ.txtというファイルを保存しようとする。
どうやら、コンソール出力の内容を保存するみたい、リダイレクトだったか、既定かな。便利と言えば便利。
コンソールを閉じていても出てくる時がある。
何か知らない構造があるのだろう。
200617
C、open
ファイル読込の際、rでもrbでも同じ結果になる。読込方次第か。
fp = fopen(fpath, "r");
200617
C#、byte[] bytes
byte[] bytes = SiftJISenc.GetBytes()について調べてみました。

76C2CC・・というテキストを読み込ませ、
変数に代入し、直下にブレークポイントを置くと、実際の数値をみられます。

データは以下の通りです。
bytes[0]=55= "7"
bytes[1]=54= "6"
bytes[2]=67= "C"
bytes[3]=50= "2"

つまり、アスキーコードが入るという事です。

ついでに、文字に戻すには、
char mo = (char)bytes[0];
char mo2 = (char)bytes[2];
UTF-16で戻ってしまう。困った。(これは間違い、勉強不足の頃の話)

200617
C#、ブレークポイント

Cではどこにでもブレークポイントが置けます。
C#ではコードのある行でないと置けません。
これが分からずに、再起動を繰り返しました。

200616
スクリプト、コード

エディタで作るプログラムのソースファイルの中身をなんというか、迷っていました。
今後は、HSPはスクリプト、その他の言語はコードと表現する事で統一します。
HSPのエディタは、HSPスクリプトエディタとなっています。
VSの方はMicrosoftVisualStudioCommunity2019となっていて、ここでは判断できませんが、ヘルプの中にはコードと書いてあります。

200615
C、strcat
strcat(aa,bb);
この前に、aa[0]='0';が無いとエラーになる。

200615
VSCode、HEX表示

VCCodeに16進表示の拡張機能をインストールしました。
下のプログラムの確認の為に使います。
この操作方法に毎回迷います。どうしたら16進表示になるのかです。

あちこちメニューをめぐって何とかなるのですが、今回間違いのない方法を見つけました。多分。
ファイルを読み込んで、ファイル名が表示されている所を右クリック、
そのプルダウンメニューの最下部にShow Hexdumpと出ています。

Shift_JISファイルが、いつも、文字化けしています。UTF-8で読み込まれています。
下のエンコーディングの所から、読み直すことが出来ますが面倒です。
ウーザー設定に初期設定がありました。

200611
C#、StringBuilderクラス、言語別実行速度比較、poke
C#で満足できるだけの速度を出せました。
ネットは、早い、という記事を見ます。ここまで信じられない話でした。
恥ずかしながら、ここまでのバタバタをまとめておきます。

作業は、テキストファイルの16進表示です。100KBのテキストファイルを変換してみました。
(実際には、その他、多少の副次的な作業もするのですが、中心の作業は16進変換です。)

という事で、forにしろrepeatにしろ、100000回のループが必要です。
最初にHSPで作ったものは、100KBのファイルを処理するのに11分かかりました。
いつものやり方で、冗長なスクリプトで作るとこうなります。
これは、スクリプトを見直して、39秒までには縮めました、(下の一覧表の*列の記号で、A、以下同じ)
しかし、この速度では役には立ちません。

そこで、コンパイラで、となります。
VisualStudioCommunity2019をインストールしました。
ついでに、VSCodeも落としました。
(後で気づいたのですが、このVSや、VSCodeには、16進表示の機能が付いていました。)

色々の言語を試しましたが、総合的な問題でC#に行き着きます。
当初、C#では期待通りの速度は出ませんでした。HSPより多少いいか、という程度でした。
そこで、調べていたら、文字列の連結には、StringBuilderクラスというものがあって、これが早いそうです。
以下、このStringBuilderクラスに到着するまでの経過です。

最初に、VBで試しました。
しかしながら、付け焼き刃の知識では何ともなりません。
VSの文字コードは、基本Unicodeだそうです。
ここまで扱ってきた文字コードはShift_JISだけでした。
Shift_JISのファイルを読み込んで、Unicodeで処理されるので、多分、変換してShift_JISのコードを出力する、となると思いますが、この変換がうまく行きません。
(この時点では、こんな風に考えていましたが、C#で何とか出来た現在、C#もVBもほとんど変わらないみたいですので、今なら何とかなるのかも知れません。Shift_JISで読み込んで、そのまま処理して、出力もShift_JISを指定して出力する。でしょう。)

対象のテキストファイルを、最初からメモ帳などでUnicodeに変換して処理するといいじゃないか、となります。
長年の事で、これが許せません。BOMとか4バイト一文字とかに抵抗があるのです。
やはり、文字は1バイトで処理できないといけません。(根拠なし。面倒だというだけです。)

そこで、先のVSでCに挑戦しました。
C言語については、昔、ほんの少しですが経験がありましたので。
便利な世の中です。ネットを探すと、例文が沢山出てきます。
それを継ぎはぎすると何とかなるものです。以下同じ。
それに、VBで悩んだUnicodeが出てきません。Shift_JISをShift_JISのまま読込め、そのまま処理出来ました。
VCでは、コードのファイルもShift_JISで保存されています。

Cで試すと、100KBの作業でも78ミリ秒で終わります(B)。
ただ、残念な事に、コンソールモードです。
Cではデスクトップの画面が作れません。どんなに探しても、フォームエディタを見つけられませんでした。

これには、便法ですが略式の解決方法があります。
画面処理はHSPで済ませて、実際の作業は、execでCの実行ファイルを起動します。H
この方法でやると、100KBの処理を700ミリ秒で終わります。(C)
待たされたと感じない時間です。
これで、実用上は問題ないのですが、ちょっと見苦しい気がします。

そこで、C++です。
確かに、ネットの情報を駆使してVSのメニューを掘り下げると、フォームエディタは出てきます。
ただ、ビルドしてもコンソール画面しか出てきません。
コードの書き方も全く分かりません。文法がCとはかけ離れています。
ネットにはCと大して変わらないとありますが、とてもそのようには思えません。

やむを得ず、C#を試しました。
C#だとフォームエディタは簡単に出現し、編集もできました。ボタンやテキストボックスなど簡単に取り付けられます。
マウスのドラッグでボタンなどの配置場所を指定できます。
HSPだと配置場所はスクリプトに座標の数字を書き込んで行きますので、C#の方が簡単です。
コードの配置場所もすぐ見つかりました。
private void button1_Click(object sender, EventArgs e)
の下に書けばいいのです。
ここに、ネットからの例文をコピーして多少変数をいじるだけで動きます。

で、試した結果、100KBの処理に16秒かかりました。ミリ秒ではありません。(D)(E)
こんなものかと思いました。コンパイラではありません。C#は中間言語なのです。
HSPよりはいいけど、秒の単位が必要なら、使うのに躊躇します。
そこで、順番としてはC++に向かったのですが、上のメモの通りです。
この間、他の言語も調べました。
GoとかFreeBASICとかです。
いずれも、デスクトップ画面を作れるかがよく分かりませんでした。

やむを得ず、C#に戻りました。
ここでようやく、StringBuilderクラスを知りました。
これを使うと、驚きです、同じ処理が151ミリ秒で終わります。(F)(G)
C並みとは言えないにしろ、これに近い、抵抗のない数字です。
それに、C#だけで画面から処理まで完結できます。

これで、ネットでの評価に近い数字になりました。
C++の迷路をさまよう必要はなく、HSPからCの実行ファイルを呼び出す必要もありません。
手探り状態ですけど、C#で何とかなりそうです。

一段落した所で、各言語のコードやスクリプトを比較していたら、幾つか気付いたことがあります。

HSPでは、文字列の足し算(連結)をしていました。
ここまでの経過で、文字列の連結には時間がかかる事を知りました。
HSPにも文字列を直接操作する手段があります。pokeです。
元々、変換元からの取り出しにはpeekを使っていました。
それでも、pokeを使わなかったのは、peekはメモリからの読み出しで、pokeはメモリへの書き込みです。
これに、多少の躊躇がありました。
それに、多少は早くなったとしても、そんなには違わないだろうと思っていました。
しかし、C#での事で、試してみる価値がありそうな気がしてきました。

HSPのスクリプトをpokeで作り直してみました。
爆速です。
39秒かけていた100KBのテキストの変換が0.516秒で終わりました。ミリ秒の単位で終わります。(H)
こうなると、HSPでの作業に抵抗はありません。
C、C#での騒ぎが何だったのかという事にもなります。

Cでは最初からポインタと配列で作業しています。つまり、メモリへ直接書き込んでいました。(B)
偶然、参考にした文例がよかったのでしょう。
あ、恥ずかしながら、配列とポインタが同じものだ、ぐらいは知っていました。

Cにも文字列の連結があります。一応。これも試しました。
連結だと、Cでも遅くなります。100KBの変換で2.8秒かかりました。(I)(J)


処理にかかる時間に関して一覧表を作りました。
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) Cを1とした倍率   処理時間(秒) Cを1とした倍率
A HSP 1.703 106.4   39.860 511.0
B C(コンソール) 0.016 1.0   0.078 1.0
C HSP+C 0.653 40.8   0.703 9.0
D C#(debug) 0.393 24.6   15.683 201.1
E C#(releace) 0.319 19.9   8.092 103.7
F C#(sb:debug) 0.133 8.3   0.155 2.0
G C#(sb:releace) 0.135 8.4   0.151 1.9
H HSP(poke) 0.329 20.6   0.516 6.6
I C(strcat) 0.265 16.6   5.563 71.3
J C(sprintf) 0.140 8.8   2.813 36.1


以下は作業中のメモです。
System.Diagnostics.Stopwatch()を使って、時間を表示させました。
(HSPでは、GetTickCount、C#では、GetTickCount())

C#の作業時間、(F)
20KBで、(0, 2, 0, 123, 8, 合計133ミリ秒)
100KBで、(1, 12, 0, 132, 10, 合計155ミリ秒)
という結果です。いずれもデバッグモードです、驚きました。

releaceモードだと、(G)
20KBで、(0, 2, 0, 133、合計135ミリ秒)
100KBで、(1, 10, 0, 140、合計151ミリ秒)

合計以外のコンマ付きの数字は、各セクション毎の所要時間です。
テキストファイル読込、16進数変換、16進数整形、mesboxへの表示、16進数ファイルの保存、の順番で表示しています。
コンマ付き数字が4個の結果は、mesboxへの表示と16進数ファイルの保存の合計です。

こうしてみると、時間のかかっているのは、変換結果のボックス表示の時間です。
他の作業には時間がかかっていません。
コードの間違いか、何やら、タイムラグみたいなものがあるのかも知れません。
あるいは、並行処理みたいなもので、実際の処理は他所でやっているとか。
あるいは、グラボの性能が悪いだけ、かも知れません。


簡単にそれぞれのスクリプトとコードを書き出しました。
肝心の所だけです。本来は、多少の修飾があります。

HSP、単に文字列の結合、(A)
repeat len
  one=peek(sjistext,cnt)
  hextext=hextext+strf("%02x",one)
loop
実行結果は、20KBで、1.703秒、100KBで、39.860秒


C、コンソールモード、配列に直接書き込み、(B)
for (i = 0; i < size; i++) {
  one = buf0[i]
  mae = one / 16;
  sprintf(mozi, "%X", mae);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
  usiro = one % 16;
  sprintf(mozi, "%X", usiro);
  buf[ctr] = *mozi;
  ctr = ctr + 1;
}
buf[ctr] = '\0';
結果、20KBで、16ミリ秒、100KBで、78ミリ秒、(デバッグモードのデバッグなし開始)


C#、単に文字列の追加、(D)、(E)
for (int ctr=0;ctr<len;ctr++)
{
  hextext += bytes[ctr].ToString("X2");
}


C# StringBuilderクラスを使って文字列を追加、(F)(G)
System.Text.StringBuilder hextext = new System.Text.StringBuilder();
for (int ctr = 0; ctr < len; ctr++)
{
  hextext.Append(bytes[ctr].ToString("X2"));
}
string hextext0 = hextext.ToString();
結果は、20KBで、135ミリ秒、100KBで、151ミリ秒



HSP、pokeで書き込み、(H)
repeat len
  one=peek(jistext,cnt)
  mae=one/16
  asc=strf("%X",mae)
  poke hextext,ctr,asc
  ctr=ctr+1
  usiro=one\16
  asc=strf("%X",usiro)
  poke hextext,ctr,asc
  ctr=ctr+1
loop
poke hextext,ctr,0
実行結果は、20KBで、329ミリ秒、100KBで、516ミリ秒


C、コンソールモード、連結方式でも試してみました。(I)
strcatで連結していきます。
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  sprintf(mozi, "%X", mae);
  strcat(buf, mozi);
  ctr++;
  usiro = hitomozi % 16;
  sprintf(mozi, "%X", usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果(H)、20KBが、265ミリ秒、100KBで 5563ミリ秒。(デバッグモードのデバッグなし開始)


C、更に、sprintfを連結して二文字ずつ作業すると、(J)
for (i = 0; i < size; i++) {
  mae = buf0[i] / 16;
  ctr++;
  usiro = buf0[i] % 16;
  sprintf(mozi, "%X%X", mae, usiro);
  strcat(buf, mozi);
  ctr++;
}
buf[ctr] = '\0';
結果、20KBで、140ミリ秒、100KBで 2813ミリ秒(デバッグモードのデバッグなし開始)





200609
C++のプロジェクト、フォーム

上に新しいメモあり、

C#の速度が、HSPに比べたら早いけど、驚くほどの速さではない、Cに比べたらかなり遅い、という状況でした。
そこで、C++でフォームアプリに挑戦です。
何しろ、プロジェクトの作り方から分かりません。フォームのデザイナが出てこないのです。
ネット参照でようやくたどり着きましたのでメモしておきます。

新しいプロジェクトの作成
上の窓で、C++、Windows、コンソール、を選んでおく。
CLR空のプロジェクト(.NET Framework)を選ぶとビルドが通らない。。
CLRコンソールアプリ(.NET Framework)を選ぶとビルドできる。
次へ
プロジェクト名とフォルダを適当に指定する。
作成
エディタのプロジェクトメニューで、新しい項目の追加、
UI、Windowsフォーム、を選んで、(UIがないのは今までの選択が間違っている)
追加
データが失われる可能性云々のエラーが出る。この場合は、
ファイルメニューで、ソリューションを一旦閉じる
ソリューションの一覧が出るので、今作ったソリューションを開く

何とか、フォームを使う所まで到着して、ボタンをダブルクリックでコードを書き込む場所までは分かりました。
しかし、分かりません。構文が他の言語とはあまりに違いすぎます。
ここで中断(というより放棄)して、DLLを勉強してみます。

そのボタンのコードですが、
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
というものがダブルクリックで生成されます。
ダブルクリック以外に冷静な方法がありそうなものですが、分かりません。

どこか間違っている様です。ビルドしてもフォームが出てきません。main()が?

C#では、同じ部分がこうなっています。
private void button1_Click(object sender, EventArgs e)
この程度だと、我慢して見られます。

どうにもこうにもC++が分かりません。
そこで、C#に戻って、調べました。
文字列の連結に使うStringBuilderクラスというものに気付きました。
これを使うと、C並みとはいきませんが、Cと同じ桁で実行できます。
C#に戻ります。

200609
C#、実行速度
この項、上に、新しいメモあり。

ネットではC#の実行速度は、コンパイラ並ではないにしろ、コンパイラと遜色ないような記事が多いです。
それならと、目下勉強中です。
ある程度、作り上げて、実際に試してみました。結果、HSPよりも少し早い程度です。
いえ、まだ途中経過で、改良の余地がある状況ですし、完全に同じ作業にはなっていないはずです。
とりあえずの結果です。

何しろ、ほとんど文法が分かっていないのに、ネットの文例をつなぎ合わせていくと、動いてしまいます。
そういう作りですので、まだまだ不十分だと思います。

その上で、
20KBのテキストファイルの処理がHSPでは1.7秒でした。

これをC#では、約400ミリ秒、です。
C#の計測結果、debugモードで、(10, 248, 248, 393ミリ秒)、12, 261, 0, 142(合計415ミリ秒)
releaceモードでビルドした実行ファイルで、(11, 183, 183, 319ミリ秒)

やはり、C#でもテキストボックス等へ大量のテキストを表示させると、時間がかかっています。
これはHSPでも同様で、どちらも表示は部分的に省略するようにしています。
どちらも、条件は変わらないと思います。

100KBのテキストで、HSPで40秒でした。
C#の計測結果は、debugモードで:(32, 15541, 15542, 15683ミリ秒)、36, 16006, 0, 155(合計16197ミリ秒)
同、releaceモードでビルドした実行ファイルで:(12, 7953, 7954, 8092ミリ秒)
C#では、8秒という事になります。

ここで、初めてreleace版で生成した実行ファイルで試してみました。
かなり早くなっています。こちらが本当の速さという事でしょう。
Cでも双方試しましたが、差は分かりませんでした。Cでは差が出るほどの作業ではなかったという事かも知れません。

やはり、テキスト表示は部分的に省略しています。
なお、C#で、テキストを省略せずに表示させると、29秒かかります。つまり、ボックスへの表示に13秒かかっています。
上二つ、Cも計測してあります。

まとめると、(前半の作業時間)
言語 20KBのテキストでの作業   100KBのテキストでの作業
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP 1.703 1.0   39.860 1.0
C#(debug) 0.393 1/4.3   15.683 1/2.5
C#(releace) 0.319 1/5.3   8.092 1/4.9
Cのみ 0.016 1/106   0.078 1/511

HSPと比べればかなり成績が上がりましたが、8秒では心理的にも抵抗があります。
もう少し対策を考えます。

ネットで調べていたら、StringBuilderクラスというものがあって、文字列の連結に強い、そうです。
試しました。
20KBで140ミリ秒、(0, 3, 0, 137、合計140ミリ秒)
100KBで175ミリ秒、(12, 14, 0, 149、合計175ミリ秒)
という結果です。いずれもデバッグモードです、驚きです。
これで、ネットでの評価に近い数字になりました。C++のジャングルをさまよう必要はなく、C#に戻れそうです。


ループについて
この間の作業で、C#でも単純で数の多いループの最中に、帰ってこない状態になることがありました。
フォームの右肩のXのボタンが赤く表示されます。マウスカーソルが行っている状態です。
数秒ですので、何も試していませんが、ちょっとした暴走状態だと思います。
終了だけは出来ます、という意味かも知れません。
HSPではwaitを入れない単純なループでよく経験します。



漢字モード
VSのエディタで漢字がONにならない場合があります。
ビルドしてエラーも結構出ていますので、何やら暴走させているのかもしれません。
エラーが出ている間、デバッグ実行中にはONに出来ないようです。
コードを書き換えられない様にしてあるのかもしれません。



200607
VS、灰色の点々

自己書き換え、とでもいうのかな
VSのエディタに灰色の点々があります。よくできていると思います。
マウスを近づけるとメッセージが出てきます。
int宣言の所で、不必要な代入、とありました。
エラーにはならないけど無駄だという程度なのでしょう。

str.Replace("A", "B")

文字列の一部を入れ換えるのに
str.Replace("A", "B")
というものがあります。
これをそのまま信用して、
str.Replace("A", "B");
と書きます。
いくら待っても書き換わりません。

HSPに同様のコマンド、strrepがあります。
strrep strr,"A","B"、とすると、strrが書き換わります。

C#では、
strr=str.Replace("A", "B");
が正解の様です。

文字コード指定、文字コードの確認
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

私が扱うテキストファイルの形式は全部Shift_JISなので、苦労しています。
VSではUnicodeが標準みたいですので。
上の構文でファイルのエンコードを指定できるみたいです。
最初に指定しておくと、いい様です。
と言いますのも、ファイル読込の時に指定して、再度書き込みの時に指定するとエラーになります。
例の赤線、インテリセンスが出て、既に定義されているとなります。
コンパイルは通るのかもしれませんが。

さて、問題は実際にShift_JISで保存されているのかが心配です。
構文の意味がよくわからずに使っていますので。
最近は、いい時代になりました。
ネットで探せば、大抵の例文が出ています。
例え初めてのC#でも、面倒な作業でなければ、なんとかなっています。
ですが、上のような心配もします。

そこで、解決策に気付きました。
半角だけのテキストの場合に、文字のエンコードを確認する方法です。
メモ帳ではUTF-8と表示されます。TeraPadでは、Shift_JISと表示されています。
プロパティなどで、バイト数を見ます。
同じもので、エンコードがはっきりしているファイルが必要です。
私の場合は、同じものを、HSPで作っていますので、Shift_JISとはっきりしているものがあります。
それと同じバイト数ならShift_JIS、少し大きいならUTF-8となります。

上のメモは、BOM無しUTF-8だとダメみたいです。
しかし、VSで出力されているものはBOM有りでした。

検索と置換、インテリセンス
System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis");
System.IO.File.WriteAllText(filePath, htext, enc);

上のコードのencをShiftJISencに置換したいと考えました。
ネットを見ていたら、同じような文例を見つけ、こちらの方が分かり易いなと思った次第です。
それに、多分、この単語は適当に変えていい部分だと気が付きました。

で、エディタの編集メニューにある検索と置換から実行しようとしました。
すると、encの部分は良いのですが、どうやら.Encoding.GetEncodingにあるEncの部分も置換対象に含まれている様子です。

そこで、いちいちスキップする方法はありますが、手間は変わりません、手書きで変更していくことにしました。
手書きと言っても最初にShiftJISencをコピーしておいて、対象のencを探してペーストしていきます。

ここで、ありがたい機能に気付きました。
よく出てくるインテリセンスの赤い点線です。これがとても役に立ちます。
最初に、定義の?最初の行の、encを書き換えると、残りのencが全部赤い点線になっています。
先ほど度違って、今度は変更が必要な部分だけです。
これを順番にペーストしていくだけでした。



200605
C#、ツールボックス
フォームを作るのに、C#が簡単という記事を見て、ちょっと始めてみました。
VSにC#も全部入っています。多分。
見よう見まねで作っていきます。
ネットからの切り貼りで何とかなるというのが、便利というか恐ろしいというか。

確かにフォームデザインが簡単にできます。できました。
それでもやはり試行錯誤です。
失敗した時、意図通り出来上がらない時、フォルダーごと削処して、プロジェクトの作成からやり直しです。
いえ、どこが間違っているのか分かりませんし、修正なんかできるはずもありませんので。

何回かやり直しているうち、ツールボックスからボタンbuttonという項目がなくなりました。
新しいプロジェクトを作る際、.NETCoreと.NETFrameworkを行き来している時でした。
フォームにボタンが貼り付けられません。
困って、色々メニューを探したら、それらしきものがありました。ツールボックスのリセット、という項目です。
ツールボックスの上での右クリックメニューです。
これで復活しました。

長い文章を表示するボックスをつくるのに、TextBoxだと一行しか表示できそうにありません。
試してみると、よさそうな物に、RichTextBoxがありました。
これだと、簡単に、縦長のボックスが作れます。
しかし、よくよく調べると、TextBoxでもよかった様です。オプションでMultilineをセットすると縦に拡張できました。
今のところ、どちらが正解なのかは分かりません。

TextBoxにも最大文字数があるようです。32KBみたいです。
ただ、こちらはMaxLength=0とする事で簡単に変更できるとの事です。

さて、迷いごとを一つ、
System.IO.File.Exists();、
という構文と、

using System.IO;
.IO.File.Exists();
という、どうやら二つが分離されている構文があります。

どうやらusingがdefineみたいなものの様で、以下省略できるという意味の様です。
迷いますね、統一してもらいたい所です。


200529
文字列の比較

Cで文字列の比較で躓きました。
if (argv[1] == "ag")です。全く意図通り動いてくれません。

試しに、
printf("1番目の引数は:%s %d\n",argv[1],strlen(argv[1]));とすると、
ちゃんと
1番目の引数は:ag 2、とでます

正解は、Cでは文字列の比較は、==、では意味がなく、
if (strcmp(argv[1], "ag") == 0)
だそうです。

思い起こせば、HSPでも同じような事情があります。ただHSPでは=までは通じます。
大小の比較はできません。



200528
CTRL+A

各種編集作業の時便利なキーがあります。
Ctrl+C、Ctrl+V、Ctrl+X、Ctrl+A、です。
コピー関係のショートカットです。
特にCtrl+Aは重宝しています。全て選択、ですね。

私は、HSPの作業中に途中の経過をクリップボードに転送しておきます。
メモ帳などに貼り付けるのです。
作業後にそれを見て、意図通り動いているか調べます。

この時、前回の経過が貼り付けてあるメモ帳の表示を入れ換えるのに、Ctrl+A、Ctrl+Vで済みます。
ただ、最近、これらのショートカットを多用していると、効かなくなることがあります。
コピーもペーストも出来なくなります。

原因不明です。特に、HSPのエディタ上で顕著です。HSPを再起動すると回復します。
最近、Cを始めたので、何か悪影響が出ているのかもしれません。
そのものずばりで、clipsetを多用している事が原因かもしれません。


200524
VSのエディタ、赤い波線、インテリセンス
VSのエディタでCの作業中、全く関係ないファイルから数行のテキストををコピーして持って来ました。
すると、赤い波線が出て来ました。理由はよくわかりませんが、エラーの様です。
赤い波線は、例えば、行末にセミコロン;、を付け忘れた時に出てきます。心穏やかではありません。
どうやら、この波線をインテリセンス、というみたいです。やはりエラーです。

しかしながら、コピーしたものは日本語のテキストで、貼り付け(ぺースト)した場所は、/**/で囲んだ注釈行の中なのです。
構文の間違いではありません。
200526追記
この件、プログラムをVer16.6.0へアップデートする事で解決しました。した様に見えます。
以下、無意味なドタバタの記録です。200609再発しました。
まず、VSで悩まされている、日本語コードを疑いました。
調べてみると、ファイルの日本語コードは、コピー元もコピー先もShift_JISです。
コピー先の、VSのC言語のソースも、何故かShift_JISなのです。
VSのエディタで、どのように扱っているかは調べようがありませんが、保存してあるソースファイルはShift_JISです。

試しに、保存してあるソースファイルをメモ帳で開いて、同じ内容を貼り付けて、VSを立ち上げてみました。
結果、同様に赤い波線が出てきます。

特殊な漢字を使っていて、それに反応しているのかもと調べてみました。
昔、機種依存文字とか、コントロールコードとかの絡みで、こういう事がありました。
一行ずつ、一文字ずつ削除して調べました。それでもはっきりしません。
消える場合もあります。消えない場合もあるのです。どの漢字か特定できません。
しかも、全部削除しても波線が残る時もあります。

ただ、コンパイル、ビルドは通ります。
この用語がよく分かりません。
昔は、実行ファイルを作る作業をコンパイルとかリンク、メイクmakeとか読んでいたと思いますが、VSには、今の所、どちらも出てきません。
後日、調べて、実行ファイルを作るのはビルドだそうです。いつもビルドした後デバッグしていたので、デバッグで実行ファイルが作られるのかと勘違いしていました。
更に、releaseモードでビルドしたものが正式の実行ファイルの様です。
debugモードでもビルとすると実行ファイルができます。
同じものかと思っていましたが、ファイルを比較しててみたら。サイズが違います。
releaseモードの方が小さくなっています。
どこにも書いてありませんが(どこにも見つけられませんが)、多分、デバッグモードの方は、デバッグの為のコードが含まれているのでしょうね。暴走しない様に。
実行速度にも違いがあります。releaceの方が早いです。

そのビルドやデバッグですが、波線があってもできます。実行できています。
これはやはり、波線の方が間違いだろうと考えるようにもなりました。

ある時、偶然気付きました。
窓で作業している時に発生します。
全画面で作業している時はこの現象は出てきません。
ただ、窓で発生している状態で、全画面にしても消えません。
逆に、全画面でコピーして、窓に変えた場合は、発生する場合も発生しない場合もあります。
困ったものです。
貼り付けたものを、元に戻すコマンドで戻しても消えない事が多いです。しかし、そのまま全画面にして、赤線の出た状態で終了して、再度起動すると消えていたりします。
色々試すと、もう滅茶苦茶です。

プロジェクトをもう一つ作ってあって、そちらではこの現象は発生しません。
そこで、考えました。
最初からやり直す事にしました。
下のメモにある方法で、既存のCファイルからプロジェクトを作り直してみました。
何しろ、ソースファイル一つのプロジェクトです。
そのファイルを一つだけコピーして作り直すだけです。
これで見事解消しました。

思うに、原因は、
この作業中にソースファイルを入れ換えたことです。
なんの為だったかおぼろげですが、どこかのコメント行を追加したか、コードの一部を他所から持って来たかで、ソースファイルを同じ名前で入れ換えたことがあります。
多分、このせいだと思います。
試してみると簡単に分かることですが、面倒なのでやりません。
VSのプロジェクトは、多数のファイルが出来ています。
その中に、何かエディタ上の変更に付随して書き換わるファイルがあるのではないだろうか、という事です。
VS以外のエディタで、途中で編集をすると、何か辻褄の合わない事が起きるのではないのか、というのが、現在の推定です。

200526追記
再発しました。また赤い波線です。
思い当たる直前の作業は、
まず、ちょっと暴走気味で、メニューの変な所をクリックして、帰ってきませんでした。
どうするかのダイアログが出て、終了を選びました。
メモ帳からの文章をコピーで持って来ました。
#define文で、一行に//を2か所使いました。
この辺りで波線に気付きました。
やはり、窓での作業中でした。全画面にすると、消える時も消えない時もあります。
今回は、二つのプロジェクトで同時に発生しました。

行き詰って、最後に、プログラムのバージョンアップが無いか調べたら、新しいものがありました。
更新しました。
今の所、発生していません。波線は出ていません。まだアップして一日目ですが、平穏です。

200609
再発しました。
コメントの、/*、*/、の部分が赤い波線になっています。
今回は、変な作業はしていません。いえ、他のテキストからコピペぐらいはしたかもしれません。
200610
また、更新がありましたので、実行しました。Ver16.6.2になっています。
再起動したら、消えています。
200616
しばらく出ていませんでしたが、今日出ました。赤い波線です。
何故か、ほぼ全体的に発生しました。
終了、起動を何度か繰り返すと消えました。
発生は、エラーと言いますか、例外が発生した直後に出るようです。
一旦VSを終了し、再開すると大体は消えます。
更新は関係ないかも。更新したら、再起動しますからね。
こんなものなのかも知れません。



200522
既存のCのファイルからVSのプロジェクトを作る

既存のC言語のコードからVisualStudioのプロジェクトを作る段取り。
これまで、何度か試していて、ここまで、うまく行ったり行かなかったりでした。
今日、改めて試して、すんなり成功しましたので、メモしておきます。

別のプロジェクトで使ったフォルダ全体をコピーして、フォルダとソースファイル名だけ変えて、新しいプロジェクトを立ち上げても、うまく行きませんでした。対策を知らないだけかもしれませんが。
ソースファイルだけを、名前を変えて新しいフォルダにコピーして、この方法でプロジェクトを作るとうまく行きます。
(単独のソースの場合です。)

まず、
VSの起動画面の、プロジェクトの選択画面で、コード無しで実行、を選択します。

何も無い状態でVSが開くので、
メニューの、ファイル、新規作成、既存のコードからプロジェクトを作成、を選択していきます。

作成ウイザードが開くので、
作成するプロジェクトの種類はVisualC++、を選択し、次へのボタン、

プロジェクトのファイルの場所は、あらかじめ準備していたフォルダを、
プロジェクト名は、準備してある既存のCのコードのファイル名を入れます。
ここ、あらかじめ、既存のファイル名、フォルダ名、プロジェクト名の3つを同じ名前に合わせています。ただ、これが必須かどうかは不明です。
この窓には、都合3個のチェックボックスがあります。
一つは、次のフィルダー云々「フィルダー」となっています。
既定で全部チェックされていますので、そのままです。意味は分かりません。
次へのボタン、です。

つぎの画面で、プロジェクトの種類に、コンソールアプリケーションプロジェクト、を選択します。
ここの選択肢で、Windowsアプリケーションが既定の様ですが、多分、これを選ぶとまずいのだと思います。
後、次へのボタンで数画面ありますが、意味不明で、いずれも既定のままです。
ですので、完了ボタンで終わっています。

この設定で始めると、先のSDL関連はチェックされていません。
ですので、最初から、ビルドエラーは出ません。


200522
VSでコードのファイルがリソースファイルのフォルダに属している

何やら、試行錯誤でプロジェクトを作った際、よく見ると、Cのソースファイルが、ソリューションエクスプローラーでリソースファイルのフォルダに属している問題。

ファイル一つのプロジェクトで、ソースファイルのフォルダには何もありません。
これで、期待通りに実行は出来ているので、実用上の問題はないのですが、少し不安です。

そこで、思い切って入れ換えてみました。
方法は、
ソリューションエクスプローラーのファイル名の右クリックメニューに削除という項目があります。
これを選ぶと、除外か削除か選択するように促されます。
そこで、除外を選びます。削除を選ぶと、実際にファイルが削除されそうでした。
次に、ソースファイルの右クリックメニューで、追加、既存の項目、と進んで、該当ファイルを選択すると、無事入れ換えが出来ました。
ビルドもデバッグも同じようにできます。変わりません。


200521
VS2019、ビルドエラー、C4996

これまで、ほどほどうまくいって、期待通りの結果を出しているCのプロジェクトがあったので、このコードを使って別のファイルを作ろうと、新しいプロジェクトを立ち上げました。

新しいプロジェクトを作り時、試行錯誤で色々試したので、どの方法だったか思い出せません。
何やら、ソースファイルに、元のファイルからコードを全コピーして持ってきたと思います。
ところが、全く同じコードなのですが、ビルドエラーです。
fopenなどがエラーになっています。
元のコードでは警告で済んでいる所です。

何か対策があるはずと調べてみたら、
ソースファイルを反転させて、(右クリックメニューにあるプロジェクトから進んでも同じです。)、
メニューの、プロジェクト、プロパティ、C/C++、全般、と進んで、SDLチェック、という項目を、いいえ、にすると解決しました。
プロジェクトの作り方、初期設定が間違っていたのだと思います。
多分、コンソールではなくWindowアプリを選んでいたのだと思います。

なお、この問題、上の200522の記事で、根本的な(多分)解決方法を見つけてあります。

200519
malloc

Cでテキストファイルを読み込もうとしました。
250KBほどある巨大なファイルです。
大きいファイルだと、読み込んだり、作業するのが面倒なので、最初は小さなファイルから始めました。

まあ一応、予定通りの動きをします。
そこで、目的のファイルを読み込ませてみます。
エラーです。

試行錯誤と合わせて、ネットで調べた結果、分かったことです。
文字型配列の要素数に限度があり、大きな配列を宣言する時は、mallocを使って領域を確保する必要があるとの事です。
スタック領域、ヒープ領域という言葉で説明されています。
普通の宣言では、スタック領域に確保され、こちらだと、通常、あまり大きな領域は確保できない。
思い起こすと、アセンブラで言う、push、popの領域でしょうかね。
ヒープ領域は、この制限がなく、こちらを使う時には、mallocを使って確保する、のだそうです。

200512
文字コード、改行
Cでのテキストファイルの保存に関して
改行が余分に入って保存された事があります。
メモ帳で見たら、Macintosh(CR)となっていました。
TeraPadでは、SJIS CRと表示され、やはり改行が余分に入っていました。
ワードパッドでも試しました。改行されていませんでした。こちらでは何と判断されているか分かりませんでした。

余分な改行の原因はすぐ分かりました。と言っても試行錯誤の結果です。
fopenを "w"で開くと別にCRが付加されます。CRLFの他にCRが付きます。
"wb"で開くと、そのままです。
そうです。テキストをバイト単位で扱っているプログラムです。
ですので、16進のダンプも打ち出せます。
先の改行を挟む所は、通常は0d,0a、(CR,LF)となるべきところで、
余分な改行が入っている分は、0d,0d,0a、(CR,CR,LF)となっていました。
読込の時は、普通に"r"でfopenしても問題は出ていません。

なんとなく、世間では常識的な話なのかもしれません。

200512
プログラム言語、VisualStudio2019、文字コード

ほかの言語についても、多少の知識はあります。あるつもりでした。
現に、PCには古いコードを残しています。
1998年にCを、2003年にC++をやっていた形跡があります。LccとかBccとかのフォルダがあります。
コードもexeファイルも残っているので、試しに実行してみましたが、現在の環境では動きませんでした。
タイムスタンプから見て、Win98とかXPの頃でしょうかね。XPの環境はありますので、実行してみましたが、動きませんでした。

PCを作り変える際、データディスクだけは、そのまま付け換えるなり、コピーするなりして移動させていましたので、当時のOSが何だったかは、はっきりとは思い出せません。

他に、COBOLを勉強していた時期があります。
かすかな記憶では、COBOLは計算が苦手で、平方根の計算が出来ませんでした。
そこで、ニュートン法を使って試行錯誤で平方根を探すルーチンを作った覚えがあります。

具体的には、平方根は、元の数字以下になる事は分かっていますので、まず、元の数の半分の値を2乗します。
さすがに2乗は掛け算です。どの言語でもできます。
この結果が、元の数より大きければ、更に下半分に答えがあることが分かります。
小さければ、上半分です。
ですので、どちらかをさらに半分にした数字で試していきます。
これを必要な桁数まで探していくだけです。
これをある程度進めていくと、小数点以下で変化しない桁が増えていきます。
その変化しない桁は有効な数字と考えていいはずです。多分。

このルーチンは、当時は貴重だったのかもしれません。
オフィスコンピュータのメーカーのSEの方から、コピーさせてくれと頼まれて、コードの入っているFDを渡した記憶があります。
何しろ、当時、COBOLはオフコンでのみ動いていましたので、コンパイルさせてもらう為に、時々、メーカーの事務所に遊びに行っていました。会社にオフコンを導入した際の取引先でした。

BASICに関しては、使っていたPCの数だけありますね。
当時は、各メーカーが独自のパソコンを作っていて、OSもメーカーの数だけありました。それぞれ、ほとんど互換性はありませんでした。
その後、MS-DOSというOSが主流になって、全てMSのWindowsに流れていく訳です。

思い出すのは、沖BasicとN88Basicとの共通のFDを作った事です。
当時は5インチFDでした。2DDとか1MとかのFDの頃です。
双方のBasicで、FATでしたか、データを管理する領域の配置が違っていました。
幸い、当時は、セクター単位で読み書きするコマンドがBASICにもあって、自由に中身を調べ、変更できました。
そこで、互いの管理領域に仮のデータがあるように処理して、アクセスしないようにしていました。

アセンブラも少し勉強しました。MASMとかありました。
当時、Z80でした。haltだけ覚えています。
こちらは、8086に変わった時点で諦めました。
逆だったかもしれません。
ニーモニックでしたか、命令語が一段と増えていました。まあ、様子見、冷やかしでしたので。

さて、本題は、
とにかく、処理の早い言語の導入を考えました。
どうやら、コンパイラならどれでもいいようです。
各言語での速度比較のページによると、BASIC関係以外は大差ありません。いえ、BASICやHSPに比べたら格段に速いです。

真っ先にC言語です。
以前、Cで簡単な計算をする物を作っています。
最初、LotusかExselのシートで作った物を、Basicに移し、C言語に移しました。
更に主流は当時でもC++に移行中で、C++でも作りました。
ところが、C++に至って、クラスだったか構造体だったかが理解できず、挫折しました。
おぼろげな記憶ですが、とにかく、選択肢が多くて、複雑で面倒だなと思ったものです。
その後、現在のHSPを見つけて、ほとんどこれ一本で遊んでいます。
数KBのファイルを扱うものなら、インタプリタでも速度が遅くても問題ないのです。

ここに至って、なにがしかのコンパイラで作ればなんとかかるだろうと、準備を始めました。
VisualStudio2019をインストールしました。
これだと、CでもC++でもVisualBasicでも使えるという事です。しかも無料です。
先の速度比較では、VisualBasicでもHSPより格段に速いとありました。

まず、VB、C++,、Cと試しました。
先に、昔、自分で作った物をVS2019に移そうとしましたが、まずこれが出来ません。
ようやく移行できて、コンパイルすると、ビルドでしょうか、エラーです。
残念なことに、Cでさえ、その原因が分かりません。
どうやら、当時のコンパイラ独特のヘッダファイルとかがあるようです。

それなら、VBなら何とかなるかと、試してみました。
さすがに、VBだと、ある程度工夫すると動きます。
ところが、結果が文字化けします。
理由は、どうやら昔のShift_JISが通用しない事にあるようです。
いまのVisualStudioはUnicode(UTF-8、16)が標準みたいです。
コンバートする方法もあるみたいですが、理解できません。うまくいきません。

最終的にCで組めました。コンソールタイプですが。
ありがたいのは、どうやらC言語だとVSでもShift_JISで扱える事です。
標準なのかどうかは不明ですが、そのままで通用しています。
ソースファイルもShift_JISで保存されています。
ことによると、最初の既存のコードファイルがShift_JISだったので、そのまま引き継がれているのかもしれません。
作業対象のShift_JISのテキストファイルを普通にfopen、fread、fwriteすると、Shift_JISのままで操作できています。



200512
実行速度
現在、このサイトのページを作る事以外にも、色々な作業をHSPで試しています。
その中で、テキストファイルの変換をするものを作りました。
テキストを読み込んで、変換作業をして、再度ファイルに保存するものです。
単純な作業なのですが、バイト単位の作業で、意外と時間がかかります。
100KB程度のファイルで、11分ほどかかっていました。(この点、下に訂正あり。)
これでは、少し、時間がかかり過ぎです。

そこで、他の言語の実行速度を調べてみました。
まず最初に、自分のスクリプトを見直してみる、という事には思い当たりませんでした。
ネットで、他の言語を調べてみると、さすがにコンパイラでは速度は桁違いです。しかも何桁も違います。
そこで、コンパイラを試す事にしました。

200526追記
C言語での作業が一段落したので、結果です。
対象は100KB程度のテキストの変換作業です。作業内容は先のHSPと同じです。
HSPのみでは、11分かかる作業が、Cで作ると、125ミリ秒弱で終わります。0.125秒です。
HSPに比べてCでは、1/5500の時間で済んでしまうという事になります。(この点、以下に訂正あり。)

200530追記
Cでコードを作る際、HSPで組んでいたスクリプトを参考にしました。
ここで、HSPのアルゴリズムを見直しましたので、実行速度に関して、ものすごく冗長に作っていた事に気付きました。
プログラムは、速度より見やすさ優先が昔からの癖で、一回のループで済むところを何回かに分けたりして処理しています。

極端な話、数回のループなら、スクリプトをその数分コピーして済ますようなこともあります。
この方が、安全確実ですので。

やむを得ず、ループ内で複数の作業をする場合、作業の経過が分かるように、中間の処理状況を入れる変数をたくさん作ります。
途中、debugやassertを使って状況を調べられ、作業状況が分かり易くなるのは間違いありません。
ただ、大量のデータを扱う場合、そうも言っておられません。上の通り、たいした事をしていないのに11分かかる様になってしまいます。

Cの方は、アルゴリズムが分かっていたので、一回のループで処理できています。
それに、経過記録など悠長なコードの書き方を知りません、コンソールなので元々表示が単純でした、等が原因でしょう。
時間計測の際は、更に、#defineでprintf類をスキップします。

これを見習って、翻って、今度はHSPのスクリプトも修正しました。
作業時間の比較をするのなら、無駄な作業を省かないといけません。
無駄な変数を使わない。
無駄な表示もしない。
今回、mesboxも大量のテキストだと、表示時間が結構かかる事に気付きました。
しかも、末尾の記述が見やすいように、逐一スクロールさせていましたので大変です。
また、mesboxを使って、バイト単位の作業状況を表示させていました。
つまり、バイトごとに表示、ここでは数字ですが、を書き換えていました。
ループも出来るだけ少なく、中でawait類を使わない。(これで大量のデータ処理をすると、帰ってこない状態になりますが。)
等、作り直しました。

結果、先の100KBのテキストの処理が、49秒で終わるようになりました。HSPだけでの作業です。
上で、冗長なスクリプトで、11分かかったとメモしたものです。正確には689秒でした。
HSPでの改良だけで、前に比べて、1/14の時間に短縮されています。
いえ、それだけ冗長なスクリプトを書いていた、という事で、11分に関しては、これ以上比較する意味がありません。

次に、肝心のテキストの変換作業だけをCで代行する事を考えました。
本来は、作業速度を考えるなら、デスクトップを含んで全部をCか他のコンパイラで作ってしまう所でしょう。
あるいは、Cでdllを作って、HSPで読み込んで実行させる、という事の様です。
これについても少し調べましたが、私にはどちらも理解が出来ませんでした。

そこで、Cとの連携をファイルを使ってする事にしました。幼稚なやり方です。ですが、今の知識で出来ました。
目的のファイル名など、HSPでデータ引き継ぎ用のテキストファイルを作って保存して、Cを呼び出します。
Cでは、そのファイルを読み込んで変換作業をし、作業結果を、やはりファイルに保存します。

まあ、Cでも、ファイルの読み書きと、足し算引き算ぐらいなら、私にも出来るという事です。
それに、今回分かった事で、ファイルの読み書きには、さして時間がかからないという事です。
Cと引継ぎをする為のファイルにしろ、作業対象のファイルにしろ、ミリ秒の単位で処理されています。

このCで作るファイルをHSPで見張っていて、ファイルが出現したら、作業完了となります。
今、HSP側で、ファイルの出現を見張る間隔を1秒にして試すと、変換作業が3秒で終わるようになりました。
HSPだけで作業すると、50秒でしたので、1/17に短縮したことになります。
何より、3秒程度の待ち時間なら、精神的に許される時間だと思います。
その意味で、Cとの原始的な連携は許されていいと思います。

更に、HSP側の見張る間隔を0.5秒にすると、作業は1.2秒で終わりました。
これなら、もう十分に許される範囲です。
改良しても、HSPだと目的の100KBを処理するのに50秒かかります・
これでは、やはりストレスです。Cと組み合わせた価値が出てきます。

この状態で、C単独での実行時間(0.094秒)と比べると、527倍の時間です。Cだと、1/527の時間で済む、という事です。

ここまでの数字を一覧表にまとめてみます。
言語 100KBのテキストでの作業   20KBのテキストでの作業   2KB のテキスト
処理時間(秒) HSPを1として   処理時間(秒) HSPを1として   処理時間(秒) HSPを1として
HSP改良前 689.000 13.9   134.000 60.2  
HSP改良後 49.548 1.0   2.226 1.0   0.156 1
HSP+C 1.234 1/40   1.023 1/2.2   1.094 7.0
Cのみ 0.094 1/527   0.031 1/72  

20KBのテキストでも試してみました。
HSP+Cでの作業時間は、どちらでも、ほとんど変わりません。
これは、HSPでCの作業終了を見張る間隔を0.5秒にしている事で、この時間内に収まる作業では差は出ないという事でしょう。
何しろ、C単独だと、0.1秒程度で終わっています。

HSP単独での作業で、作業時間がファイル容量の比率にならないのが不思議です。
指数関数的な作業になっている様ですが、よく分かりません。

HSPで、2KBも試して、HSPだけで時間の比較をしてみました。
100KBだと、1KB当たり、0.495秒、
20KBだと、1KB当たり、0.113秒、
2KBだと、1KB当たり、0.078秒、
やはり、何か指数関数的なものがあるようです。



200507
Visual Studio Code 日本語化

エディタが欲しくて、Visual Studio Codeをインストールしてみました。
HSP以外のプログラム言語に挑戦してみようという魂胆です。
どうやら、今持っているTeraPadやメモ帳では物足りないみたいですので。

まず最初に、
MSのページからインストーラをダウンロードするのですが、紹介されているページが沢山あり、どれが一番安全なのか、主流なのか迷います。
結局、Microsoft Storeにも置いてありましたので、これを使いました。
他にも、MSのページが検索の最初に出ました。そこからもダウンロードしてみましたが、全く同じ物でした。

インストールは簡単に終わり、簡単に起動できました。
途中、デスクトップにアイコンを作る、ファイルの右クリックメニューに追加する、という意味のチェックが出ましたので、追加しておきました。

問題は、最初の起動が英語で、これを日本語化する事でした。
ネットの記事通り実行したつもりですが、再起動しても相変わらず英語のままです。

何度か試した結果、原因は、
メニューのviewのプルダウンから幾つか進んで、
configure display languageをクリックした後、
select display languageというダイアログが出ますので、
そこで、jaを選択する、
という事でした。
この間、日本語のインストールが済んでいなければ、その作業も入ります。

肝心の場面は下のキャプチャー画像の通りです。
そのまま適当にクリックしたり、Enterなどで指定するとenの方が反転していて、enを指定したことになります。
ここでしっかり、jaの部分を指定し、反転させねばなりません。
install云々の所をクリックしても、jaを選択したことにはなりません。
enを選択した状態でも、再起動のメッセージが出ますので、ここがとても迷うところでした。


200506
HSP、C言語

普段、HSPでプログラムを作っています。趣味程度です。
このサイトの大半のページを、そのHSPで半自動化しています。
今回、サイト作成とは関係なく、テキストファイルを読み込んで、バイト単位で変換して、保存する、というプログラムを作りました。
ところが、これが手間取るのです。
100KB程度のテキストファイルだと11分かかってしまいました。

このサイトのページは、5KBから10KB程度です。この程度のものだと待ち時間は感じられません。
ただ、11分もかかるようだと問題です。
対策は、プログラムを改良するか、他の言語を試すかです。
他の言語を試すことにしました。



トップページへ