实现一个拷贝文件的功能,提醒:要考虑超大文件问题,如:依次读取1024字节,循环读取
def diy_copy(src_file_path,destination_file_path): # 复制文件。源文件路径,目标文件路径
f_read=open(src_file_path,'r',encoding='utf-8') # 读取源文件
string=f_read.read(1024) # 如果是仅1行的超大文件,一次读取一部分
f_write=open(destination_file_path,'w',encoding='utf-8') # 写入目标文件
while(string): # 只要读取的内容不为空就持续写入并读取后面的
f_write.write(string)
string=f_read.read(1024)
f_write.close()
f_read.close()
diy_copy('','')
先发流程图,是写完第二版代码后画的,如果有错还请指出。只是解决这个问题的思想,不一定和代码执行流程一模一样。第一次用visio,还不太会用。
import os
from os import path
def copy_single_file(src_file_path,destination_file_path): # 从文件复制到文件、从文件复制到目录
if path.isdir(destination_file_path): # 如果第二个参数是目录
src_file_name=path.basename(src_file_path) # 提取源文件名,含扩展名
destination_file_path=path.join(destination_file_path,src_file_name) # 将目录与文件名拼接,生成最终的第二个参数
f_read=open(src_file_path,'r',encoding='utf-8') # 读取源文件
string=f_read.read(1024) # 如果是仅1行的超大文件,一次读取一部分
f_write=open(destination_file_path,'w',encoding='utf-8') # 写入目标文件
while(string): # 只要读取的内容不为空就持续写入并读取后面的
f_write.write(string)
string=f_read.read(1024)
f_write.close()
f_read.close()
def dir_or_file(destination_file_path): # True说明目标地址是文件,False是目录
'''
判断目标地址是文件还是目录的思路:
如果名字里有'.',且后面是纯字母(忽略m3u8,写完才想起这个,不过它是.ts),那它是文件;如果后面不是纯字母,那它是目录(如版本号1.1.0).
如果名字里没有'.',那它是目录(忽略无扩展名的文件,这里把无扩展名的作为目录).
可能可以直接用正则判断----------学过正则后补充这个函数的正则写法--------------------------
还可以用rsplit('.',1),如果返回的列表长度为1,则是目录;如果长度不为1,且列表最后一个元素是纯字母,则它是文件,否则是目录
'''
'''这个函数也可以这么写,因path.basename()底层调用path.split()
temp_tuple=path.split('a/b/c/d/')
if '.' in temp_tuple[-1]:
temp_list=temp_tuple[-1].split('.')
if temp_list[-1].isalpha():
return True
else:
return False
else:
return False
'''
name = path.basename(destination_file_path)
if '.' in name:
name_split = name.split('.')
if name_split[-1].isalpha():
return True
else:
return False
else:
return False
def diy_copy(src_file_path,destination_file_path):
if path.abspath(src_file_path)==path.abspath(destination_file_path): # 第一个参数写绝对路径,终端运行不报错;写相对路径,终端运行报错,pycharm不报错
print('源文件与目标地址相同,无法复制')
return
if path.isdir(src_file_path) and dir_or_file(destination_file_path): # 后者返回True说明后者的参数是一个文件
print('源文件是目录,目标地址是文件,无法复制')
return
if not path.exists(destination_file_path): # 上面都是不能复制的,不用创建原来不存在的目录;下面都是能复制的,需要先创建原来不存在的目录,后面才能用path.isdir()判断
if dir_or_file(destination_file_path): # 目标地址是文件.这里先不用创建地址中间不存在的目录,copy_single_file()会创建
copy_single_file(src_file_path, destination_file_path)
elif not dir_or_file(destination_file_path): # 目标地址是目录
os.makedirs(destination_file_path)
if path.isdir(src_file_path) and path.isdir(destination_file_path): # 把目录复制到目录
filelist=os.listdir(src_file_path)
for i in filelist: # 要定义新变量存放新路径,如果用新路径覆盖src_file_path和destination_file_path,多层嵌套的目录结构递归时会报错
temp_src_file_path=path.join(src_file_path,i)
temp_destination_file_path=path.join(destination_file_path,i)
if path.isdir(temp_src_file_path): # 递归复制目录
diy_copy(temp_src_file_path,temp_destination_file_path)
else:
copy_single_file(temp_src_file_path,temp_destination_file_path)
else: # 从文件复制到文件、从文件复制到目录
copy_single_file(src_file_path,destination_file_path)
diy_copy('','') # 无论目标目录是否已存在,及无论源路径是目录时最后一个符号是否是/.支持测试从文件到文件、从文件到目录、从目录到文件、从目录到目录
# diy_copy('z:/a/新建文本文档.txt','z:/1.txt') # 从文件复制到文件 OK
# diy_copy('z:/a/新建文本文档.txt','z:/新建文本文档.txt') # 从文件复制到文件 OK
# diy_copy('z:/a/新建文本文档.txt','z:/b/') # 从文件复制到目录 OK
# diy_copy('z:/a/新建文本文档.txt','z:/b') # 从文件复制到目录 OK
# diy_copy('z:/a','z:/b') # 从目录复制到目录 OK
# diy_copy('z:/a','z:/b/') # 从目录复制到目录 OK
# diy_copy('z:/a','z:/新建文本文档.txt') # 从目录复制到文件 正常报错
# diy_copy('z:/a/新建文本文档.txt','z:/a/新建文本文档.txt') # 源与目的的路径相同 正常报错