python學習之I/O流

何爲I/O流?

I 是input,O是output,則爲input output Stream。輸入輸出流向。這裏的輸入輸出是指將數據讀入內存或者內存輸出的過程中使用的技術,操作的地方在於內存。
比如將數據存入硬盤,是輸入還是輸出呢?
答案是輸出,關注內存的流向。

I/O流的作用

主要是爲了,持久化數據,保證數據不再丟失。
python如何操作IO流
###全局函數 open 打開一個IO操作open()

I/O流的分類

數據類型
		|-- 字符流
		|-- 字節流
	流的方向
		|-- 輸入流
		|-- 輸出流

也可以組合爲字符輸入流,字符輸出流,字節輸入流,字符輸出流。

I/O流的操作

open()的操作格式如下:

open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
file: 必需,文件路徑(相對或者絕對路徑)。
mode: 可選,文件打開模式
buffering: 設置緩衝
encoding: 一般使用utf8
errors: 報錯級別
newline: 區分換行符
closefd: 傳入的file參數類型

其中文件名必不可少,只打開文件名,默認打開方式是r,文件的操作方式有以下幾種:

    ========= ===============================================================
    Character Meaning
    --------- ---------------------------------------------------------------
    'r'       open for reading (default)
    'w'       open for writing, truncating the file first
    'x'       create a new file and open it for writing
    'a'       open for writing, appending to the end of the file if it exists
    'b'       binary mode
    't'       text mode (default)
    '+'       open a disk file for updating (reading and writing)
    ========= ===============================================================

文件操作可以進行組合,b代表字節流文件,非文字類皆是。操作是加上即可。w和a的區別在於,w是直接打開,以前的內容被覆蓋,a是加在之前內容的末尾。
在這裏插入圖片描述
操作的方法

file.write()

進行文件內容寫入,覆蓋。

#打開一個文件名字是a.txt,沒有則進行創建
f = open(r"J:\Anaconda3\openlab\第五週\a.txt","w") #這裏的r是防止報錯,因爲\是轉義符,不然需要將\替換爲//,加r是取消轉移符。
s = "python是門不錯的語言,這是一篇不錯的博客!"
#將s寫入a.txt
f.write(s)
#將I/O流關閉,一定要關閉!I/O流是系統的寶貴資源,如果沒有關閉,會一直佔用內存。
f.close()

在這裏插入圖片描述
操作完成後在所在目錄創建了a.txt文件,寫入了s。

file.read()

爲了讀取一個文件的內容,調用 f.read(size), 這將讀取一定數目的數據, 然後作爲字符串或字節對象返回。
size 是一個可選的數字類型的參數。 當 size 被忽略了或者爲負, 那麼該文件的所有內容都將被讀取並且返回。

#打開一個文件名字是a.txt
f = open(r"J:\Anaconda3\openlab\第五週\a.txt","r")
#將a.txt的內容讀出來。
print(f.read())
#將I/O流關閉,一定要關閉!I/O流是系統的寶貴資源,如果沒有關閉,會一直佔用內存。
f.close()

這裏的a.txt是剛纔創建的。
在這裏插入圖片描述
對字節流的操作比如複製一個文件:
對於小文件可以直接複製,如果文件過大,直接讀取,會導致系統崩潰,python會直接導致藍屏。
複製的文件中最好是不要有數字,否則會找不到文件。

# 字節數據,必須在mode中寫上b,表示字節操作
# 不需要書寫編碼,字節不存在編碼情況
f = open("a.mp4", "br")

img = f.read()

file = open("c:\\a.mp4", "wb")

file.write(img)

f.close()
file.close()

故而copy大文件可以使用這種方式:


def copyFile(src, dest):
	"""文件的拷貝"""
	src_file = open(src, "br")
	dest_file = open(dest, "bw")

	# 當文件時,如果文件是字節文件,要注意大文件的拷貝
	# 如果是大文件,一定不要直接拷貝,防止內存溢出

	while True:
		content = src_file.read(1024) #讀取文件中1024字節,內存大的可以這裏寫1024*1024 還可以1024*1024*1024.
		if content == b'': #對讀取的數據判空,即是否讀取完成,讀取到末尾,結束,跳出循環。
			print("文件讀取完成")
			break
		else:
			dest_file.write(content) #讀取的內容寫入另一個文件中

	src_file.close()
	dest_file.close()
	

if __name__ == '__main__':
	src = input(r"請輸入您要拷貝的文件路徑:")
	dest = input(r"請輸入你要保存的新路徑:")#加r,爲了就直接複製路徑,
	copyFile(src, dest)

對象序列化

對象序列化
	pickle模塊(二進制和對象之間的序列化)
		|-- dumps(obje)		# 將對象序列化成二進制數據
		|-- dump
		|-- loads		# 反序列化,將序列化成二進制數據重新轉換爲對象
		|-- load()

	json模塊(json字符串和對象之間的序列化)
		|-- dumps(obje)	
		|-- dump
		|-- loads		
		|-- load()

with語句

with語句塊

python 每當打開一個IO,最後一定要關閉資源

with open("a.txt", "r") as f:
	# 操作IO流,不用關閉

with語句塊打開的IO,
with結束時自動調用close方法關閉資源

今天I/O流的操作就分享到這裏,下面提供兩道練習題目:

作業1:
	遍歷磁盤,完成磁盤的備份
作業2:
	博客,持久化
		用戶
		博客

作業1:

import sys
import hashlib
from datetime import datetime

import utils


# 所有的保存在list
users = []
# 記錄當前登錄用戶
login_user = {}
# 所有文章
'''
{"title": "我的第一篇博客", "content": "嘿嘿,我也來寫博客了",\
	 "publish_time": datetime.now(), "modify_time":datetime.now(), "author":login_user.get("username") }
'''
articles = []


def init():
	pass


def main():
	""" 主界面 """
	print("~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n")
	print("~*~*~*~*~*~*~*~*~*~*~歡迎進入我們博客系統*~*~*~*~*~*~*~\n")
	print("\t\t1、用戶註冊\n")
	print("\t\t2、用戶登錄\n")
	print("\t\t3、退出系統\n")
	print("~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n")
	return input("請輸入您的操作:")


def main_blog():
	""" 博客主界面 """
	print("~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n")
	print("~*~*~*~*~*~*~*~*~*~*~歡迎進入我們博客系統*~*~*~*~*~*~*~\n")
	print("\t\t1、發佈博客\n")
	print("\t\t2、查看自己博客\n")
	print("\t\t3、刪除自己博客\n")
	print("\t\t4、回到上一級\n")
	print("~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~*~\n")
	return input("請輸入您的操作:")


def is_exists(username):
	''' 通過用戶名稱判斷用戶是否存在 '''
	for u in users:
		if u.get("username") == username:
			return True
	return False


def check_reg(username, password, comfirm_pass):
	''' 用戶註冊時用戶數據校驗 '''
	# 先判斷用戶名是否爲空
	if username is None or username.strip() == "":
		print("用戶名不能爲空")
		return False
	# 判斷用戶是否存在
	if is_exists(username):
		print("該用戶名稱已經存在,請重新註冊")
		return False

	# 判斷密碼不能爲空,密碼長度不能少於3位
	if password == None or password.strip() == "" or len(password) < 3:
		print("對不起,密碼不能爲空或者長度不能小於3位")
		return False

	# 兩次密碼不一致
	if password.strip() != comfirm_pass.strip():
		print("對不起,兩次密碼不一致")
		return False
	return True


def reg(username, password):
	# 首先密碼加密
	new_pass = utils.encryption_md5(password)
	user = {"username": username, "password": new_pass}
	users.append(user)
	# 保存用戶信息
	print("註冊成功!!!請登錄")


def login(username, password):
	# 首先密碼加密
	new_pass = utils.encryption_md5(password.strip())
	for u in users:
		if u.get("username") == username.strip() and u.get("password") == new_pass:
			return u
	return None


while True:
	# 初始化數據
	# 主界面
	choice = main()
	# 判斷
	if choice == "1":
		while True:
			# 用戶註冊
			username = input("請輸入用戶名稱:")
			password = input("請輸入用戶密碼:")
			comfirm_pass = input("請再次輸入用戶密碼:")

			# 數據校驗
			is_success = check_reg(username, password, comfirm_pass)
			if is_success != None:
				reg(username, password)
				break

	elif choice == "2":
		# 用戶登錄
		username = input("請輸入用戶名稱:")
		password = input("請輸入用戶密碼:")
		login_user = login(username, password)
		if login_user != None:
			print("恭喜您,登錄成功!!!")
			while True:
				choice = main_blog()
				if choice == "1":
					title = input("請輸入博客標題:")
					content = input("請輸入博客內容:")
					article = {}
					article["title"] = title
					article['content'] = content
					article["publish_time"] = datetime.now()
					article["modify_time"] = datetime.now()
					article["author"] = login_user.get("username")
					articles.append(article)
					print("當前所有文章是:")
					print(articles)
				elif choice == "2":
					print("查看自己博客")
				elif choice == "3":
					print("刪除博客")
				else:
					break

			else:
				print("登錄失敗,用戶名或者密碼錯誤,請重新登錄")
	else:
		yes = input("您確定要退出系統?(yes/no):")
		if yes.lower() == "yes":
			sys.exit()

作業2:

# -*- coding: utf-8 -*-
import os
import sys
from os import path


def sannaer_file(real_path, dest):
	"""
		使用遞歸遍歷磁盤
	"""
	files = os.listdir(real_path)
	for f in files:
		# 進行路徑拼接
		file = path.join(real_path, f)
		# file = real_path + "/" + f
		# file = real_path + os.sep + f

		# 判斷路徑是不是文件夾
		if path.isfile(file):
			# 該路徑是一個文件
			print(file)
			copyFile(file, dest)
		elif path.isdir(file):
			# 說明是一個文件夾!!
			sannaer_file(file, dest)



def copyFile(src, dest):
	"""文件的拷貝"""
	try:
		src_file = open(src, "br")

		# 構建一個真正的路徑出來
		p = src[src.find("\\")+1:]
		dest += p

		basename = path.dirname(dest)
		if path.exists(basename):
			dest_file = open(dest, "bw")
		else:
			os.makedirs(basename)
			dest_file = open(dest, "bw")

		# 當文件時,如果文件是字節文件,要注意大文件的拷貝
		# 如果是大文件,一定不要直接拷貝,防止內存溢出

		while True:
			# 100M 左右
			content = src_file.read(1024 * 1024 * 100)
			if content == b'':
				print("文件讀取完成")
				break
			else:
				dest_file.write(content)
		src_file.close()
		dest_file.close()

	except FileNotFoundError as e:
		print("出現異常:---->", e)


if __name__ == '__main__':
	sannaer_file("D:\\", "J:\\test\\")

今天的分享就到這裏,喜歡的小夥伴可以關注博主。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章