質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

4回答

302閲覧

textでオプションが"r+"しか使えない

yep

総合スコア45

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/04/23 15:45

大文字を小文字にするコードで、"r+"にすると、入力した大文字の末尾に小文字が追加されて出力されてしまいます。
"r","w","a"にすると下記のエラーがでます。
"w+"はエラーは出ないものの、元のテキストの中身が削除されます。

出力後のファイルを小文字だけにしたいと考えています。

python

1import os, tkinter, tkinter.filedialog 2 3def process(): 4 root = tkinter.Tk() 5 root.withdraw() 6 fTyp = [("","*.txt")] 7 iDir = os.path.abspath(os.path.dirname(__file__)) 8 path = tkinter.filedialog.askopenfilename(filetypes = fTyp,initialdir = iDir) 9 file = open(path, "r+")#問題の部分 10 str = file.read() 11 output = str.lower() 12 file.write(output) 13 file.close() 14 print("Process Completed!")
Exception in Tkinter callback Traceback (most recent call last): File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Anaconda3_64\lib\tkinter\__init__.py", line 1702, in __call__ return self.func(*args) File "C:\Users\onvcgkjcqh\Desktop\kaki\tk_main.py", line 80, in button_nlp_0 txt_0.process() File "C:\Users\onvcgkjcqh\Desktop\kaki\fir_win\txt_0.py", line 10, in process str = file.read() io.UnsupportedOperation: not readable

OS:Windows10

もしわかる方がいらっしゃれば、
何卒、ご教授宜しくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ファイルを全部変数に読み込むののであれば、"r"で読み込んで、"w"でオープンし直して、書くのがわかりやすいです。

あるいは、"r+"でオープンして読み込んだ後、そのままlseekでポジション0(ファイル先頭)に位置づけてから書きます。今のプログラムに最小の変更で済ませるならこれですね。

投稿2019/04/23 16:34

otn

総合スコア84505

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

"r+" は読み書き両用のモードなのですが、
一旦読み込みをするとカーソル位置が移動し、書き込むのはそこからになります。

| をカーソル位置とするとこんな感じです。

open

1|TEST

read

1 TEST|

write

1 TESTtest|

まずは読み込み専用で一度読み込んだらファイルを閉じて、次に書き込み用で開き直して書き込むようにしてみてはどうでしょうか。

投稿2019/04/23 15:55

mather

総合スコア6753

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

rはファイルを読み込み専用で開くので書き込みはできません。
w+はファイルの読み書きができますが開いたときに元の内容をクリア(ファイルの長さが0になる)してしまいます。
対してr+は読み書きができますし、ファイルを開く際に元の内容を保ったままです。ただしread/writeをする位置はtellで示される「現在位置」から行われます。

これらr+, r, w+, w等のモードの意味はリファレンスを見ると書いてあります。

https://docs.python.org/ja/3.7/library/functions.html#open

さてr+モードですが例えばファイルを一行読み込むと現在位置は読み込んだ行の直後の文字になります。ファイルを全て読み込めば当然現在位置はファイルの最終位置(最後の文字の次)を指すので、そのままwriteすればファイルの末尾に追加されます。

ファイルの長さを変えず内容だけを変更するならr+で開き、read/writeの開始位置に注意しながら必要に応じてseekで現在位置を変更すればお望みのことができます。

example.txt

Python

1with open('temp.txt', 'r+') as f: 2 pos = f.tell() 3 line = f.readline() # 1行ずつ読む 4 if not line: 5 break 6 f.seek(pos) 7 f.write(line.lower()) 8 9# ファイルが小さいなら 10 11with open('temp.txt', 'r+') as f: 12 text = f.read() # 全部読む 13 f.seek(0) # 先頭位置へ移動 14 f.write(text.lower())

bash

1$ cat temp.txt 2ABC 3DEF 4GHI 5$ python3 example.py 6$ cat temp.txt 7abc 8def 9ghi 10$

しかしながらこれを行うのは「ファイル上のバイト列の長さを絶対に変更しない」といった確信がないと危険です。本件のように大文字を小文字に変換するだけなら比較的安全とは思いますが・・・

例えばもしLinuxで改行文字が'\r\n'となっているようなテキストをこのような方法で変換しようとすると'\r'が捨てられその分だけ各行のバイト数が小さくなることでしょう。それに気づかずそのままcloseすると結果のファイルの末尾にごみデータが残り次回のreadの際にエラーが起きる可能性が出てきます。そうならないためには最後の書き込みの後に現在位置以降を(trancateで)消す必要があります。

こうした読み込みと書き込みのバイト数が変わるようなケースでは途中でI/Oエラーが起きたり誤ってプログラムを強制終了したときやっかいな問題を引き起こします。ぶっちゃけそのような事態になったらバックアップから元のファイルを復元した方が早いでしょう。変更中のファイルは最早正しいテキストファイルにはなってないかも知れないからです。

r+による更新方式にはこうした思わぬ落とし穴が潜んでいると思います。

こういう微妙な問題はy_waiwaiさん他の方の回答にあるように「一旦rモードで全部読み、別の一時ファイルへwモードで書き込み、最後に一時ファイルを元のファイルへリネーム」という方法を用いればほとんど避けて通れるようになります。起こり得る様々な問題を想定するのは結構難しいのでそうした安全確実な方法を取った方がよいかも知れません。

このプログラムが単なるツールであり「失敗しても自分で何とかできる」ならr+で一発更新なんてことをやってみるのもよいかと思います。

投稿2019/04/23 16:55

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yep

2019/04/24 03:02

結局、otnさんの"r"で読み込んで、"w"で書く方法になりました。 with open(path, "r") as file: str = file.read() output = str.lower() with open(path, "w", encoding="utf-8") as file: file.write(output) file.close() r+には注意が必要ということを知れたのでベストアンサーにさせていただきました。
guest

0

ファイルの内容をそのまま書き換えることはできないので、一旦別のファイル名でファイルを作り、書き換えたデータで書き込み後、元ファイルを削除して作成したファイルを元ファイルの名前にリネームするようにしましょう

あるいは、ファイルがそんなに大きくなければ、ファイルの中身を全部読み出し、データを変換後、新規でファイルを作り直し、そっくりデータを書き込む、ってことですね

投稿2019/04/23 15:49

編集2019/04/23 15:52
y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問