Python中的文件


目標:

  • 文件的概念
  • 文件的基本操作
  • 文件/文件夾的常用操作
  • 文本文件的編碼方式

1.文件的概念

1.1文件的概念和作用

  • 計算機的文件,就是存儲在某種長期存儲設備上的一段數據
  • 長期存儲設備包括:硬盤、U盤、移動硬盤、光盤····

  文件的作用:

  將數據長期存儲下來,在需要的時候使用

  

1.2文件的存儲方式

  • 在計算機中,文件是以 二進制 的方式保存在磁盤上的

  文本文件和二進制文件

  • 文本文件
    • 可以用 文本編輯軟件查看
    • 本質上還是二進制
    • 例如:Python源文件
  • 二進制文件
    • 保存的內容不是給人直接閱讀的,而是提供給其他軟件使用的 
    • 例如:圖片文件、音頻文件、視頻文件等等
    • 二進制文件不能直接使用文本編輯器查看

2.文件的基本操作

2.1操作文件的套路

  在計算機中,要操作文件的套路非常固定,一共包含三個步驟:

  1. 打開文件
  2. 讀、寫文件
    • 讀:將文件內容讀入內存
    • 寫:將內存內容寫入文件
  3. 關閉文件

2.2操作文件的函數/方法

  • 在Python中操作文件需要記住1個函數和3個方法
序號 函數/方法 說明
1 open 打開文件,並返回文件操作對象
2 read 將文件內容讀取到內存
3 write 將指定內容寫入到文件
4 close 關閉文件
  • open() 函數負責打開文件,並返回文件對象
  • read/write/close三個方法都需要通過文件對象來調用

 

2.3read方法——讀取文件

  • open函數的第一個參數,是被打開的文件名(文件名區分大小寫)
    • 如果文件存在,返回文件操作對象
    • 如果文件不存在,會拋出異常
  • read方法 可以一次性讀入並返回 文件的所有內容
  • close方法 負責關閉文件
    • 如果忘記關閉文件,會造成系統資源消耗,而且會影響到后續對文件的訪問
  • 注意:方法執行后,會把文件指針移動到文件的末尾
  • 提示:
    • 在開發中,通常先編寫打開和關閉的代碼,在編寫中間針對文件讀/寫操作!
  • #獲得文件操作對象(sis.txt文件)
    file = open("sis.txt")
    #讀取
    text = file.read()
    print(text)
    #關閉文件
    file.close()
    '''
    運行結果
    我是中文的哦
    nidie中文
    '''

 

  • 文件指針
    • 文件指針 標記 從那個位置開始讀取數據
    • 第一次打開文件時,通常文件指針會指向文件開始的位置
    • 當執行了read方法后,文件指針會移動到讀取內容的末尾
      • 默認情況下會移動到文件末尾
    • 思考:如果執行了一次read方法,讀取了所有內容,那么再次調用read方法還能獲取到內容嗎?
      • 答案:不能。第一次讀取內容后,文件指針移動到文件末尾,再次調用不會讀取到任何內容
      •  1 #獲得文件操作對象(sis.txt文件)
         2 file = open("sis.txt")
         3 #讀取
         4 text = file.read()
         5 #查看讀取文件的長度  (14)
         6 print(len(text))
         7 #輸出讀取到的文件
         8 print(text)
         9 print("*"*30)
        10 #重新讀取文件
        11 text = file.read()
        12 print(text)         #
        13 print(len(text))    # (0)
        14 #關閉文件
        15 file.close()
        16 
        17 """
        18 運行結果:
        19 14
        20 我是中文的哦
        21 nidie中文
        22 ******************************
        23 
        24 0
        25 """
        文件指針演示

         

2.4打開文件的方式

  • open函數默認以只讀方式打開,並返回文件對象

  語法如下:

    • f = open( " 文件名 "  , " 訪問方式 " )
  •  x:以x打開一個文件,如果這個文件存在,那么報錯

  • t:以t打開一個文件,底層是以二進制的形式打開,但是會默認幫我們將文件解碼(linux:默認以UTF-8).
  • b:以b打開一個文件,是以二進制的形式打開,獲取到的信息都是字節。 
  • r+、rt+、rb+,默認光標位置:起始位置
    w+、wt+、wb+,默認光標位置:起始位置(清空文件)
    - x+、xt+、xb+,默認光標位置:起始位置(新文件)
    - a+、at+、ab+,默認光標位置:末尾

     

     提示:頻繁的移動指針,會影響文件讀寫效率,開發中更多的時候會以 只讀、只寫 的方式來操作文件

 

2.5讀寫文件內容

  • read,讀

    • 讀所有【常用】

      f = open('info.txt', mode='r',encoding='utf-8')
      data = f.read()
      f.close()
      
      f = open('info.txt', mode='rb')
      data = f.read()
      f.close()
  • 讀n個字符(字節)【會用到】
    f = open('info.txt', mode='r', encoding='utf-8')
    # 讀1個字符
    data = f.read(1)
    f.close()
    print(data) #
    
    
    f = open('info.txt', mode='rb')
    # 讀1個字節
    data = f.read(3)
    f.close()
    print(data, type(data))  # b'\xe6\xad\xa6' <class 'bytes'>

     

  • read方法默認會把文件的 所有內容 一次性讀到內存
  • 如果文件太大,對內存的占用會非常嚴重

  readline 方法:

    • 可以一次讀取一行內容
    • 方法執行后,會把指針移動到下一行,准備再次讀取

  讀取大文件的姿勢:

    •  1 #打開文件
       2 file = open("sis.txt")
       3 while True:
       4     #讀取一行內容
       5     text = file.readline()
       6     #判斷是否讀取到內容
       7     if text == "":          #或者 if not text:
       8         print(type(text))   #<class 'str'>
       9         break
      10     #每讀取到末尾都會有一個 \n
      11     print(text,end="")
      12 """
      13 運行結果:
      14 python1一
      15 python2二
      16 python3三
      17 python4四<class 'str'>
      18 """
      View Code

readlines,讀所有行,每行作為列表的一個元素

f = open('info.txt', mode='rb')
data_list = f.readlines()
f.close()
print(data_list)

循環,讀大文件(readline加強版)【常見】

f = open('info.txt', mode='r', encoding='utf-8')
for line in f:
    print(line.strip())
f.close()

write,寫

f = open('info.txt', mode='a',encoding='utf-8')
f.write("你好")
f.close()

f = open('info.txt', mode='ab')
f.write( "你好".encode("utf-8") )
f.close()

flush,刷到硬盤

f = open('info.txt', mode='a',encoding='utf-8')
while True:
    # 不是寫到了硬盤,而是寫在緩沖區,系統會將緩沖區的內容刷到硬盤。
    f.write("你好")
    f.flush()
f.close()

  移動光標位置(字節)

f = open('info.txt', mode='r+', encoding='utf-8')
# 移動到指定字節的位置
f.seek(3)
f.write("武沛齊")
f.close()

移動到指定字節的位置,再插入數據時,會覆蓋后面的數據

注意:在a模式下,調用write在文件中寫入內容時,永遠只能將內容寫入到尾部,不會寫到光標的位置。

  獲取當前光標位置(按字節算)

f = open('info.txt', mode='r', encoding='utf-8')
p1 = f.tell()
print(p1)  # 0
f.read(3)  # 讀3個字符 3*3=9字節
p2 = f.tell()
print(p2)  # 9
f.close()


f = open('info.txt', mode='rb')
p1 = f.tell()
print(p1)  # 0
f.read(3)  # 讀3個字節
p2 = f.tell()
print(p2)  # 3
f.close()

2.6文件讀寫案例——復制文件

目標:用代碼實現文件的復制過程

  • 小文件復制
    • 打開一個已有文件,讀取完整內容,並寫入到另一個文件
    •  1 #復制小文件方式1
       2 file_read = open("sis.txt","r")
       3 file_write = open("test.txt","w")
       4 text_1 = file_read.read()
       5 text_2 = file_write.write(text_1)
       6 file_write.close()
       7 file_read.close()
       8 
       9 #復制小文件方式2 推薦(with關鍵字,會自動釋放文件對象空間)
      10 test = None
      11 with open("sis.txt","r") as file:
      12     test = file.read()
      13 with open("test1.txt","w") as file:
      14     file.write(test)
      小文件復制
  • 大文件復制
    • 打開一個已有文件,逐行讀取內容,並順序寫入到另一個文件
    •  1 #大文件復制
       2 file_read = open("五筆詞根1.jpg","rb")
       3 file_write = open("五筆詞根2.jpg","wb")
       4 while True:
       5     text = file_read.readline()
       6     #python中,除了‘’、""、0、()、[]、{}、None為False, 其他轉換都為True。 也就是說字符串如果不為空,則永遠轉換為True。
       7     if not text:
       8         break
       9     file_write.write(text)
      10 file_read.close()
      11 file_write.close()
      大文件復制

 

2.7上下文管理、文件讀寫中的函數

之前對文件進行操作時,每次都要打開和關閉文件,比較繁瑣且容易忘記關閉文件。

以后再進行文件操作時,推薦大家使用with上下文管理,它可以自動實現關閉文件。

with open("xxxx.txt", mode='rb') as file_object:
    data = file_object.read()
    print(data)

在Python 2.7 后,with又支持同時對多個文件的上下文進行管理,即:

with open("xxxx.txt", mode='rb') as f1, open("xxxx.txt", mode='rb') as f2:
    pass

文件讀取 — Python 3.10.1 文檔

3.文件/目錄的常用管理操作

  • 在   終端/文件瀏覽  中可以執行常規的  文件/目錄  管理操作,例如
    • 創建、重命名、刪除、改變路勁、查看目錄內容........
  • 在Python中如果希望通過程序實現上述功能,需要導入  os  模塊

  文件操作:

    

 

   目錄操作:

    

 

  • 提示:文件或者目錄操作,都支持  相對路徑絕對路勁

 

4.文本文件的編碼方式

pass

# -*- coding: utf8 -*-
# -*- coding: utf-8 -*-
# -*- coding: gbk -*-

讀文件:

  1. r打開文件,默認使用GBK(windows是默認GBK,但是MAC和linux是默認UTF-8)的編碼格式打開,所以在讀文件時,默認編碼需要與文件編碼相同否則報錯

  2. rb打開文件,是一個字節流,所以需要decode()解碼,默認decode("utf-8")

  3. rt打開,以文本的形式打開一個文件(默認使用(windows是默認GBK,但是MAC和linux是默認UTF-8)打開文件)

  4. 由上可知,python中的默認編碼是基於操作系統決定的 UTF-8:MAC、linux GBK:WIN

寫文件:

  1. w打開文件,默認使用GBK(windows是默認GBK,但是MAC和linux是默認UTF-8)的編碼格式打開,所以在寫文件時,如果文件已存在並且該文件的默認編碼,與打開時的編碼不同,也會亂碼(因為它只會清空文件,不會修改文件的編碼格式)。在寫文件時,不需要encode。

  2. wb打開二進制文件,不會受到編碼影響,在write寫入文件時,需要encode()壓縮,壓縮時指定編碼,那么生成的文件就是什么編碼。

  3. wt打開一個文件(默認使用(windows是默認GBK,但是MAC和linux是默認UTF-8)打開文件),在寫入文件時,如果文件已經存在,那么文件編碼與wt編碼不同時,一樣會亂碼(原理同1)。

 

 所以:在打開一個文件時,最好指定其編碼格式,推薦為UTF-8

5.csv格式文件

逗號分隔值(Comma-Separated Values,CSV,有時也稱為字符分隔值,因為分隔字符也可以不是逗號),其文件以純文本形式存儲表格數據(數字和文本)。

對於這種格式的數據,我們需要利用open函數來讀取文件並根據逗號分隔的特點來進行處理。

CSV文件內容

練習題案例:下載文檔中的所有圖片且以用戶名為圖片名稱存儲。

import requests
import os
with open("test.txt", mode="r", encoding="utf-8") as read_f:
    read_f.readline()
    for line in read_f:
        user_id, name, url = line.strip().split(",")
        res = requests.get(
            url=url,
            headers={
                "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
            }
        )
        if not os.path.exists("images"):    #判斷文件夾是否存在,如果不存在,就創建
            os.makedirs("images")
        with open("images/{}.png".format(name), mode="wb") as write_f:
            write_f.write(res.content)
View Code

6.ini格式文件

ini文件是Initialization File的縮寫,平時用於存儲軟件的的配置文件。例如:MySQL數據庫的配置文件。

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
log-bin=py-mysql-bin
character-set-server=utf8
collation-server=utf8_general_ci
log-error=/var/log/mysqld.log
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

[mysqld_safe]
log-error=/var/log/mariadb/mariadb.log
pid-file=/var/run/mariadb/mariadb.pid

[client]
default-character-set=utf8

這種格式是可以直接使用open來出來,考慮到自己處理比較麻煩,所以Python為我們提供了更為方便的方式。configparser(配置解析器)

import configparser
# 獲取可以處理ini文件的對象
config = configparser.ConfigParser()
# 打開文件
config.read("test.ini", encoding="UTF-8")

# 1.獲取所有節點    sections()(章節)
result = config.sections()
print(result)

# 2.獲取節點下的鍵值  items(): 返回一個列表,列表中存儲鍵值對,鍵值對以元組的形式存儲
result = config.items("mysqld")
print(result)
for x, y in config.items("mysqld_safe"):  # 可以使用這種方式將鍵值對取出
    print(x, y)

# 3.獲取節點下,鍵對應的值 get()
result = config.get("mysqld", "datadir")
print(result)

# 4.檢測節點是否存在  has_section()
result = config.has_section("mysqld")
print(result)

# 5.增加一個節點 add_section():如果節點已經存在,那么會報錯
config.add_section("root")

# 6.給節點設置鍵值 set():節點必須存在,可創建鍵值對,也可修改值
config.set("root", "niha", "456")
config.set("root", "niha1", "456")

# 7.刪除節點 remove_section() :會刪除節點下的所有鍵值對
config.remove_section("root")

# 8.刪除節點下的鍵值對 remove_option(節點,鍵)
config.remove_option("root", "niha")

# 4-8操作雖然給文件更改了數據,但是數據還在緩沖區中,所以在修改了文件后,需要使用write寫入
config.write(open('test.ini', 'w'))

 

 

 

5.拓展:eval函數

eval函數功能非常強大——將字符串當成有效的表達式來求值,並返回計算結果

# -*- coding: gbk -*-
#基本的數學計算
print(eval("1+1"))
#字符串重復
print(eval("'*'*30"))
#將字符串轉變成列表
print(type(eval("[1,2,3,4,5]")))
#將字符串轉變成元組
print(type(eval("(1,2,3,4,5)")))
#將字符串轉變成字典
print(type(eval("{'name':'蘋果','age':18}")))

 

案例——計算器

input_str = input("輸入算數題")
print(eval(input_str))
'''
運行:
輸入算數題1+1
2
'''

注意:在開發的時候千萬不要使用 eval 直接轉換 input 的結果

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM