質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

5回答

538閲覧

ファイルの読みこみ、書き込み操作について

oryou

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

1クリップ

投稿2017/11/10 00:00

質問内容
ファイルの読み込み書き込み操作をするときに、どんな処理が基本的に必要なのかを教えてください。

補足
今回ご教示していただきたい内容は、コードではなく処理の内容です。

取り扱うファイル
テキストファイルを扱います。
データ量としては10行くらいです。
記述された文字列を読み込んで画面に表示したり、変更した内容をファイルに書き込んだりします。
ただ自分の中ではテキストファイル以外(バイナリファイル等)であっても、基本的に求められる処理は同じなのかなと思っているので、テキストファイルを適正に操作する方法を学べば他のファイルも扱えるのかなと思っています。
勘違いしていたらすいません。

自分で思いつく処理内容
自分の中では以下のような操作で十分なのかなと思っていますが、ほかにも必要な処理があればご教示ください。
まだ扱ったことは無いのですがデッドロックや大容量のデータの扱いについては、今回は除外しています。

・ファイルを読み込む処理
1、読み込むファイルを指定する。
2、指定されたファイルが存在するかを確認する。
3、ファイルが存在しない場合は、仕様に応じてエラーメッセージを表示するか、プログラム側で新規に作成する。
4、読み込むファイルをロックする。
5、ファイルを読み込む。
6、読み込みが終了したらロックを外す。
7、読み込んだデータを画面に表示する処理をする。

・データをファイルに書き込む処理
1、書き込むファイルを指定する。
2、指定されたファイルが存在するかを確認する。
3、ファイルが存在しない場合は、仕様に応じてエラーメッセージを表示するか、プログラム側で新規に作成する。
4、書き込むファイルをロックする。
5、ファイルにデータを書き込む
6、書き込みが終了したらロックを外す。
7、終了

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

自分の中では以下のような操作で十分なのかなと思っていますが、ほかにも必要な処理があればご教示ください。

扱うのはテキストファイルですよね?

であれば、質問者さんが列挙した以外のことで考えなければならないことに文字エンコーディングがあると思います。(個人的にはこれが一番重要なことではないかと思っています)

ファイルの中身は単純にバイト列ですが、プログラムから文字列をファイルに書き込むときにどの文字エンコーディングでバイト列に変換するか、ファイルからプログラムに文字列として読み込むときにファイルのバイト列がどの文字エンコーディングで書き込まれていたたかが分からないと何ともならないですよね。

一度、メモ帳で "あいうえお" などの文字をファイルに書き込んで、それをバイナリエディタで開いて見てください。メモ帳の「文字コード」オプションで ANSI, Unicode, Unicode big endian, UTF-8 が選択できますが、それぞれ結果は異なるはずです。

メモ帳で作ったテキストファイルなら、文字コードが Unicode, Unicode big endian, UTF-8 の場合は先頭に BOM が付くので、BOM がついていていれば BOM の指定どおり、付いてなければ Shift_JIS と判断できます。

StreamReader などを使ってもそのような実装ができます。

StreamReader コンストラクター (String, Encoding)
https://msdn.microsoft.com/ja-jp/library/x8xxf0x5(v=vs.100).aspx

"StreamReader オブジェクトは、ストリームの最初の 3 バイトを参照して、エンコーディングの検出を試みます。 ファイルが該当するバイト順序マークで開始される場合は、UTF-8、リトル エンディアン Unicode、ビッグ エンディアン Unicode の各テキストが自動的に認識されます。 それ以外の場合は、ユーザー指定のエンコーディングが使用されます"

BOM がつかないテキストエディタで作ったテキストファイルですと、どの文字エンコーディングなのかを把握して、例えば上に紹介した StreamReader を使うならコンストラクターの第二引数 encoding に文字エンコーディングを指定しないと正しく解釈できず、結果文字化けするはずです。

注:kiichi54321 さんが紹介された File クラスを使う際も上に書いた文字エンコーディングへの配慮は必要です。

投稿2017/11/10 04:08

編集2017/11/10 04:43
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oryou

2017/11/10 13:04

回答ありがとうございます。 文字コードはあまり気にしたことが無かったのですが覚えておく必要がありますね。 今まで自分の作ったアプリでかつ自分で作成したファイルしか扱ってなかったので、文字コードは自分指定なので問題はなかったのですが、もし他の人が作成したファイルを扱うようになったら文字化けで処理できなくなるのですね。 覚えておくようにします。 ありがとうございました。
guest

0

ベストアンサー

本来は、そういう面倒な処理やるのだけど、テキストファイルに関しては、大体は、
File.ReadLines
https://msdn.microsoft.com/ja-jp/library/dd383503(v=vs.110).aspx

File.WriteAllText
https://msdn.microsoft.com/ja-jp/library/ms143375(v=vs.110).aspx

を使えばよくて、せいぜい、
対象ファイルの存在確認、をして、
とりあえず、ファイル処理をしているところをTry Catchで囲んで例外処理をするくらいで十分です。

読み込むファイルをロックとかは、勝手にやってくれることなので、気にしなくていいです。
やっていることを、知っているのは重要ですけど。
(たまにはまるので、エクセルとかで)

また、Using文を使うことで、解放処理を勝手にやるので、Using文を使うところでちゃんと使いましょう。

投稿2017/11/10 01:34

編集2017/11/10 04:15
kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oryou

2017/11/10 12:49

回答ありがとうございます。 ロックをする必要があると思い込んでいたのですが、そこはStreamReaderが行ってくれているのですね。 ファイル読み込み中にsleep()をして、自分でテキストファイルを削除しようとしたのですが、できませんでした。 テキストファイルの扱いが正しく分かりました。。 テスト的に以下のようなコードでテキストを読み込んでみました。 try catchとusingの合わせ技も適正に使えているか自信はありませんが以下のような形にしてみました。 どうもありがとうございました。 static void Main(string[] args) { // ファイルのパス string filePath = @"C:\Users\T534S\Desktop\test.txt"; // ファイルの内容を格納する string contents = string.Empty; try { if (!File.Exists(filePath)) { Console.WriteLine("ファイルを確認してください。"); return; } using (var file = new StreamReader(filePath, System.Text.Encoding.GetEncoding("shift_jis"))) { // ファイルを読み込む contents = file.ReadToEnd(); // 10秒間停止 System.Threading.Thread.Sleep(10000); } } catch (Exception ex) { // エラーメッセージを表示 Console.WriteLine(ex.Message); } // ファイル内容を表示 Console.WriteLine(contents); }
guest

0

テキストファイルを適正に操作する方法を学べば
他のファイルも扱えるのかなと思っています。

ご質問は汎用的な考えを求めていると思うので、
とくにエラー処理について解説したいと思います。
入門書などにあまり載ってない難しい部分だからです。


3、ファイルが存在しない場合は、
仕様に応じてエラーメッセージを表示するか、
プログラム側で新規に作成する。

ご質問で提示された手順でおおむね問題ないと思いますが、
今回はエラー処理がテーマなので、あえてくどく重箱の隅をつついてみましょう。

引用部でどういう問題が起こりうるか考えてみます。

ファイルがなく新規作成するとき、タイトルが未設定の場合、
「新規ファイル」といったデフォルトの名前で保存するでしょう。

しかしここで、2回目の場合に何が起こるでしょうか。
「新規ファイル」に上書きしてしまう挙動が起こりがちです。

多くの開発者の本音としては、「利用側が不注意だから悪いのだ」
と言いたくなるところです。しかし、注意が必要なのは使いにくいソフトです。

ここで、既存のテキストエディタなどだと、
「新規ファイル(2)」などと連番を振って、
勝手に上書きしない挙動をしますが、見たことがあるかと思います。
その方が使いやすいので、そういう処理を書いていきます。

そんなの分かる、と思うかもしれないので、
もう少し難しい処理としては、アンドゥ・リドゥの処理があります。
ファイルの保存もアンドゥできるという、
そういうテキストエディタがあるんです。

保存を巻き戻すときには、削除する処理が必要になります。
そうすると、テキスト編集中にフォルダの
ファイルをリネームすると消える可能性が出てきます。

だんだんエラー処理が難解になっていく様子がお分かりでしょうか。
こういう細かい面倒臭いケースが、それこそ100個とかあるわけです。

100個も網羅して説明できないので、どうやって想定すればいいかと言えば、
利用側の立場に回って考えることです。利用していた頃を思いだすとか、
既存のソフトの挙動やヘルプを見て、どうやって処理するのか研究するとか。

「秀丸」といった老舗のテキストエディタの
変更履歴などを見ると、その修正量に気が遠くなります。
20年直し続けてきた分量をイメージしてください。

まあ今は、便利なライブラリやフレームワークが
細かいところを代わりにやってくれたりしますが、
自分がライブラリやフレームワークの作成者に回る場合に、
こうした意図しないケースの対応が必要になってきます。

プログラミングは、動くだけなら意外と簡単で、
でも動いてからが本番で、使いやすくするのが難しいのです。

投稿2017/11/10 04:40

LLman

総合スコア5592

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oryou

2017/11/10 13:16

回答ありがとうございます。 全く考えたこともない内容でしたが凄く興味深かったです。 エラー時は「ファイルが見つかりません」とだけメッセージを表示すればいいのかなと思っていましたが、いろんな処理の仕方があるのですね。 しかもかなり複雑な内容の・・・。 私も秀丸エディタを利用しているのですが、20年も更新されているなんて知りませんでした。 「使いやすくていいエディタだな」と思っていただけでしたが、凄い技術の結晶だったのですね。 プログラムは動かなきゃ意味がない、だけど動けばいいっていうところでしか考えていませんでしたが、動いてからが本番なんですね。 勉強になりました。 ありがとうございました。
guest

0

こんな感じでしょうか。

1.ファイルをオープンする
2.オープンがエラーなら、原因を見て適切な処理をする
3.ファイルから読む
4.読み込みでエラーが起これば、原因を見て適切な処理をする
5.EOFで無ければ読んだデータの処理をする
6.EOFで無い場合、繰り返しが必要なら3から繰り返す
7.EOFの場合、もしくは何らかの理由で途中で読むのをやめた場合は、ファイルをクローズする

これは、読み込んだ段階でEOFが分かる言語の場合です。
言語によっては、読む前にEOFであるかどうか判断する必要があります。
なお、EOFというのはEnd of File(これ以上読み込むデータがない状態)です。

投稿2017/11/10 00:11

otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oryou

2017/11/10 12:53

回答ありがとうございます。 C#ではEOFを気にせずコードを組んでいますが、言語によってそういった処理があるのですね。 これから先EOFを扱う処理があるかもしれないので覚えておくようにします。 ありがとうございました。
otn

2017/11/10 16:01

すいません。質問文だけ見て、タグを見て無かったので、C#限定の質問だと気づきませんでした。 > コードではなく処理の内容です。 ということだったので、言語に依らない汎用的な話と思って回答しました。
guest

0

  1. ファイルが開けなかった(ロックできなかった)
  2. 全データを読込、書込できなかった
  3. 読込データが正しくなかった(バリデーション)

も考慮しておいたほうがよいと思います。
また、これらの異常時、アプリケーションの状態(表示画面など)をどうするのか(クリアするかそのまま残しておくか)を決めておく必要があります。

投稿2017/11/10 04:44

can110

総合スコア38266

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oryou

2017/11/10 12:57

回答ありがとうございます。 上記で挙げられている3つの内2番目と3番目については全く考えたことが無かったので、今後こういった点も視野に入れていきたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問