Pythonでのファイルの読み込みや書き込み、作成、圧縮や展開方法を徹底理解!(初心者にもわかりやすく)【Python入門・応用20】

こんにちは、キノコードです。
この動画では、Pythonでのファイル操作について説明します。
Pythonでは、ファイルに文字を書き込んだり、書き込まれたファイルを読み込んだりすることができます。

ファイルの種類

まず、ファイルの種類について説明します。
ファイルには大きく分けてテキストファイルとバイナリファイルの2種類あります。
テキストファイルは、人間が理解できるように文字コードを使って、文字で出力できるファイルです。
メモ帳などのテキストエディタを使って正しく表示できるものをテキストファイルと言います。
一方、バイナリファイルは、コンピューターが理解できるようにデータを0と1で表したファイルです。
バイナリファイルは人間には理解できず、文字で出力できません。
画像データや音声データなど、テキストエディタで正しく表示できないものは全てバイナリファイルです。
なお、テキストファイルもコンピューター内部では0と1に変換されているのでバイナリファイルの一部ですが、ここでは区別します。
今回はこのテキストファイルを扱います。

ファイルの作成、書き込み

まず、ファイルの作成、書き込みについて説明します。
open関数を使うと、ファイルの作成や書き込みができます。
確認してみましょう。

f = open("test.txt", "w")
f.write("test")
f.close()

まず、open関数を使ってファイルを作成し、変数fに代入します。
第一引数にファイル名、第二引数にモードを渡します。
今回はファイル名をtest.txtとします。
また、ファイルを作成したいので第二引数のモードは"w"を渡します。
"w"はwriteモードを表し、新しくファイルを作成することができます。
なお、ファイルが既に存在していれば上書きします。
次に作成したファイルのwriteメソッドを使って、テキストを書き込みます。
今回は「test」と書き込みます。
最後にcloseメソッドを使って、ファイルの作成を完了します。
それでは、ファイルを作成してみましょう。
実行します。

test.txtが作成されました。
中身を確認してみましょう。
「test」と書き込まれています。

with open("test.txt", "w") as f:
    f.write("overwrite")

また、open関数をwith文と一緒に使うと、最後にcloseメソッドを書く必要がなくなります。
まずwithを書き、その後に先ほどと同様にopen関数を書きます。
その後にas、変数名、:(コロン)を書きます。
今回は変数名をfとします。
こうすると作成したいファイルを変数fで扱うことができます。
インデントを下げて、次の行で変数fのwriteメソッドを使ってテキストを書き込みます。
今度は既にtest.txtは存在するので、上書きされることになります。
そのため、今回は「overwrite」と書き込みます。
それでは、ファイルに書き込んでみましょう。
実行します。

test.txtの中身を確認してみましょう。
「overwrite」と書き込まれ、test.txtの中身が上書きされています。
このように、with文を使ってファイル操作をするとcloseメソッドを書き忘れる心配がありません。
積極的にwith文を使っていきましょう。

text = '''\
apple
grape
orange
banana
'''

with open("test2.txt", "w") as f:
    f.write(text)

また、トリプルクォートを使うと、改行を含むテキストをそのまま書き込むことができます。
トリプルクォートを使ってapple、grape、orange、bananaを改行して書き、変数textに代入します。
最初のトリプルクォートの直後にそのまま改行すると、改行も文字列として扱われてしまうので、バックスラッシュを書きます。
そしてwith文とopen関数を使ってファイルに書き込みます。
今度はファイル名をtest2.txtとします。
test2.txtというファイルは存在しないので、新しく作成されます。
そして、writeメソッドの引数に変数textを渡しましょう。
実行します。

test2.txtが作成されました。
中身を確認してみましょう。
変数textに代入した文字列がそのまま書き込まれています。

with open("test2.txt", "a") as f:
    f.write("peach\n")

open関数の第二引数のモードに"w"を渡すと、ファイルが上書きされました。
第二引数のモードに"a"を渡すと、ファイルの末尾にテキストを追加することができます。
"a"はappendモードを表し、リストにおけるappendメソッドと似ています。
なお、ファイルが存在しない場合は新しくファイルが作成されます。
open関数の第一引数に先ほど作成したtest2.txtを渡し、第二引数には"a"を渡します。
そして、writeメソッドを使ってpeachと改行を表す(バックスラッシュ)nを書き込んでみましょう。
実行します。

test2.txtの中身を確認してみましょう。
末尾にpeachが追加され、改行されています。

ファイルの読み込み

次に、ファイルの読み込みについて説明します。
ファイルの書き込みと同じように、with文とopen関数を使うとファイルの読み込みもできます。
確認してみましょう。

with open("test2.txt", "r") as f:
    print(f.read())

with文とopen関数を書き、第一引数に読み込みたいファイル名、第二引数に"r"を渡します。
今回は先ほど作成したtest2.txtを読み込みます。
また、"r"はreadモードを表し、ファイルを読み込むことができます。
なお、存在しないファイル名を指定した場合はエラーになります。
次に、変数fのreadメソッドを使って、テキストを読み込みます。
そして、print関数で読み込んだテキストを表示してみましょう。
実行します。

test2.txtの中身が表示されました。
正しくファイルを読み込めています。

with open("test2.txt", "r") as f:
    print(f.readline())

readメソッドを使うと、一度に全てのテキストを読み込むことができました。
readlineメソッドを使うと、テキストを1行ずつ読み込むことができます。
先ほど使用したreadメソッドをreadlineメソッドに変えてみます。
実行します。

appleと表示されました。
test2.txtの最初の1行だけを読み込めています。

with open("test2.txt", "r") as f:
    for i in range(3):
        print(f.readline(), end="")

for文と一緒に使うと、任意の行数のテキストを読み込むことができます。
print関数で表示する前に、for文を追加します。
今回は繰り返す回数を3回とします。
その後にprint関数で読み込んだテキストを表示します。
また、元々のテキストの各行には改行が含まれているので、print関数では改行しないように引数endには空の文字列を渡しましょう。
実行します。

apple、grape、orangeが表示されました。
test2.txtの最初の3行を読み込めています。

ファイルの読み込み書き込み

次に、ファイルの読み込み書き込みモードについて説明します。
open関数の第二引数のモードに"w"や"a"を渡すとファイルの書き込み、"r"を渡すとファイルの読み込みができることを説明しました。
"w+"、"a+"、"r+"を渡すと、読み込みと書き込みの両方ができます。
それぞれ少しずつ動作が異なるので、一つずつ説明していきます。

with open("test2.txt", "r+") as f:
    print(f.read())
    f.write("melon\n")

まず"r+"のモードから説明します。
"r+"はファイルの読み込みに加えて、書き込みもできるようになるモードです。
基本は読み込みモードなので、存在しないファイル名を指定するとエラーになります。
open関数を使って、先ほど作成したtest2.txtを読み込みます。
第二引数のモードは"r+"を渡します。
次にreadメソッドを使って、テキストを読み込み、print関数で表示します。
そして、その後にwriteメソッドを使ってmelonと改行を表す(バックスラッシュ)nを書き込んでみましょう。
実行します。

apple、grape、orange、banana、peachと表示されました。
これはreadメソッドで読み込んだテキストの中身です。
test2.txtの中身を確認してみましょう。
最後の行にmelonが追加されています。
readメソッドでpeachまで読み込み、その後にwriteメソッドでmelonと書き込んでいるので、このような結果になります。

with open("test2.txt", "r+") as f:
    f.write("melon\n")

今度はreadメソッドを使わずに、writeメソッドだけでmelonと(バックスラッシュ)nを書き込んでみましょう。
実行します。

test2.txtの中身を確認してみましょう。
1行目のappleがmelonに置き換わっています。
readメソッドを使わなかったので、テキストの最初から書き込みが始まり、このような結果になっています。

with open("test2.txt", "r+") as f:
    f.seek(6)
    f.write("melon\n")

テキストの途中から書き込みたい場合はseekメソッドを使います。
seekメソッドの引数にテキストの先頭からの位置を渡すと、その位置まで移動できます。
このとき、スペースや改行も一文字として数えます。
今回は2行目のgrapeをmelonで上書きしてみます。
2行目の始まりは改行も含めると先頭から6文字目なので、seekメソッドの引数に6を渡します。
そして、writeメソッドでmelonと(バックスラッシュ)nを書き込んでみましょう。
実行します。

test2.txtの中身を確認してみましょう。
2行目のgrapeがmelonに置き換わっています。
このように、seekメソッドを使うと目的の位置からテキストの操作ができます。

text = '''\
apple
grape
orange
banana
'''

with open("test3.txt", "w+") as f:
    f.write(text)
    print(f.read())

次は"w+"のモードについて説明します。
"w+"はファイルの書き込みに加えて、読み込みもできるようになるモードです。
基本は書き込みモードなので、ファイルが存在しない場合は新たに作成し、ファイルが存在する場合は上書きされます。
新たに、トリプルクォートを使ってapple、grape、orange、bananaを改行して書き、変数textに代入します。
次に、open関数を使って、新たにtest3.txtを作成します。
第二引数のモードは"w+"を渡します。
次に、writeメソッドの引数に変数textを渡します。
そして、readメソッドでテキストを読み込み、読み込んだテキストをprint関数で表示してみましょう。
実行します。

print関数では何も表示されていません。
しかし、test3.txtは作成できました。
中身を確認してみましょう。
変数textに代入した文字列が書き込まれています。
writeメソッドでテキストを書き込んだ後は、テキストの末尾に移動しています。
その後ろには何も書かれていないので、readメソッドでは何も読み込んでいません。
従って、print関数でも何も表示されない、ということになります。

text = '''\
apple
grape
orange
banana
'''

with open("test3.txt", "w+") as f:
    f.write(text)
    f.seek(0)
    print(f.read())

書き込んだテキストを読み込むためには、テキストの先頭に戻る必要があります。
そこで、先ほどの"r+"モードの時にも使用したseekメソッドを使います。
writeメソッドでテキストを書き込んだ後、seekメソッドの引数に0を渡してテキストの先頭に戻ります。
その後にreadメソッドでテキストを読み込んでみましょう。
実行します。

テキストの文字列が表示されました。

with open("test3.txt", "a+") as f:
    f.write("peach\n")
    f.seek(0)
    print(f.read())

最後に"a+"のモードについて説明します。
"a+"はファイルの末尾にテキストを追加でき、読み込みもできるようになるモードです。
open関数を使って、先ほど作成したtest3.txtを開きます。
第二引数のモードは"a+"を渡します。
次に、writeメソッドでpeachと(バックスラッシュ)nを書き込みます。
次に、seekメソッドでテキストの先頭に戻ります。
そして、readメソッドでテキストを読み込み、print関数で表示してみましょう。
実行します。

apple、grape、orange、banana、peachと表示されました。
test3.txtの中身を確認してみましょう。
こちらも末尾にpeachが追加されています。

csvファイルの作成、書き込み、読み込み

次に、csvファイルの操作について説明します。
csvファイルは複数のデータをカンマで区切りで保存したテキストファイルです。
テキストファイルなので、先ほどと同様に扱うことができますが、カンマが入っているので少し処理が複雑になります。
そこで、csvという標準ライブラリを使うと、簡単にcsvファイルを操作できます。
コードを書いて確認してみましょう。

import csv

with open("test.csv", "w") as f:
    writer = csv.writer(f)
    writer.writerow(["Yamada", 180, 70])

まず、csvファイルを作成し、書き込んでみましょう。
今回は、名前、身長、体重のデータが入ったcsvファイルを作成します。
最初に、Pythonの標準ライブラリであるcsvをインポートします。
次に、with文とopen関数を使って、今までと同じ方法でcsvファイルを作成します。
ファイル名はtest.csvとし、モードは"w"を渡します。
次に、csvのwriter関数の引数にfを渡し、変数writerに代入します。
writer関数によって、ファイルに書き込むためのwriterオブジェクトが作成されます。
そして、この変数writerのwriterowメソッドを使って、ファイルに書き込みます。
書き込む内容はリストを使って、Yamada、180、70とします。
このリストをwriterowメソッドの引数に渡し、結果を確認してみましょう。
実行します。

test.csvが作成されました。
中身を確認してみましょう。
リストの内容が書き込まれています。

import csv

with open("test.csv", 'a') as f:
    writer = csv.writer(f)
    writer.writerows([["Sato", 160, 50], ["Suzuki", 170, 60],
                      ["Takahashi", 190, 90], ["Yamaguchi", 150, 40]])

writerowメソッドは1行しか書き込むことができません。
writerowsメソッドを使うと、複数行書き込むことができます。
writerowsメソッドを使って、さらに4人のデータを追加してみましょう。
open関数の第一引数に先ほど作成したtest.csvを渡します。
データを追加したいので、第二引数のモードは"a"を渡します。
次に、csvのwriter関数の引数にfを渡し、変数writerに代入します。
そして、writerowsメソッドを使って、ファイルに書き込みます。
引数はリストの中にリストを書き、2次元配列のような形式で渡します。
Satoさん、Suzukiさん、Takahashiさん、Yamaguchiさんの身長と体重のデータを追加してみましょう。
実行します。

test.csvの中身を確認してみましょう。
4人のデータが追加されています。

import csv

with open('test.csv', 'r') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

次に、csvファイルを読み込みます。
先ほど作成したtest.csvを読み込んでみましょう。
open関数の第一引数にtest.csvを渡し、第二引数のモードは"r"を渡します。
次に、csvのreader関数の引数にfを渡し、変数readerに代入します。
reader関数によって、ファイルを読み込むためのreaderオブジェクトが作成されます。
このreaderオブジェクトの中身は、1行ずつfor文で取り出すことができます。
for、row、in、reader、:(コロン)と書き、readerオブジェクトの中身を1行ずつ取り出し、print関数で表示してみましょう。
実行します。

test.csvの中身が1行ずつリストで表示されました。

import csv

with open('test.csv', 'r') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row[0])

また、1行ずつリストで取り出されるので、インデックスを指定することで各行の要素を取得できます。
取り出した各行のデータの0番目のインデックスを指定し、名前だけを表示してみましょう。
実行します。

名前だけが表示されました。

ファイルの圧縮、展開

最後に、ファイルの圧縮、展開について説明します。
ファイルの圧縮とは、複数のフォルダやファイルを一つのフォルダにまとめて、容量を軽くすることです。
複数のデータや、大容量のデータをやりとりするときに使われます。
ファイルの展開とは、圧縮されたファイルを元に戻すことです。
ファイルの解凍とも言います。
圧縮ファイルは様々な形式がありますが、今回はzipファイルを扱います。
コードを書いて確認してみましょう。

import zipfile

with zipfile.ZipFile("test.zip", "w") as zf:
    zf.write("test.txt")
    zf.write("test.csv")

まず、zipファイルを作成しましょう。
最初に、Pythonの標準ライブラリであるzipfileをインポートします。
次に、with文を書きます。
その次はopen関数ではなく、zipfileモジュールのZipFileインスタンスを作成します。
第一引数にzipファイル名、第二引数にモードを渡します。
今回はtest.zipという名前にし、新しくファイルを作成するのでモードは"w"を渡します。
zipファイルなので、変数名はzfとします。
そして、writeメソッドの引数に圧縮したいファイルを渡します。
今回はtest.txtとtest.csvを圧縮しましょう。
実行します。

test.zipが作成されました。
中身を確認してみましょう。
macをお使いの方はFinder、windowsをお使いの方はエクスプローラーから現在のフォルダを開き、test.zipをダブルクリックするとzipファイルを展開できます。
zipファイルを展開すると、test.txtとtest.csvが入っていることを確認できました。
ただし、このzipファイルは複数のファイルがまとめられただけで、容量は圧縮されていません。

import zipfile

with zipfile.ZipFile("test2.zip", "w",
                      compression=zipfile.ZIP_DEFLATED,
                      compresslevel=9) as zf:
    zf.write("test.txt")
    zf.write("test.csv")

ZipFileインスタンスの引数compressionに圧縮方式を指定すると、指定した圧縮方式でファイルを圧縮できます。
現在、この圧縮方式にはZIP_STORED, ZIP_DEFLATED, ZIP_BZIP2、ZIP_LZMAの4つがあります。
このうち、ZIP_STOREDは複数のファイルを一つにまとめるだけで、容量は圧縮されません。
デフォルトではこのZIP_STOREDが指定されています。
さらに、ZIP_DEFLATEDとZIP_BZIP2は引数compresslevelに圧縮レベルを指定できます。
圧縮レベルは1から9の間で指定でき、数値が大きいほど圧縮スピードは遅くなりますが、圧縮レベルは高くなります。
確認してみましょう。
先ほどと同様に、ZipFileインスタンスを作成します。
zipファイル名はtest2.zipとします。
そして、引数compressionにzipfileモジュールのZIP_DEFLATEDを渡します。
また、引数compresslevelに9を渡し、圧縮レベルを最大にします。
そして、先ほどと同様にtest.txtとtest.csvを圧縮しましょう。
実行します。

test2.zipが作成されました。
先ほど作成したtest.zipと容量を比べてみましょう。
test.zipよりもtest2.zipの方が少しだけ容量が小さくなっていることが確認できます。

import zipfile

with zipfile.ZipFile("test2.zip", "a",
                      compression=zipfile.ZIP_DEFLATED,
                      compresslevel=9) as zf:
    zf.write("test2.txt")

また、ZipFileインスタンスの第二引数のモードに"a"を指定すると、作成済みのzipファイルにファイルを追加できます。
先ほど作成したtest2.zipの中に、test2.txtを追加してみましょう。
実行します。

test2.zipの中身を確認してみましょう。
test2.txtが追加されています。

import zipfile

with zipfile.ZipFile('test2.zip', "r") as zf:
    zf.extractall("sample")

最後に、zipファイルの展開について説明します。
Finderやエクスプローラー上でダブルクリックするとzipファイルを展開できますが、Python上でもzipファイルを展開できます。
ZipFileインスタンスの第二引数のモードに"r"を渡し、zipファイルを読み込みます。
次に、extractallメソッドを使って、zipファイルの中身を全て展開します。
引数に展開したファイルを保存するフォルダ名を渡します。
今回はsampleというフォルダ名にしましょう。
実行します。

sampleというフォルダが作成されました。
中身を確認してみましょう。
test2.zipに入っていた、test.csv、test.txt、test2.txtが展開されて保存されたことがわかります。