[解決!Python]テキストファイルの読み書きまとめ:解決!Python
テキストファイルに対する読み込みと書き込み、テキストファイルを読み書き両用でオープンする方法、エンコーディングの指定や検出の方法を1ページにまとめて紹介する。
テキストファイルの読み書きまとめ
ここでは本連載でこれまでに紹介してきたテキストファイルの読み書きの方法をまとめる。詳しい解説はコード例の後で紹介しているリンクを参照してほしい。
テキストファイルの読み込み
# test.txtファイルの内容
#atmark IT
#
#deep insider
# ファイルをオープンして、1行ずつその内容を読み込んで処理する
with open('test.txt') as f:
for line in f:
line = line.rstrip() # 読み込んだ行の末尾には改行文字があるので削除
print(line)
# 出力結果(4行目に空行が表示されるときとされないときがあるのを除き、以下同じ)
#atmark IT
#
#deep insider
# テキストファイルをオープンして、その内容を全て読み込み、クローズする
f = open('test.txt') # f = open('test.txt', 'rt'):
s = f.read() # ファイルの全内容が1つの文字列として返される
print(s)
f.close()
# with文と組み合わせると使い終わったとき(ブロック終了時)や
# 例外が発生したときにファイルが自動的にクローズされる
with open('test.txt') as f:
s = f.read()
print(s)
# pathlibモジュールのPath.read_textメソッドを使う
from pathlib import Path
p = Path('test.txt') # s = Path('test.txt').read_text()
s = p.read_text() # ファイルのオープン、読み込み、クローズをまとめて実行
print(s)
# 改行を区切り文字として文字列を分割し、リストに格納
sl = s.split('\n')
print(sl) # ['atmark IT', '', 'deep insider', '']
for line in sl:
print(line)
# readlineメソッドを使ってテキストファイルから1行ずつ内容を読み込む
with open('test.txt') as f:
line = f.readline()
while line:
line = line.rstrip()
print(line)
line = f.readline()
# Python 3.8以降なら代入式を使ってシンプルに書ける
with open('test.txt') as f:
while line := f.readline():
line = line.rstrip()
print(line)
# テキストファイルの内容をリストに読み込む
with open('test.txt') as f:
sl = f.readlines()
print(sl) # ['atmark IT\n', '\n', 'deep insider\n']
# readlinesメソッドを使って各行を順次処理するループを形成
with open('test.txt') as f:
for line in f.readlines():
line = line.rstrip()
print(line)
テキストファイルの読み込みについては「テキストファイルを読み込むには」を参照のこと。
テキストファイルへの書き込み
# ファイルを書き込み用にオープンして、ファイル先頭から文字列を書き込む
with open('test.txt', 'w') as f: # 「with open('test.txt', 'wt') as f:」と同じ
f.write('this is a test.\n') # 改行したければ改行文字を最後に付加
sl = ['atmark IT\n', 'deep insider\n']
f.writelines(sl) # 文字列リストはwritelinesメソッドで書き込む
x = 1
f.write(str(x) + '\n') # テキストファイルに書き込めるのは文字列のみ
# 上で作成した内容の確認
from pathlib import Path
print(Path('test.txt').read_text(), end='')
# 出力結果:
#this is a test.
#atmark IT
#deep insider
#1
# with文を使わない場合
f = open('test.txt', 'w')
f.write('this is a test.\n') # 戻り値は書き込んだ文字数
f.close()
# pathlibモジュールのPathクラスが提供するwrite_textメソッドを使用
p = Path('test.txt')
p.write_text('foo\nbar\nbaz\n')
print(p.read_text(), end='')
# 出力結果:
#foo
#bar
#baz
# ファイルを追記
with open('test.txt', 'a') as f:
f.write('deep insider\n')
print(Path('test.txt').read_text(), end='')
# 出力結果:
#foo
#bar
#baz
#deep insider
# ファイルを排他的に作成してオープン
with open('test.txt', 'x') as f: # 既に存在しているのでFileExistsError例外
pass
with open('test2.txt', 'x') as f:
f.write('absolutely a new line!\n')
print(Path('test2.txt').read_text(), end='') # absolutely a new line!
テキストファイルへの読み込みについては「テキストファイルに書き込むには」を参照のこと。
テキストファイルを読み書き両用でオープン
with open('test.txt', 'w+') as f: # ファイルを読み書き両用でオープン
f.write('deep insider\n') # ファイル先頭から書き込み
f.seek(0) # ファイル先頭にファイルポインタを移動
print(f.read(), end='') # deep insider:ファイル先頭から読み込んで表示
with open('test.txt', 'r+') as f: # 内容を削除せずに読み書き両用でオープン
f.write('atmark IT') # ファイル先頭から書き込み(上書き)
f.seek(0) # ファイル先頭にファイルポインタを移動
print(f.read(), end='') # atmark ITder:ファイル先頭から読み込んで表示
with open('test.txt', 'a+') as f:
f.write('python\n') # ファイル末尾に書き込み
f.seek(0) # ファイル先頭にファイルポインタを移動
print(f.read(), end='') # ファイル先頭から読み込んで表示
# 出力結果:
#atmark ITder
#python
with open('test.txt', 'x+') as f: # FileExistsError例外
pass
with open('moretest.txt', 'x+') as f: # OK
f.write('atmark IT\ndeep insider\n') # ファイル先頭から書き込み
f.seek(0) # ファイル先頭にファイルポインタを移動
print(f.read(), end='') # ファイル先頭から読み込んで表示
# 出力結果:
#atmark IT
#deep insider
モード | 概要 | ファイルの内容 | ファイルポインタ |
---|---|---|---|
r+ | ファイルを読み書き両用でオープンする。 指定した名前のファイルがなければFileNotFoundError例外が発生する |
以前のファイルの内容を削除しない | ファイル先頭 |
w+ | ファイルを読み書き両用でオープンまたは新規作成する | 以前のファイルの内容を削除する | ファイル先頭 |
a+ | ファイルを読み書き両用でオープンまたは新規作成する | 以前のファイルの内容を削除しない | ファイル末尾 |
x+ | ファイルを読み書き両用で排他的に新規に作成する | 新規に作成 | ファイル先頭 |
open関数のモードに'+'を付加した場合の振る舞い |
テキストファイルを読み書き両用でオープンする方法については「テキストファイルを読み書き両用にオープンするには」を参照のこと。
エンコーディングを指定して、シフトJISなどのファイルを読み書きする
# シフトJISエンコードのテキストファイルの読み込み
# sjis.txtの内容:このファイルはシフトJISでエンコードされています
with open('sjis.txt', encoding='shift_jis') as f:
s = f.read()
print(s.rstrip()) # このファイルはシフトJISでエンコードされています
# UTF8エンコードのテキストファイルの読み込み
# utf8.txtの内容:このファイルはUTF-8でエンコードされています
with open('utf8.txt', encoding='utf-8') as f:
s = f.read()
print(s.rstrip()) # このファイルはUTF-8でエンコードされています
# バイナリファイルとして読み込んだ後にエンコーディングを指定してデコード
with open('sjis.txt', 'rb') as f:
b = f.read()
s = b.decode('shift_jis')
print(s.rstrip()) # このファイルはシフトJISでエンコードされています
# シフトJISエンコードでテキストファイルに書き込み
with open('sjis-2.txt', 'w', encoding='shift_jis') as f:
f.write('このファイルもシフトJISでエンコードされています\n')
with open('sjis-2.txt', encoding='shift_jis') as f:
print(f.read().rstrip())
# UTF-8エンコードでテキストファイルに書き込み
with open('utf8-2.txt', 'w', encoding='utf-8') as f:
f.write('このファイルもUTF-8でエンコードされています\n')
with open('utf8-2.txt', encoding='utf-8') as f:
print(f.read().rstrip())
エンコーディングの指定については「エンコーディングを指定して、シフトJISなどのファイルを読み書きするには」を参照のこと。
テキストファイルのエンコーディングを調べて、その内容を読み込む
# chardetによるエンコーディングの判定とテキストデータのデコード
# sjis.txtの内容:このファイルはシフトJISでエンコードされています
from chardet import detect # 「pip install chardet」などでインストールしておく
with open('sjis.txt', 'rb') as f: # バイナリファイルとしてファイルをオープン
b = f.read() # ファイルの内容を全て読み込む
print(b) # b'\x82\xb1\x82\xcc\x83t\x83@\x83C……\x82\xdc\x82\xb7\r\n'
enc = detect(b) # chardet.detect関数を使ってエンコーディングを判定
print(enc)
# 出力結果:
# {'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}
# 得られたエンコーディング情報を使ってファイルをオープンし直す
with open('sjis.txt', encoding=enc['encoding']) as f:
s = f.read()
print(repr(s)) # 'このファイルはシフトJISでエンコードされています\n'
# もしくは得られたエンコーディング情報を使ってバイト列をデコード
s = b.decode(encoding=enc['encoding'])
print(repr(s)) # 'このファイルはシフトJISでエンコードされています\r\n'
# ファイルサイズが大きい場合
from chardet.universaldetector import UniversalDetector
with open('sjis.txt', 'rb') as f: # ファイルをバイナリファイルとしてオープン
detector = UniversalDetector() # UniversalDetectorオブジェクトを生成
for line in f: # 行末(\n)またはEOFまでを読み込みながら、以下を繰り返す
detector.feed(line) # 読み込んだデータをfeedメソッドに渡す
if detector.done: # 判定できたらdone属性がTrueになるのでループを終了
break
detector.close() # ループ終了時にUniversalDetectorオブジェクトをクローズ
print(detector.result)
# 出力結果:
# {'encoding': 'SHIFT_JIS', 'confidence': 0.99, 'language': 'Japanese'}
# UniversalDetectorオブジェクトもまとめてwith文で取り扱う
from chardet.universaldetector import UniversalDetector
from contextlib import closing
with open('sjis.txt', 'rb') as f, closing(UniversalDetector()) as detector:
for line in f:
detector.feed(line)
if detector.done:
break
print(detector.result) # 結果を出力
エンコーディングの検出と、それを利用したファイルの読み込みについては「テキストファイルのエンコーディングを調べて、その内容を読み込むには(chardetパッケージ)」を参照のこと。
Copyright© Digital Advantage Corp. All Rights Reserved.