📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

 
(同じ利用者による、間の4版が非表示)
1行目: 1行目:
== 概要 ==
C#では、<code>System.IO</code>名前空間を使用することにより、ファイルの読み書き、作成、削除等の基本的な操作を行うことができる。<br>
<br>
テキストファイルの読み込みには、主に<code>StreamReader</code>クラスや<code>File.ReadAllText</code>メソッドが使用される。<br>
これらを使用することにより、テキストファイルの内容を簡単に文字列として取得できる。<br>
<br>
テキストファイルへの書き込みには、主に<code>StreamWriter</code>クラスや<code>File.WriteAllText</code>メソッドが使用される。<br>
<br>
バイナリファイルを扱う場合は、<code>FileStream</code>クラスを使用する。<br>
これにより、バイトデータの読み書きが可能になる。<br>
また、非同期操作を行う場合は、<code>ReadAsync</code>メソッドや<code>WriteAsync</code>メソッド等を使用することで、効率的にファイル操作を行うことができる。<br>
<br>
ファイルパスの操作には、<code>Path</code>クラスが役立つ。<br>
このクラスを使用することで、ファイル名の取得や拡張子の変更、ディレクトリの結合等の操作が簡単に行える。<br>
<br>
セキュリティの観点からは、ファイルアクセス権限の設定が重要である。<br>
<code>FileInfo</code>クラスや<code>DirectoryInfo</code>クラスを使用して、ファイルやディレクトリのアクセス権限を確認したり変更することができる。<br>
<br>
エラーハンドリングについて、ファイル操作時には様々な例外が発生する可能性があるため、try-catchブロックを使用して適切に対処することが基本である。<br>
<br>
また、大容量ファイルを扱う場合は、メモリ効率を考慮する必要がある。<br>
ファイルを1度に全て読み込むのではなく、ストリームを使用して少しずつ読み込むことにより、メモリ使用量を抑えることができる。<br>
<br><br>
== バイナリファイル ==
== バイナリファイル ==
==== バイナリファイルの読み込みと書き込み ====
==== バイナリファイルの読み込みと書き込み ====
ファイルの内容をすべてbyte配列に読み込む、または、byte配列全体をファイルに書き込む場合、<br>
ファイルの内容をすべてbyte配列に読み込む、または、byte配列全体をファイルに書き込む場合、<br>
Fileクラス(System.IO名前空間)のReadAllBytesメソッドおよびWriteAllBytesメソッドを使用する。<br>
<code>File</code>クラス(<code>System.IO</code>名前空間)の<code>ReadAllBytes</code>メソッドおよび<code>WriteAllBytes</code>メソッドを使用する。<br>
これらのメソッド(静的)では、ファイルを開く、byte配列への読み込みまたはbyte配列の書き込み、ファイルを閉じるという3つの処理を<br>
<br>
ReadAllBytesメソッドで実行可能である。<br>
これらのメソッド(静的)では、"ファイルを開く"、"byte配列への読み込みまたはbyte配列の書き込み"、"ファイルを閉じる"という3つの処理を<br>
ReadAllBytesメソッドは、読み込むファイルのパス名をパラメータに指定して呼ぶと、戻り値としてファイルの内容を読み込んだbyte配列を返す。<br>
<code>ReadAllBytes</code>メソッドで実行可能である。<br>
また、WriteAllBytesメソッドでは、書き込むファイルのパス名(ファイルが存在する場合は上書き)と書き込むbyte配列をパラメータで指定する。<br>
<code>ReadAllBytes</code>メソッドは、読み込むファイルのパス名をパラメータに指定して呼ぶと、戻り値としてファイルの内容を読み込んだbyte配列を返す。<br>
尚、WriteAllBytesメソッドの戻り値はない。<br>
<br>
  <source lang="cpp">
また、<code>WriteAllBytes</code>メソッドでは、書き込むファイルのパス名(ファイルが存在する場合は上書き)と書き込むbyte配列をパラメータで指定する。<br>
なお、<code>WriteAllBytes</code>メソッドの戻り値は無い。<br>
  <syntaxhighlight lang="c#">
  byte[] data = File.ReadAllBytes(@"hoge.bin"); // 読み込み
  byte[] data = File.ReadAllBytes(@"hoge.bin"); // 読み込み
  File.WriteAllBytes(@"newhoge.bin", data);    // 書き込み
  File.WriteAllBytes(@"newhoge.bin", data);    // 書き込み
  </source>
  </syntaxhighlight>
<br>
<br>
==== サンプルコード(バイナリファイルを固定サイズで分割する) ====
==== バイナリファイルを固定サイズで分割する ====
次のサンプルコードは、ReadAllBytesメソッドとWriteAllBytesメソッドを使用したサンプルコードである。<br>
以下の例では、<code>File</code>クラスの<code>ReadAllBytes</code>メソッドと<code>WriteAllBytes</code>メソッドを使用している。<br>
このプログラムでは、バイナリファイルを読み込み、それを固定サイズ(サイズ : 1[MB])の複数ファイルに分割して出力する。<br>
バイナリファイルを読み込み、それを固定サイズ(1[MB])の複数ファイルに分割して出力している。<br>
尚、出力する最後のファイルは固定サイズに満たない場合がある。<br>
<br>
なお、出力する最後のファイルは固定サイズに満たない場合がある。<br>
  <syntaxhighlight lang="C#">
  <syntaxhighlight lang="C#">
  using System;
  using System;
51行目: 78行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br>
<br>
ReadAllBytesメソッドは、ファイル全体を一度に読み込むため、巨大なファイルを扱う場合には、<br>
<u>※注意</u><br>
読み込みに掛かる時間や使用するメモリ量について注意が必要である。<br>
<u>ReadAllBytesメソッドは、ファイル全体を一度に読み込むため、</u><br>
<u>サイズの大きいファイルを扱う場合は、読み込みに掛かる時間や使用するメモリ量について注意が必要である。</u><br>
<br>
<br>
==== サンプルコード(非同期でバイナリファイルを読み書きする) ====
==== 非同期でバイナリファイルを読み書きする ====
バイナリファイルへ書き込んだ後、それを読み込むサンプルコードに示す。<br>
以下の例では、バイナリファイルへ書き込んだ後、そのバイナリファイルを読み込んでいる。<br>
この例では、書き込み用に開くときにFileMode.Createを指定しているので上書きになる。(追記する場合 : FileMode.Append)<br>
バイナリファイルを書き込み用として開く時に<code>FileMode.Create</code>を指定しているため、上書きになる。(追記する場合は、<code>FileMode.Append</code>)<br>
  <syntaxhighlight lang="c#">
  <syntaxhighlight lang="c#">
  async Task BinaryReadWriteAsync(byte[] data)
  public async Task BinaryReadWriteAsync(byte[] data)
  {
  {
     const string FilePath = @".\sample.dat";  // 読み書きするファイル
     const string FilePath = @".\sample.dat";  // 読み書きするファイル


     // バイナリファイルへ書き込み
     // バイナリファイルとして書き込む
     // ファイルを上書きモードで開く(ファイルが存在しない場合は作成)
     // ファイルを上書きモードで開く(ファイルが存在しない場合は作成する)
     // 追加モードにするにはFileModeをAppendに変える
     // 追記モードにするには、FileMode.Appendに変更する
     using (var fs = new FileStream(FilePath, FileMode.Create, FileAccess.Write))
     using (var fs = new FileStream(FilePath, FileMode.Create, FileAccess.Write))
     {
     {
244行目: 272行目:
<br><br>
<br><br>


== CSVファイル ==
== ファイルの削除 ==
CSVファイルを読み込むには、.NET Framework 2.0で追加された<code>TextFieldParser</code>クラス(<code>Microsoft.VisualBasic.FileIO</code>名前空間)を使用する。<br>
==== 読み取り専用ファイルの削除 ====
<code>TextFieldParser</code>クラスを使用することで、CSVファイルを読み込み、各行の各フィールドの文字列を簡潔に取得することができる。<br>
<br>
==== CSVファイルを読み込む ====
<code>TextFieldParser</code>クラスを使用してCSVファイルを読み込むには、<br>
まず、<code>TextFieldParser</code>クラスのコンストラクタに処理するCSVファイルを指定して、インスタンスを生成する。<br>
CSVファイルに日本語が含まれている場合は、文字コードを指定する。<br>
<syntaxhighlight lang="c#">
using System.Text;
using Microsoft.VisualBasic.FileIO;
var parser = new TextFieldParser(@"hoge.csv", Encoding.GetEncoding("Shift_JIS"));  // 文字コードはShift-JISを指定する
</syntaxhighlight>
<br>
次に、<code>TextFieldType</code>プロパティに<code>FieldType.Delimited</code>を指定する。<br>
もし、<code>FieldType.FixedWidth</code>を指定する場合、フィールドが固定幅のファイルも扱うことができる。<br>
<br>
また、<code>SetDelimiters</code>メソッドを使用して、区切り文字を指定する。(複数の区切り文字が指定可能)<br>
CSVファイルの場合は、<code>,</code>(カンマ)を指定する。<br>
<syntaxhighlight lang="c#">
parser.TextFieldType = FieldType.Delimited;
parser.SetDelimiters(",");  // 区切り文字はカンマを指定する
</syntaxhighlight>
<br>
<code>TextFieldParser</code>クラスの<code>ReadFields</code>メソッドを実行するごとに、CSVファイルを1行ずつ読むことができる。<br>
<code>ReadFields</code>メソッドは、読み込んだレコードの全てのフィールドを文字列配列に変換して返す。<br>
次のレコードが存在するかどうかは<code>EndOfData</code>プロパティにより判定できるため、ループにより、CSVファイル全体を処理できる。<br>
<syntaxhighlight lang="c#">
while (!parser.EndOfData)
{
    // 配列rowの要素は読み込んだレコードの各フィールドの値
    string[] row = parser.ReadFields();  // 1レコード読み込む
}
</syntaxhighlight>
<br>
==== CSVファイルを読み込み表示する ====
以下の例では、hoge.csvファイルを読み込み、各フィールドを切り出してタブ区切りで画面に出力する。<br>
改行文字および空白文字がどのように処理されるかを分かりやすくするために、それぞれをnと_に置換して出力している。<br>
<br>
* <code>HasFieldsEnclosedInQuotes</code>プロパティ
*: フィールドに改行やデリミタを含める為に引用符を使っているようなフォーマットを考慮する場合は、
*: <code>HasFieldsEnclosedInQuotes</code>プロパティを<code>true</code>に設定する。(初期値はtrue)
* TrimWhiteSpaceプロパティ
*: フィールドの前後の空白文字を削除しない場合は、<code>TrimWhiteSpace</code>プロパティを<code>false</code>に設定する。(初期値はtrue)
<br>
<syntaxhighlight lang="c#">
using System;
using System.Text;
using Microsoft.VisualBasic.FileIO;
class CSVParser
{
    static void Main()
    {
      using (var parser = new TextFieldParser("text.csv", Encoding.GetEncoding("Shift_JIS")))
      {
          parser.TextFieldType = FieldType.Delimited;  // フィールドはデリミタにより区切る(可変)
          parser.Delimiters = new[] {","};            // 区切り文字を指定
          parser.CommentTokens = new[] {"#"};          // #で始まる行をコメントとする
          // parser.HasFieldsEnclosedInQuotes = false; // 引用符で括られたフィールドを持つか指定
          // parser.TrimWhiteSpace = false;            // フィールドの前後に含まれる空白を削除するか指定
          while (!parser.EndOfData)
          {
            try
            {
                string[] row = parser.ReadFields(); // 1行読み込む
                foreach (string field in row)
                {
                  field = field.Replace("\r\n", "n"); // 改行をnに置換
                  field = field.Replace(" ", "_");    // 空白を_に置換
                  Console.Write(field + "\t");    // タブ区切りで出力
                }
                Console.WriteLine();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
          }
      }
    }
}
</syntaxhighlight>
<br><br>
 
== ファイルを確実に削除する ==
<code>System.IO.File</code>クラスの<code>Delete</code>メソッドを使用する場合、読み取り専用ファイルに対して実行すると例外が発生する。<br>
<code>System.IO.File</code>クラスの<code>Delete</code>メソッドを使用する場合、読み取り専用ファイルに対して実行すると例外が発生する。<br>
これを解決するには、ファイルを削除する前に、ファイルの読み取り専用属性を解除する。<br>
これを解決するには、ファイルを削除する前に、ファイルの読み取り専用属性を解除する。<br>
369行目: 310行目:
  </syntaxhighlight>
  </syntaxhighlight>
<br><br>
<br><br>
== パーミッション ==
.NET 5以降では、<code>System.IO.FileSystem</code>名前空間に<code>UnixFileMode</code>列挙型が追加された。<br>
この列挙型を使用して、UNIX系OSのファイルパーミッションを扱うことができる。<br>
<br>
<u>ただし、<code>UnixFileMode</code>プロパティはLinux環境でのみ動作することに注意する。</u><br>
<br>
<syntaxhighlight lang="c#">
using System;
using System.IO;
class FilePermissions
{
    static void Main(string[] args)
    {
      // lsコマンドのファイルパス
      string filePath = $"/usr/bin/ls";
      // ファイルが存在するかどうかを確認
      if (!File.Exists(filePath))
      {
          Console.WriteLine("指定されたファイルが存在しない");
          return;
      }
      try
      {
          // ファイルの情報を取得
          FileInfo fileInfo = new FileInfo(filePath);
          // Unixファイルモードを取得
          UnixFileMode mode = fileInfo.UnixFileMode;
          // パーミッションを8進数で表示
          Console.WriteLine($"ファイル: {filePath}");
          Console.WriteLine($"パーミッション: {Convert.ToString((int)mode, 8).PadLeft(4, '0')}");
          // 詳細なパーミッション情報を表示
          Console.WriteLine("詳細:");
          Console.WriteLine($"ユーザ: {((mode & UnixFileMode.UserRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.UserWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.UserExecute) != 0 ? "x" : "-")}");
          Console.WriteLine($"グループ: {((mode & UnixFileMode.GroupRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.GroupWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.GroupExecute) != 0 ? "x" : "-")}");
          Console.WriteLine($"その他:  {((mode & UnixFileMode.OtherRead) != 0 ? "r" : "-")}" +
                            $"{((mode & UnixFileMode.OtherWrite) != 0 ? "w" : "-")}" +
                            $"{((mode & UnixFileMode.OtherExecute) != 0 ? "x" : "-")}");
      }
      catch (Exception ex)
      {
          Console.WriteLine($"エラーが発生: {ex.Message}");
      }
    }
}
</syntaxhighlight>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:C_Sharp]]
[[カテゴリ:C_Sharp]]