python 文件操作和json模块的模块化写法
前言
python 操作文件的方法有,open 直接打开文件。json,pickle,shelve ,configparser ,都是写入到文件,或者修改文件。
1.python open 打开文件(分别读写)
就以自己写的自动添加目录索引为例子。
原始文件如下:
<ol> <li><a style="text-decoration:none;color: #000000; line-height: 20px; font-family: 楷体; font-size: 20px;" href="http://www.cnblogs.com/keep-going2099/articles/8134851.html" target="_blank">python 编码格式 </a></li> </ol>
要求:当有新的url链接需要生成时,在最后一个<li></li>标签后面添加一行数据,或者说是,在</ol>前面添加一个<li></li>标签里面的内容;
先贴代码:
# -*- coding: utf-8 -*- import io,sys,os def add_blog_url(url,info): add_content = '<li><a style="text-decoration:none;color: #000000; line-height: 20px; font-family: 楷体; font-size: 20px;" href="%s" target="_blank">%s</a></li>'%(url,info) # add_content = '<li><a href="%" target="_blank"></a></li>'%(url,info) li_content = [] with io.open("blog_url.html", 'r', encoding='utf-8') as read_file, io.open("new_blog_url.html", 'w',encoding='utf-8') as write_file: content = read_file.read() post = content.find('</ol>') if post != -1: content = content[:post] + add_content+'\n' + content[post:] ''' 这里就相当于字符串的切片操作,find的意思是,如果找不到就返回-1,找到返回查找的字符串的位置。 content = content[:post] + add_content + content[post:] content[:post] :读取的是查找内容之前内容 add_content : 表示要添加的内容 content[post:] :表示查找内容之后的 ''' write_file.write(content) # os.rename('blog_url.html','bak_blog_url.html') os.remove('blog_url.html') os.rename('new_blog_url.html','blog_url.html') if __name__ == '__main__': while True: url = input("输入网址,退出(Q):").strip() if url == 'Q':break if len(url) == 0:continue if url.startswith("http://") or url.startswith("https://"): info = input("输入网站信息:").strip() add_blog_url(url,info) else: print("必须是http:// 或者https:// 开头才能访问,") continue
知识点1:open函数打开文件;
首先:用with 打开文件时,不需要close文件对象。
在py2 和py3 中,open打开文件的方法是不同的,区别在于在python2 中不添加 " encoding='utf-8' ",python3中可以不加,但是,如果加上以后,在py2 中执行就会报错。
但是,无论是py2还是 py3 的open函数,都是调用了 io 模块下的open函数,因此,直接调用io模块,io.open("blog_url.html", 'r', encoding='utf-8'),这样,无论是在py2 还是py3 都不会报错了!
知识点2:怎么能够在指定字符串之前插入数据。
原理:在 read_file 文件对象,读取到文件的内容以后,content = read_file.read(),读到的其实是一串字符串。然后用find 找到 指定字符串在 content中第一次出现的位置。然后用 字符串的切片方法进行分割,如下:
str.find("strinfg") 查找字符串,如果没有找到返回 -1 ,找到以后就返回string 在原始字符串中的 postion 位置。
content = content[:post] + add_content+'\n' + content[post:] ''' 这里就相当于字符串的切片操作,find的意思是,如果找不到就返回-1,找到返回查找的字符串的位置。 content = content[:post] + add_content + content[post:] content[:post] :读取的是查找内容之前内容 add_content : 表示要添加的内容 content[post:] :表示查找内容之后的 '''
2. 修改文件的方法(替换)
修改文件两种方式:
1) 直接把要修改的文件内容写到一个新文件,然后在把新文件rename成为一个老文件。
2) 把修改的内容修改以后放到一个列表里面,然后,在把列表里面的内容写到源文件。注意:当要修改的文件,或者说是要替换的字符串的长度大于新字符串的长度时,文件原始的字节长度是不变的,因此 就会出现一部分字符串在修改文件的末尾,因此,此时就要用 文件操作的方法(truncate)来进行截断。因为,当文件修改以后,游标会到修改的那个位置,因此,在游标的位置进行truncate就会把原始文件未被占用的字节长度给截断掉。
方法1:差不多相当于上面的方法,只是自己的实现方式上的小区别修改即可。
方法2:有如下文件,需要把python 替换成为 java
[root@dev second_modules]# cat text.log hello world! everyday study python l like python do you love python?
代码如下:读到内存,然后再写到源文件
[root@dev second_modules]# cat modify_file_free.py #!/usr/bin/env python #coding:utf-8 f_name = "text.log" old_str = "python" new_str = "java" f = open(f_name,'r+',encoding="utf-8") list01 = [] for line in f: if old_str in line: line = line.replace(old_str,new_str) list01.append(line) values = ''.join(list01) print(values) f.seek(0) f.write(values) f.truncate() f.close()
** 上面红色字体的 truncate的意思就是,列表内容写完以后,假如源文件的字节长度大于现在的字节长度,那么就把现在的字节长度写完以后,进行截断。因为,不管是读还是写都是在源文件的基础上去进行的,源文件的原始字节长度不会改变。如果不进行截断,那么就会多出源文件的一部分字节出来。演示方法去掉truncate即可,并且替换的字节长度小于要替换的字节长度。
用更通俗的话来讲:首先读,会把整个文件读完,那么文件指针就会走到文件内容的末尾。不可能继续读,然后,f.seek(0),把文件指针重新放到文件头部,此时写的时候,就相当于 ”w“ 方法了。因此,可以直接写。truncate 只是为了截取就文件多余的字节长度。
3.python 的json 模块的,模块化写法
json其实读取文件和写入文件具体用法可以查看 python笔记,但是,为什么还要继续写这个笔记呢?
因为,在写python程序的时候,很多次的会用到 json模块的读方法和写放啊。因此,为何不在json的基础上,直接写一个你想要打开的文件的方法呢。
代码如下:
#coding:utf-8 import os import io import json import sys ''' 该模块使用方法: operate_user_info_file(filename,mode,dirname=default_path,data=None) filename:文件名(可以用用户的名称作为文件名) mode:参数用:read 或者 write dirname:默认是写到conf目录下,但是,也可以自己写指定的路径。 data: 是用于写方法时,写入文件的数据。 正确调用方法: 1.读:operate_file('ryan','read') 或者,自己自己目录读取 operate_user_info_file(filename,mode,dirname=yourdir) 2.写:operate_file('ryan','write',data="yourdata"),如果要指定路径写,也是和读一样自己指定路径。 ''' if os.name == 'posix': default_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/'+'conf' elif os.name == 'nt': default_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '\\'+'conf' def operate_file(filename,mode,dirname=default_path,data=None): if mode == 'write': write_file = io.open("%s/%s.json"%(dirname,filename),'w',encoding='utf-8') json.dump(data,write_file) write_file.close() return True,"写入成功" elif mode == 'read': filename = "%s/%s.json" % (dirname, filename) # print(filename) if os.path.isfile(filename) and os.path.exists(filename): read_file = io.open(filename, 'r', encoding='utf-8') return_data = json.load(read_file) read_file.close() return return_data else: return False if __name__ == '__main__': res = operate_file("ryan2",'read') if res: print("文件存在") else: print("not exists")