File Operation


引用自:

在这里插入图片描述
在这里插入图片描述

模式描述
t文本模式 (默认)。
x写模式,新建一个文件,如果该文件已存在则会报错。
b二进制模式。
+打开一个文件进行更新(可读可写)。
U通用换行模式(不推荐)。
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
r+打开一个文件用于读写。文件指针将会放在文件的开头。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
w打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
w+打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
wb+以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
import os 
print (os.getcwd())
os.chdir('newdir')
print (os.getcwd())
D:\01_Project\99_test
D:\01_Project\99_test\newdir

读文件 open(mode=‘r’)

打开一个文件用open()方法(open()返回一个文件对象,它是可迭代的)

f = open('test.txt', 'r')
f
<_io.TextIOWrapper name='test.txt' mode='r' encoding='cp936'>

r表示是文本文件,rb是二进制文件。(这个mode参数默认值就是r)

如果文件不存在,open()函数就会抛出一个IOError的错误,并且给出错误码和详细的信息告诉你文件不存在

f = open('test.txt', 'r')
f
<_io.TextIOWrapper name='test.txt' mode='r' encoding='cp936'>

文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的

f.close()

由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try … finally来实现:

file_path = r'D:\01_Project\99_test\newdir\test.txt'
try:
    f = open(file_path, 'r')
    print(f.read())
finally:
    if f:
        f.close()
Hello, world!

但是每次都这么写实在太繁琐,所以,Python引入了with语句来自动帮我们调用close()方法

with open(file_path, 'r') as f:
    print(f.read())
Hello, world!

python文件对象提供了三个“读”方法: read()、readline() 和 readlines()。每种方法可以接受一个变量以限制每次读取的数据量。

  • read() 每次读取整个文件,它通常用于将文件内容放到一个字符串变量中。如果文件大于可用内存,为了保险起见,可以反复调用read(size)方法,每次最多读取size个字节的内容。
  • readlines() 之间的差异是后者一次读取整个文件,象 .read() 一样。.readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for … in … 结构进行处理。
  • readline() 每次只读取一行,通常比readlines() 慢得多。仅当没有足够内存可以一次读取整个文件时,才应该使用 readline()。

注意:这三种方法是把每行末尾的’\n’也读进来了,它并不会默认的把’\n’去掉,需要我们手动去掉。

with open('test.txt', 'r') as f1:
    list1 = f1.readlines()
list1
['Hello, world!']
with open('test.txt', 'a') as f:
    f.write('Hello, world!')
with open('test.txt', 'r') as f1:
    list1 = f1.readlines()
for i in range(0, len(list1)):
    list1[i] = list1[i].rstrip('\n')
list1
['Hello, world!Hello, world!']

对于read()和readline()也是把’\n’读入了,但是print的时候可以正常显示(因为print里的’\n’被认为是换行的意思)

with open('test.txt', 'r') as f1:
    list1 = f1.read()
print (list1)
list1
Hello, world!Hello, world!

'Hello, world!Hello, world!'
with open('test.txt', 'r') as f1:
    list1 = f1.readline()
print (list1)
list1
Hello, world!Hello, world!

'Hello, world!Hello, world!'

一个python面试题的例子

有两个文件,每个都有很多行ip地址,求出两个文件中相同的ip地址:

with open('data1.txt', 'r') as f1:
    list1 = f1.read()
    print (list1)
print ('*_'*30)
with open('data2.txt', 'r') as f1:
    list1 = f1.read()
    print (list1)
172.190.10.2
172.190.8.205
172.168.1.125
172.168.1.1
*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_*_
172.190.10.2
172.190.8.215
172.168.1.152
172.168.1.1
172.190.140.8
# coding:utf-8
import bisect

with open('data1.txt', 'r') as f1:
    list1 = f1.readlines()
for i in range(0, len(list1)):
    list1[i] = list1[i].strip('\n')
with open('data2.txt', 'r') as f2:
    list2 = f2.readlines()
for i in range(0, len(list2)):
    list2[i] = list2[i].strip('\n')

list2.sort()
length_2 = len(list2)
same_data = []
for i in list1:
    pos = bisect.bisect_left(list2, i)
    if pos < len(list2) and list2[pos] == i:
        same_data.append(i)
same_data = list(set(same_data))
print(same_data)
['172.190.10.2', '172.168.1.1']

要点:

  • 用with
  • 处理行末的’\n’
  • 使用二分查找提高算法效率
  • 使用set快速去重。

写文件 open(mode=‘w’)

写文件和读文件是一样的,唯一区别是调用open()函数时,传入标识符’w’或者’wb’表示写文本文件或写二进制文件

f = open('test.txt', 'w')
f.write('Hello, world!')
f.close()

注意:'w’这个模式是酱紫:如果没有这个文件,就创建一个;如果有,那么就会先把原文件的内容清空再写入新的东西。所以若不想清空原来的内容而是直接在后面追加新的内容,就用’a’这个模式。

我们可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件。当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放到内存缓存起来,空闲的时候再慢慢写入。只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘。忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的丢失了。所以,还是用with语句来得保险

with open('test.txt', 'w') as f:
    f.write('Hello, world!')

python文件对象提供了两个“写”方法: write() 和 writelines()。

  • write()方法和read()、readline()方法对应,是将字符串写入到文件中。
  • writelines()方法和readlines()方法对应,也是针对列表的操作。它接收一个字符串列表作为参数,将他们写入到文件中,换行符不会自动的加入,因此,需要显式的加入换行符。
f1 = open('test1.txt', 'w')
f1.writelines(["1", "2", "3"])
#    此时test1.txt的内容为:123
f1.close()

f1 = open('test2.txt', 'w')
f1.writelines(["1\n", "2\n", "3\n"])
f1.close()
#    此时test2.txt的内容为:
#    1
#    2        
#    3

关于open()的mode参数:

‘r’:读

‘w’:写

‘a’:追加

‘r+’ == r+w(可读可写,文件若不存在就报错(IOError))

‘w+’ == w+r(可读可写,文件若不存在就创建)

‘a+’ ==a+r(可追加可写,文件若不存在就创建)

对应的,如果是二进制文件,就都加一个b就好啦,例如在存储图片时:

‘rb’  ‘wb’  ‘ab’  ‘rb+’  ‘wb+’  ‘ab+’

JSON操作

  • dumps只完成了序列化为str,
  • dump必须传文件描述符,将序列化的str保存到文件中
  • loads 只完成了反序列化,
  • load 只接收文件描述符,完成了读取文件和反序列化

JSON(JavaScript Object Notation)即JavaScript对象表示法,一种轻量级,通用的文本数据格式。
JSON语法支持对象(Object),数组(Array),字符串,数字(int/float)以及true/false和null。
JSON拥有严格的格式,主要格式如下:

  • 只能用双引号,不能用单引号
  • 元素之间用逗号隔开,最后一个元素不能有逗号
  • 不支持注释
  • 中文等特殊字符传输时应确保转为ASCII码(\uXXX格式)
  • 支持多层嵌套Object或Array
import json

dict_var = {
    'name': 'Cactus', 
    'age': 18, 
    'skills': ['Python', 'Java', 'Go', 'NodeJS'], 
    'has_blog': True, 
    'gf': None
}

json.dumps()支持参数,indent为多行缩进空格数,sort_keys为是否按键排序,ensure_ascii=False为不确保ascii,及不将中文等特殊字符转为\uXXX等

data1 = json.dumps(dict_var)
data2 = json.dumps(dict_var, indent=2,sort_keys=True, ensure_ascii=False)
print (data1)
print (data2)
{"name": "Cactus", "age": 18, "skills": ["Python", "Java", "Go", "NodeJS"], "has_blog": true, "gf": null}
{
  "age": 18,
  "gf": null,
  "has_blog": true,
  "name": "Cactus",
  "skills": [
    "Python",
    "Java",
    "Go",
    "NodeJS"
  ]
}
json_str = '''{
    "name": "Cactus",
    "age": 18,
    "skills": ["Python", "Java", "Go", "NodeJS"],
    "has_blog": true,
    "gf": null
}'''

print(json.loads(json_str))
print(json.loads(data2))
{'name': 'Cactus', 'age': 18, 'skills': ['Python', 'Java', 'Go', 'NodeJS'], 'has_blog': True, 'gf': None}
{'age': 18, 'gf': None, 'has_blog': True, 'name': 'Cactus', 'skills': ['Python', 'Java', 'Go', 'NodeJS']}

保存为JSON文件

with open("demo2.json", "w", encoding='utf-8') as f:
    # json.dump(dict_var, f)  # 写为一行
    json.dump(dict_var, f,indent=2,sort_keys=True, ensure_ascii=False)  # 写为多行

加载JSON文件

with open("demo2.json", encoding="utf-8") as f:
    data = json.load(f)

print(data)
{'age': 18, 'gf': None, 'has_blog': True, 'name': 'Cactus', 'skills': ['Python', 'Java', 'Go', 'NodeJS']}

Pickle操作

  • pickle模块和json模块都有 dumps、dump、loads、load四种方法,而且用法一样

  • 不同的是json模块序列化出来的是通用格式,其它编程语言都认识,就是普通的字符串

  • pickle模块序列化出来的只有python可以认识,其他编程语言不认识的,表现为乱码

  • pickle可以序列化函数,但是其他文件想用该函数,在该文件中需要有该文件的定义(定义和参数必须相同,内容可以不同)

  • pickle.dump(obj, file, protocol=None)

必填参数obj表示将要封装的对象

必填参数file表示obj要写入的文件对象,file必须以二进制可写模式打开,即“wb”

可选参数protocol表示告知pickler使用的协议,支持的协议有0,1,2,3,默认的协议是添加在Python 3中的协议3。

  • pickle.load(file,*,fix_imports=True, encoding=“ASCII”, errors=“strict”)

必填参数file必须以二进制可读模式打开,即“rb”,其他都为可选参数

import pickle

dict_var = {
    'name': 'Cactus', 
    'age': 18, 
    'skills': ['Python', 'Java', 'Go', 'NodeJS'], 
    'has_blog': True, 
    'gf': None
}
# dump 将数据通过特殊的形式转换为只有python语言认识的字符串,并写入文件
with open('demo3.pk', 'wb') as f:
     pickle.dump(dict_var, f)
with open('demo3.pk', 'rb') as f:
     data = pickle.load(f)
print (data)
{'name': 'Cactus', 'age': 18, 'skills': ['Python', 'Java', 'Go', 'NodeJS'], 'has_blog': True, 'gf': None}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值