テキストファイルを扱う

 .NET Frameworkを使ったテキストファイルの扱い方についてを説明していきます。

テキストファイルを読み込む

 .NET Frameworkでファイルを扱うにはSystem.IOの中のクラスを使うのですが、BinaryReader、TextReader、StringReader、StreamReaderやFileなど同じようなことができそうなクラスがいっぱいあります。中には抽象基本クラスというものもあって、C++の知識がないとあれ?と思うものもあります。じゃあ全部覚える必要があるかというと、そんなことはありません。とりあえずいくつかの方法を試してみましょう。

System.IO.File.ReadAllLinesを使う
 簡単にスクリプトを組む人なら、まず次の使い方をお勧めします。

from System.IO import File

filename = raw_input('ファイル名を入力してください:')

lines = File.ReadAllLines(filename) ←ここで読み込んでます。

print filename + 'の中身は次の以下の通りです。'
for line in lines:
  print line

raw_input()

出力画面:
 ファイル名を入力してください:tuple.py ←例えば"tuple.py"の場合
 tuple.pyの中身は次の以下の通りです。
 #coding: shift-jis
 
 print tuple('ABCDE')
 print tuple(['a','b','c'])
 print tuple((1,2,3))
 
 raw_input()
 File.ReadAllLines()はテキスト ファイルを開き、ファイルのすべての行を文字列配列に読み取った後、ファイルを閉じます。  ファイルを開けたり、閉じたりを記述しなくていいんです。またファイル一気に読み、メモリに溜めますが大抵のテキストファイルの容量であれば、問題は起こしません(2ギガを超えると大変かな)。後はfor文を使って、各行について処理を行えば完了です。簡単ですね。

でも次の場合もあります。
出力画面:
 ファイル名を入力してください:hello.py ←例えば"hello.py"の場合
 hello.pyの中身は次の以下の通りです。
 # coding: shift-jis
 
 print u"?????????O???????????????B"
 name = raw_input()
 print "Hello, "+ name + "!"
 raw_input()
 なんだ、この?????はと思いますよね。これは日本語コードの問題です。.NET Frameworkでは通常"UTF-8"を使いますが、今回のコードは"shift-jis"ですよね。この問題を解決するためにSystem.TextのEncodingクラスを使います。使い方は次の通りです。

from System.IO import File
from System.Text import Encoding

filename = raw_input('ファイル名を入力してください:')

lines = File.ReadAllLines(filename, Encoding.GetEncoding("shift-jis"))
                     ↑ここがポイント
print filename + 'の中身は次の以下の通りです。'
for line in lines:
  print line

raw_input()

出力画面:
 ファイル名を入力してください:hello.py ←例えば"hello.py"の場合
 hello.pyの中身は次の以下の通りです。
 # coding: shift-jis
 
 print u"あなたの名前を教えてください。"
 name = raw_input()
 print "Hello, "+ name + "!"
 raw_input()

System.IO.StreamReaderクラスを使う
 Fileクラスでは1行で行ったことを数行に分けています。但しメモリの消費は少ないです。

from System.IO import StreamReader
from System.Text import Encoding

filename = raw_input('ファイル名を入力してください:')

file = StreamReader(filename, Encoding.GetEncoding("shift-jis"))

print filename + 'の中身は次の以下の通りです。'
while not file.EndOfStream: ←fileが終わるまで繰り返します。
  print file.ReadLine()

file.Close()

raw_input()

出力画面:
 ファイル名を入力してください:hello.py ←例えば"hello.py"の場合
 hello.pyの中身は次の以下の通りです。
 # coding: shift-jis
 
 print u"あなたの名前を教えてください。"
 name = raw_input()
 print "Hello, "+ name + "!"
 raw_input()

テキストファイルを書き込む

System.IO.File.WriteAllLinesを使う
 ReadAllLinesがファイルの内容を文字列配列にファイルの落としたように、今度は文字列配列をファイルに書き込む形を取ります。但しファイルが既存していた場合の細かな対応を指定できません。全て上書きされます。ファイルが既存していた場合の細かい指定は、後で説明するStreamWriterを使います。
 例を見てみましょう。

from System.IO import File
from System.Text import Encoding

filename = "test.txt"

lines = ["テストテスト","本日は晴天なり、本日は晴天なり"]

File.WriteAllLines(filename,lines, Encoding.GetEncoding("utf-8"))
    ↑今回のポイントの部分です。

lines2 = File.ReadAllLines(filename)
for line in lines2:
  print line

raw_input()

出力画面:
 テストテスト
 本日は晴天なり、本日は晴天なり
File.WriteAllLines(filename,lines, Encoding.GetEncoding("utf-8"))
上記のスクリプトではEncodingを指定しています。Defaultのままでもいいんですが、Encodingを指定してやるとファイルの一番最初に、"utf-8"のファイルである印を付けて保存されます。ソフトのよってはその印でファイルのEncodingをチェックしているものもあるので、行儀よい書き方としてEncodingを指定する書き方をお勧めします。

System.IO.StreamWriterクラスを使う
 では今度はStreamWriterを使ってみましょう。

from System.IO import *
from System.Text import Encoding

filename = "test.txt"
file = StreamWriter(filename, True, Encoding.GetEncoding("utf-8"))
      ↑今回のポイント
file.WriteLine("明日は雨天なり、明日は雨天なり")
file.Close()

lines2 = File.ReadAllLines(filename)
for line in lines2:
print line

raw_input()

出力画面:
 テストテスト
本日は晴天なり、本日は晴天なり
明日は雨天なり、明日は雨天なり
 上記の出力画面はFile.WriteAllLinesの例の続きで行ったので、"明日は雨天なり、本日は雨天なり"という文字列が追記されてた形になっています。

StreamWriter(filename, True, Encoding.GetEncoding("utf-8"))
 今回のポイントは上記スクリプトです。2番目の引数がTrueのbool値になっています。
データをファイルの末尾に追加するかどうかを判断します。ファイルが存在し、False の場合は、ファイルが上書きされます。ファイルが存在し、True の場合は、データがファイルの末尾に追加されます。それ以外の場合は、新しいファイルが作成されます。

 もっと複雑な処理ができますが、取り合えずこれだけ触れていれば十分ではないでしょうか。