DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

テキストファイルから1行削除する、先頭に1行追加する

例えばテキストファイルから末尾の1行だけを削除したいとか、テキストファイルの先頭に1行追加したいという場合は、1発で解決できる方法がありません。基本的には、「文字コードを指定してテキストファイルを読み込む」で紹介している方法でテキストファイルを読み込み、1行削除(あるいは追加)してから、「文字コードを指定してテキストファイルに書き込む」で紹介している方法で上書きするという方法になります。ここではその方法を、具体例を示して説明します。

なおテキストファイルの末尾に1行追加する場合は、「既存のファイルに追加で書き込む」の方法で簡単にできます。

すべて読み込んでから編集し、書き込む方法

まずは、テキストファイルの内容をすべて読み込んでから、文字列を編集して、編集結果をテキストファイルに書き込む方法を考えてみます。

下の例では、テキストファイル「C:\test\1.txt」の先頭に1行追加しています。この例ではFile.ReadAllTextとWriteAllTextメソッドを使用していますので、.NET Framework 2.0以降が必要です。

VB.NET
コードを隠すコードを選択
'ファイルのパス
Dim filePath As String = "C:\test\1.txt"
'テキストファイルからすべて読み込む
Dim str As String = System.IO.File.ReadAllText(filePath)
'先頭に1行追加する
str = "新しい行です。" & vbCrLf & str
'テキストファイルに上書き保存する
System.IO.File.WriteAllText(filePath, str)
C#
コードを隠すコードを選択
//ファイルのパス
string filePath = @"C:\test\1.txt";
//テキストファイルからすべて読み込む
string str = System.IO.File.ReadAllText(filePath);
//先頭に1行追加する
str = "新しい行です。\r\n" + str;
//テキストファイルに上書き保存する
System.IO.File.WriteAllText(filePath, str);

次に、テキストファイルの末尾から1行削除する例を示します。この場合も前の例と同じように文字列を編集することで削除してもよいのですが、ここではテキストファイルの内容を配列で取得して、Enumerable.Takeメソッドで行を削除する方法を紹介します。このコードを実行させるには、.NET Framework 3.5以降が必要です。なお配列の長さを変更する方法は他にもたくさんあり、「配列の大きさを変える」で紹介しています。

VB.NET
コードを隠すコードを選択
'Imports System.Linq

'ファイルのパス
Dim filePath As String = "C:\test\1.txt"
'テキストファイルからすべての行を読み込む
Dim lines As String() = System.IO.File.ReadAllLines(filePath)
'最後の1行を削除する
lines = lines.Take(lines.Length - 1).ToArray()
'最初の1行を削除するなら、次のようにする
'lines = lines.Skip(1).ToArray();
'テキストファイルに上書き保存する
System.IO.File.WriteAllLines(filePath, lines)
C#
コードを隠すコードを選択
//using System.Linq;

//ファイルのパス
string filePath = @"C:\test\1.txt";
//テキストファイルからすべての行を読み込む
string[] lines = System.IO.File.ReadAllLines(filePath);
//最後の1行を削除する
lines = lines.Take(lines.Length - 1).ToArray();
//最初の1行を削除するなら、次のようにする
//lines = lines.Skip(1).ToArray();
//テキストファイルに上書き保存する
System.IO.File.WriteAllLines(filePath, lines);

ファイルを1度しか開かない方法

今までの例では、ファイルを読み込む時と書き込む時の2回開いています。同じファイルに読み込みと書き込みを行うためにファイルを2度開く必要はなく、1度で済ますこともできます。ファイルを1度だけ開くようにすれば、ファイルを読み込んでから書き込むまでの間にファイル内容が変更されてしまうことを防ぐこともできます。

下の例では、一番初めのサンプルと同じことをこの方法で行っています。

VB.NET
コードを隠すコードを選択
'テキストファイルのパス
Dim filePath As String = "C:\test\1.txt"

'書き込みと読み込みが可能なようにファイルを開く
Dim fs As New System.IO.FileStream(filePath, _
    System.IO.FileMode.Open, _
    System.IO.FileAccess.ReadWrite, _
    System.IO.FileShare.None)
'FileStreamを基にして、StreamReaderを作成する
Dim sr As New System.IO.StreamReader(fs)
'FileStreamを基にして、StreamWriterを作成する
Dim sw As New System.IO.StreamWriter(fs)

'テキストファイルからすべて読み込む
Dim str As String = sr.ReadToEnd()

'先頭に1行追加する
str = "新しい行です。" & vbCrLf & str

'位置を先頭にする
fs.Position = 0
'長さを0にする
fs.SetLength(0)
'書き込む
sw.Write(str)
sw.Flush()

'閉じる
sr.Close()
'(StreamWriter.Closeは基になるStreamが閉じた後に呼び出すと、
' 例外ObjectDisposedExceptionをスローする)
If sw.BaseStream.CanWrite Then
    sw.Close()
End If
fs.Close()
C#
コードを隠すコードを選択
//テキストファイルのパス
string filePath = @"C:\test\1.txt";

//書き込みと読み込みが可能なようにファイルを開く
System.IO.FileStream fs = new System.IO.FileStream(filePath,
    System.IO.FileMode.Open,
    System.IO.FileAccess.ReadWrite,
    System.IO.FileShare.None);
//FileStreamを基にして、StreamReaderを作成する
System.IO.StreamReader sr = new System.IO.StreamReader(fs);
//FileStreamを基にして、StreamWriterを作成する
System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);

//テキストファイルからすべて読み込む
string str = sr.ReadToEnd();

//先頭に1行追加する
str = "新しい行です。\r\n" + str;

//位置を先頭にする
fs.Position = 0;
//長さを0にする
fs.SetLength(0);
//書き込む
sw.Write(str);
sw.Flush();

//閉じる
sr.Close();
//(StreamWriter.Closeは基になるStreamが閉じた後に呼び出すと、
// 例外ObjectDisposedExceptionをスローする)
if (sw.BaseStream.CanWrite)
{
    sw.Close();
}
fs.Close();

1行ずつ読み書きする方法

上記の方法では一度にテキストファイルの内容をすべて読み込むため、サイズの大きなテキストファイルの場合、負担が大きくなります。そのような場合は、テキストファイルから1行ずつ読み込み、1行ずつ書き込んだ方がよいでしょう。この時、1つのファイルに読み込みと書き込みを同時に行うこともできますが、とても面倒なので、ここでは書き込み先は一時ファイルとしておき、最後にファイルを入れ替えるという方法でやってみます。

以下の例では、この方法でテキストファイルの先頭の1行を削除しています。

VB.NET
コードを隠すコードを選択
'ファイルのパス
Dim filePath As String = "C:\test\1.txt"
'ファイルを読み込みで開く
Dim sr As New System.IO.StreamReader(filePath)
'一時ファイルを作成する
Dim tmpPath As String = System.IO.Path.GetTempFileName()
'一時ファイルを書き込みで開く
Dim sw As New System.IO.StreamWriter(tmpPath)

Dim isFirstLine As Boolean = True
'内容を一行ずつ読み込む
While sr.Peek() > -1
    '一行読み込む
    Dim line As String = sr.ReadLine()
    'はじめの行であれば、飛ばす
    If isFirstLine Then
        isFirstLine = False
        Continue While
    End If
    '一時ファイルに書き込む
    sw.WriteLine(line)
End While
'閉じる
sr.Close()
sw.Close()

'一時ファイルと入れ替える
System.IO.File.Copy(tmpPath, filePath, True)
System.IO.File.Delete(tmpPath)
C#
コードを隠すコードを選択
//ファイルのパス
string filePath = @"C:\test\1.txt";
//ファイルを読み込みで開く
System.IO.StreamReader sr = new System.IO.StreamReader(filePath);
//一時ファイルを作成する
string tmpPath = System.IO.Path.GetTempFileName();
//一時ファイルを書き込みで開く
System.IO.StreamWriter sw = new System.IO.StreamWriter(tmpPath);

bool isFirstLine = true;
//内容を一行ずつ読み込む
while (sr.Peek() > -1)
{
    //一行読み込む
    string line = sr.ReadLine();
    //はじめの行であれば、飛ばす
    if (isFirstLine)
    {
        isFirstLine = false;
        continue;
    }
    //一時ファイルに書き込む
    sw.WriteLine(line);
}
//閉じる
sr.Close();
sw.Close();

//一時ファイルと入れ替える
System.IO.File.Copy(tmpPath, filePath, true);
System.IO.File.Delete(tmpPath);

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • このサイトで紹介されているコードの多くは、例外処理が省略されています。例外処理については、こちらをご覧ください。
  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。