python文件讀寫 -------------------來自神祕大佬羊羊羊的指導

文件讀寫

Python內置了文件讀寫的函數,用法和c語言是兼容的
工作原理:從做系統不允許在磁盤上直接讀寫文件,多以讀寫就是請求os打開一個文件對象【被稱爲文件的描述符】,然後,通過os提供的接口從這個文件對象中讀取數據【讀文件】,或者將數據寫入到文件中【寫文件】

1、常用文件讀寫

1.1、讀文件

步驟:
 a、打開文件:open()
 b、讀取內容:read()
 c、關閉文件:close()

import os
import pprint
"""
讀文件:從磁盤到內存
寫文件:從內存到磁盤

IO:Input/Output

IoError:當文件讀取完畢,還繼續讀取
"""

# 一、打開文件
"""
open(path,flag,encoding,errors)
    path:需要打開的文件的路徑,絕對路徑、相對路徑都可以,一般r“path”
    flag:以文件的方式:
        r:以只讀的方式打開文件,文件描述符出現在文件的開頭
        rb:以二進制的方式打開一個文件用於只讀,文件描述符出現在文件的開頭
        r+:打開一個文件用於讀寫,文件描述符出現在文件的開頭
    encoding:編碼格式,常用utf-8和gbk
    errors:驚醒讀取文件的時候的無措處理,一般用異常,可忽略
"""
path = r"C:\Users\weichen\Desktop\shopping2\shopping_car\致橡樹.txt"
# 以只讀的方式打開
# f是一個變量,指向一個被打開的文件,被稱爲文件對象
f = open(path, "r", encoding="gbk")

"""
注意:
    1、如果flag採用的是rb,encoding則必須省略,否則報錯
    2、如果flag採用的是r,如果文件格式是gbk,則可以省略encoding="gbk",
        如果文件格式是utf-8,則不能省略encoding = "utf-8"
"""

# 二、讀取文件內容
# 1、read
# 1.1 默認讀取文件中的所有內容
# 使用場景:讀取內容較少的文件
# str1 = f.read()
# print(str1)

# 1.2一次讀取指定字節的內容
# 使用場景:結合循環,讀取內容較多的文件
# str1 = f.read(3)

#採用read(num)方式讀取文件的全部內容,藉助於循環
#在讀取數據量大的文件時,一次讀取的大小一般爲1024
# size = os.path.getsize(r"C:\Users\weichen\Desktop\shopping2\shopping_car\致橡樹.txt")
# print(size)
# num = 816
#
# while size>0:
#     str1 = f.read(num)
#     print(str1)
#
#     size -= num

# 2、readline
# 2.1一次讀取一行內容
# str2 = f.readline()
# print(str2)

# 藉助於循環讀取全部的內容,入伏哦返回值爲假,則表示沒有內容可讀

# result = f.readline()
#
# while result:
#     print(result)
#     result = f.readline()

# 2.2 readline(num),類似read(num),但是一般不這麼用,使用目的是爲了讀取一行內容


# 2.3 readlines,按照行進讀取,結果爲一個列表,其中會顯示換行符和空格
str3 = f.readlines()
# print(str3)
pprint.pprint(str3)

# 三、關閉文件
# 注意:關閉的文件的目的有時候爲了系統資源的浪費
f.close()

1.2寫文件

步驟:
a.打開文件:open()
b寫入內容:write()
flush
c.關閉文件:close()

# 寫文件
# 一、打開文件
"""
open(path,flag,encoding,errors)
    flag:文件的打開方式
        w:一寫入的方式打開一個文件,文件描述符存在文件的開頭
        wb:以二進制的方式打開一個文件的寫入,文件描述符存在文件的開頭
        w+: 打開一個文件用於讀寫,文件描述符出現在文件的開頭
        a:append,在源文件內容的後面追加內容
"""
f = open(r"file1.txt","w",encoding="utf-8")

# 二、寫入內容
f.write("你好hello1234")

# 一般寫入內容後刷新,加快寫入速度
f.flush()
# 三、關閉文件
f.close()

"""
總結:
    1、不管是讀取文件還是寫入文件,都需要打開文件,打開的方式取決於需要進行的操作
    2、如果時讀取文件,則文件必須存在,二如果時寫入文件,則文件可以不存在,在寫入的過程會自動創建
    3、在寫入文件的過程中,如果採用的時w,則覆蓋,a,追加
    4、在進行文件讀寫的時候,一定要注意使用的編碼格式和文件本身的編碼格式需要保持一致,否則亂碼
"""

with語句

# 文件讀寫的簡寫形式
# with.....as...
"""
通過with...as...,簡化文件讀寫過程中的異常
優點:當文件讀寫完畢之後,可以自動關閉文件,不需要手動關閉

"""

# 讀文件
# f知識一個變量,只是只想打開的文件對象
with open("致橡樹.txt","r", encoding="gbk") as f:
    print(f.read())

# 寫文件
with open("file1.txt","w",encoding="gbk") as f:
    f.write("浪裏個浪")
    f.flush()
    
# 注意:一旦代碼執行with...as..代碼塊,則文件會自動關閉,但是,對於變量不會引入新的作用域

2、csv文件的讀寫

讀取文件

# 讀取csv文件
import csv

def readcsv1(path):
    # 1.打開文件
    csvfile = open(path,"r")
    # 2.讀取文件內容
    # 區別於普通文件,但會一個迭代對象,如果要獲取具體內容,則可以遍歷該可迭代對象
    result = csv.reader(csvfile)
    print(result)

    for content in result:
        # 可迭代對象當中的元素爲列表
        print(content)
        
    # 關閉文件
    csvfile.close()


if __name__ == "__main__":
    readcsv1(r"csv1.csv")

# 二、# 讀取csv文件
import csv

def readcsv1(path):
   with open(path,"r") as f1:
       result = csv.reader(f1)
       for content in result:
           print(content)


if __name__ == "__main__":
    readcsv1(r"csv1.csv")

寫入文件

# 寫入csv文件
import  csv

# 注意,向csv文件中寫入任意的可迭代對象

def writecsv1(path):
    # 打開文件
    csvfile = open(path,"w")

    # 寫入
    # 獲取寫入對象
    result = csv.writer(csvfile)
    # 寫入
    # 列表
    # 字符串: 打碎重寫
    # 字典:只寫key

    result.writerow(["aaa", 'bbb', 'dd', 'cc'])
    
    # 關閉文件
    csvfile.close()

if __name__ == "__main__":
    writecsv1("csv2.csv")

3、編碼和解碼

亂碼:utf-8存儲中文 3個字節,gbk存儲中文佔用2個字節
注意:編解碼格式要保持一致,如果不一致,修改文件本身的編碼格式

path = r"text03.txt"

#1.編碼
with open(path,"wb") as f1:
    str1 = "今天是個好日子today is a good day"
    f1.write(str1.encode("utf-8"))
#
# with open(path,"w",encoding="utf-8") as f1:
#     str1 = "今天是個好日子today is a good day"
#     f1.write(str1)


#2.解碼
# with open(path, "rb") as f1:
#     data = f1.read().decode("utf-8")
#     print(data)

with open(path, "r", encoding="utf-8") as f1:
    data = f1.read()
    print(data)

pickle模塊

在python中,如果要實現序列化和反序列化,可以使用pickle和json
【面試題:簡述什麼時序列化和反序列化】
序列化:將對象持久化到磁盤上,【寫:weite】,英文表示爲picking,serialiation
反序列化:將磁盤上的對象讀取出來【讀:read】,英文表示:unpicking

import  pickle

"""
pickle提供了簡單的持久化功能,可以將對象以文本的形式存儲到磁盤上
pickle只能在Python中使用,
Python中所有的數據類型【list,tuple,dict,set,str,對象】都可以通過pickle模塊持久化到磁盤上

注意:通過pickle序列化之後的數據,人一般無法識別,只能計算機識別【區別於亂碼】
"""

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def show(self):
        print("姓名:%s,年齡:%s" % (self.name,self.age))

p = Person("zhangsan",10)

#1.以普通文件的方式操作對象
#缺點:write只能寫入字符串
#f = open(r"file1.txt","w",encoding="utf8")
#f.write(p)#TypeError: write() argument must be str, not Person
#f.close()

#2.思考問題:如果向文件中寫入一個對象,該如何做?---》pickle模塊

#2.1序列化【寫】
"""
pickle.dump(obj,file)
    obj:將要寫入文件的對象
    file:obj將要寫入的文件對象,注意:file必須以二進制的方式打開,爲wb
"""
#a。打開文件
f1 = open(r"obj.txt","wb")

#b.寫入對象
pickle.dump(p,f1)

#c.關閉文件
f1.close()


#2.反序列化【讀】
"""
pickle.load(file)
    file:將要讀取的文件對象,注意:file必須以二進制的方式打開,爲rb
"""
#a.打開文件
f2 = open(r"obj.txt","rb")

#b。讀取對象
result = pickle.load(f2)
print(result)
result.show()

#c.關閉文件
f2.close()

"""
w,w+,wb都會覆蓋源文件中的內容,
r,r+,rb都必須保證源文件存在
w,w+,wb,a如果文件不存在,會自動創建
"""

json模塊

思考問題:將文本或者二進制數保存到文件中,使用write操作,如果將一個列表或者字典直接保存到文件中該如何實現?------》使用json格式保存數據

JSON:JavaScript Object Notation,本來是JavaScript語句中船艦對象的一種字面量方式,被廣泛應用於跨平臺的語言的數據交換【因爲JSon時純文本,任何系統任何編程語言都可以處理純文本】

使用場景:在兩種不同的編程語言之間傳遞對象,將數據序列化爲josn,json表示出來就是一個字符串,可以被所有的語言讀取,也可以存儲到磁盤或者網絡傳輸

在web開發中,不僅使用json,還使用xml,但是使用json較多,json更快,而且可以直接在web中讀取

Python中的數據類型和json的數據類型的區別:
json    Python
object    dict
array    list
string    str
number   int/folat
true/false  True/False
null     None

注意:json和pick將數據序列化之後的區別

import  pickle
dict2 = dict(name="jack",age=10,score=100)
with open(r"pickle1.txt","wb") as f2:
    pickle.dump(dict2,f2)
import  json

#一、基本用法
#1.寫【序列化】
"""
dump():將Python對象按照json格式序列化到文件中
dumps():將Python對象處理成json格式的字符串
"""
#1.1
dict1 = dict(name="jack",age=10,score=100)
print(dict1)
r1 = json.dumps(dict1)
print(r1)
print(type(r1))

#1.2
dict2 = dict(name="jack",age=10,score=100)
with open(r"data1.json","w",encoding="utf8") as f2:
    json.dump(dict2,f2)

#2.讀【反序列化】
"""
load():將文件中的json數據反序列化爲對象
loads():將字符串的內容反序列化爲Python對象
"""
#2.1
str1 = '{"name": "jack", "age": 10, "score": 100}'
r1 = json.loads(str1)
print(r1)
print(type(r1))

#2.2
with open(r"data1.json","r",encoding="utf8") as f2:
    r2 = json.load(f2)
    print(r2)
    print(type(r2))


#練習:
#序列化
def jsonwrite(dict1):
    with open(r"data2.json","w",encoding="utf8") as f1:
        json.dump(dict1,f1)

    print("數據保存成功!")

#反序列化
def jsonread():
    with open(r"data2.json","r",encoding="utf8") as f2:
        result = json.load(f2)
        print(result)

if __name__ == "__main__":
    mydict = {
        "name":"狗蛋兒",
        "age":18,
        "qq":1736363,
        "friends":['王大錘',"馬化騰"],
        "cars":[
            {"brand":"polo","price":100000},
            {"brand":"五菱宏光","price":50000},
            {"brand":"qq","price":20000}
        ]
    }
    jsonwrite(mydict)

    jsonread()

StringIO和BytesIO

數據的讀寫不一定只能在文件中操作,也可以在內存中操作,StringIO在內存中讀寫字符串,BytesIO在內存中讀寫字節,字節數據其實就是二進制數據

注意:StringIO和BytesIO是系統的類

from  io import  StringIO,BytesIO

#一、StringIO
#1.寫入
#創建對象
si = StringIO()
#寫入
#注意:將數據寫入到了內存中
si.write("hello")
si.write("Python")
si.write("2141412")

#獲取寫入到內存中的數據
r1 = si.getvalue()
print(r1)

#2.讀取
si2 = StringIO("hello\nPython\n2141412")
#全部讀取
# r2 = si2.read()
# print(r2)
#按行讀取
# r2 = si2.readline()
# print(r2)

while True:
    r2 = si2.readline()
    if r2 == "":
        break

    print(r2)

#二、BytesIO
#1.寫入
bi = BytesIO()
#編碼
# bi.write("中文fahjghahg".encode("utf-8"))
bi.write(bytes("中文fahjghahg",encoding="utf-8"))
print(bi.getvalue())

#2.讀取
bi2 = BytesIO(b'\xe4\xb8\xad\xe6\x96\x87fahjghahg')
r2 = bi2.read()
print(r2)
#解碼
#print(r2.decode("utf-8"))
print(str(r2,encoding="utf-8"))

collections

1.namedtuple

#1.namedtuple
from  collections import  namedtuple
"""
tuple是一個有序的集合
其中允許存儲重複元素,但是,一旦被定義之後,將不可改變
"""

#需求:使用元組表示一個二維座標
#方式一
tuple1 = (2,4)
#方式二
class Point(object):
    def __init__(self,x,y):
        self.x = x
        self.y = y
print(Point)
p = Point(2,4)
print(p.x,p.y)
p.x = 10
p.y = 20
print(p.x,p.y)

print("*" *20)

#方式三
#第一步:導入模塊
#第二步:調用函數,定義了類
#namedtuple("名稱",[屬性])
Point = namedtuple("Point",["x","y"])
print(Point)
p = Point(2,4)
#第三步:訪問屬性
print(p.x,p.y)
# p.x = 10
# p.y = 20
# print(p.x,p.y)

"""
namedtuple是一個函數,它用來創建一個自定義的tuple對象
並且規定了tuple元素的個數,並可以用屬性而不是索引訪問元組中的元素

好處:可以很方便的定義一種新的數據類型,它具備元組的不可變性,又可以通過引用訪問屬性
"""

print(isinstance(p,Point))
print(isinstance(p,tuple))


Circle = namedtuple("Circle",['x','y','r'])

2.deque

from collections import  deque


"""
使用list存儲數據,按照索引訪問元素速度較快,但是,插入和刪除的速度較慢,因爲list是線性存儲

deque是爲了實現高效的插入和刪除操作的雙向列表

添加元素
    append:在末尾追加/appendleft:在頭部添加
刪除元素
    pop:刪除末尾元素/popleft:刪除頭部元素
"""

queue = deque([2,3,4])
print(queue)

#添加
queue.append(5)
print(queue)
queue.appendleft(6)
print(queue)

#刪除
queue.pop()
print(queue)
queue.popleft()
print(queue)

3.defaultdict

from  collections import  defaultdict

"""
普通的dict,如果訪問了一個不存在的key,則會報出異常KeyError
"""
dict1 = {"a":1,"b":2}
v1 = dict1["a"]
print(v1)
# v2 = dict1["c"]
# print(v2)   #KeyError: 'c'

print(dict1)

#問題:如果key存在,則獲取對應的value,但是如果key不存在,返回一個默認值,需要使用defaultdict

#defaultdict(有返回值的函數[,字典])
d = defaultdict(lambda : "aaaa")
print(d)
print(type(d))

#注意:和普通的dict相同,如果key不存在,dict[key] = value則表示將鍵值對添加到字典中
d["key1"] = 34
print(d)

#如果訪問的key不存在,則默認獲取的是函數的返回值
print(d["key2"])

4.OrderDict

from collections import  OrderedDict


"""
字典:key是無序的
"""

#字典的寫法

#1.無序字典
dict1 = {"a":1}
print(dict1)
dict2 = dict(x=1,y=3)
print(dict2)
dict3 = dict([("a",1),("b",2),("c",3)])
print(dict3)

#2.有序字典
dict4 = OrderedDict([("a",1),("b",2),("c",3)])
print(dict4)


#練習:
od = OrderedDict()
od["2"] = 20
od["1"] = 10

print(list(od.keys()))

5.Couter

from  collections import  Counter

#需求:統計一個單詞中每個字符出現的次數
data = input("請輸入文本:")

#方式一
dict1 = {}

for ch in data:
    if ch not in dict1:
        dict1[ch] = 1
    else:
        dict1[ch] += 1
print(dict1)

#方式二
#Counter是Collections中提供的一個計數器
c = Counter()
for ch in data:
    c[ch] += 1
print(c)

print(type(c))
print(isinstance(c,Counter))
print(isinstance(c,dict))

#Counter實際上是dict的一個子類,專門用來統計可迭代對象個數
c = Counter()
for num in [2,3,43,43,3,3,3,3,22,100]:
    c[num] += 1
print(c)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章