7.1 文件操作

所谓文件是指存储在硬盘上的各种文件,Python所读取的数据文件通常为文本格式,即可以使用文本编辑器来打开阅读。对于数据分析任务而言,数据文件是最为常见的数据获取途径。

1)数据文件

在讲解数据文件处理之前,先需要对数据文件做下说明。由于数据文件通常都很大,因此不建议大家直接使用Windows系统自带的记事本来打开,而可以尝试使用Sublime或者Editplus等专业文本编辑器。尤其是后者是免费软件,可以直接下载:

Sublime Text - Text Editing, Done RightSublime Text is a sophisticated text editor for code, markup and prose. You'll love the slick user interface, extraordinary features and amazing performance.https://www.sublimetext.com/

其次,数据文件未必一定表现的像一般的文本文件,在Windows中只有txt扩展名的文件才被默认看成是文本格式文件。如果更换了默认的扩展名,此时双击将不会自动使用记事本等文本编辑器打开,因此可以手工强行使用文本编辑器打开。

比如对于这个数据文件(下面练习会使用),存储的是用户对电影的评分信息:

电影评分数据文件https://www.njcie.com/python/pbda-data/7/u.zip下载后双击可能无法打开,或者打开了其他一些应用程序。

正确的打开方式是右击选择“Open with Sublime Text”:

打开效果为:

从中可以看出,Python所读取的数据文件就是文本格式,通常都采取一行表示一条记录,一行由多列组成,每列之间使用逗号、Tab或者空格分隔等形式。

2)文件读取

为方便处理,现将该数据文件 u.data 放在 C 盘的 temp 目录下。打开文件的代码为:

f = open('C:\\temp\\u.data')
print(f.read())
f.close()

输出内容很多,就是全部的文件内容。open函数可以打开文件,并创建文件类对象f,通过read方法获取全部数据,在文件访问完后,要及时使用close方法关闭文件。

更为简单常见的打开文件方法是:

with open('C:\\temp\\u.data') as f:
    print(f.read())

效果一样,但是代码更简洁,而且还具有文件读取错误检测和处理完文件自动关闭的功能。

接来下,读取一行:

with open('C:\\temp\\u.data') as f:
    print(f.readline())

输出为:uid mid rating  timestamp,readline表示读取一行,这个第一行是标题行。

利用循环还可以读取多行:

with open('C:\\temp\\u.data') as f:
    for i in range(5):
        print(f.readline())

输出为:
uid mid rating  timestamp

196 242 3   881250949

186 302 3   891717742

22  377 1   878887116

244 51  2   880606923


有了这些练习的基础,让我们来读取每行记录,并在首部增加一个从1开始累加的序号:

with open('C:\\temp\\u.data') as f:
    i = 1
    while True:  # 反复循环,直至break退出
        line = f.readline()  # 读取下一行
        if not line:  # 如果读取完毕
            break
        print(str(i) + '\t' + line)  # 输出
        i += 1

输出的最后几行为:
99996   880 476 3   880175444

99997   716 204 5   879795543

99998   276 1090    1   874795795

99999   13  225 2   882399156

100000  12  203 3   879959583

这个循环读取的方式反复读取数据文件,一旦读取失败将会使得line字符串为空(Null),因此通过检测是否为空决定是否退出循环。读取的每一行都在输出前增加了一个不断累加的变量值,实现累加序号输出的效果。

也可以写为:

with open('C:\\temp\\u.data') as f:
    i = 1
    for line in f.readlines():
        print(str(i) + '\t' + line)
        i = i + 1

输出内容一样,readlines方法返回的是所有记录结果的字符串列表,因此无需判断是否需要结束文件读取。

虽然这些方法可以读取,但是该练习存在一个问题,总是在输出各行时,在每行间增加了一个空行。具体原因在于原始数据文件的每行结尾本来就有一个换行符,再加上print函数默认的输出完自动换行,导致了两次换行。

解决方法1:去除读取的每行尾的换行符:

with open('C:\\temp\\u.data') as f:
    i = 1
    for line in f.readlines():
        print(str(i) + '\t' + line.strip())
        i = i + 1

解决方法2:取消print函数自动换行功能:

with open('C:\\temp\\u.data') as f:
    i = 1
    for line in f.readlines():
        print(str(i) + '\t' + line, end='')
        i = i + 1

这些读取方法虽然可行,但是对于更大规模的数据文件而言,就可能存在读取性能低下的问题。因此,有时就需要采取一些读取性能更高的做法:

with open('C:\\temp\\u.data') as f:
    i = 1
    while True:  # 反复循环,直至break退出
        lines = f.readlines(10000)  # 一次读取1万行
        if not lines:  # 如果读取完毕
            break
        for line in lines:
            print(str(i) + '\t' + line.strip())  # 输出
            i += 1

该代码输出内容一样。只是采取了一种称为“块读取”的方式,即一下读取多行记录。之所以能提升性能,主要原因在于读取文件需要访问硬盘等外存,这个读取本身相对很慢,不断的反复的访问硬盘往往会降低性能,所以要通过增大一次读取的数量和减少读取的频次,综合提高读取性能。这里一次读取为 1 万行,实际操作中可以根据情况灵活选择。

最后强调下含有中文信息的文件读取,有时文件名称和内容中存在中文字符,就需要指定字符集才能正确读取,如该数据文件含有中文:

文章关键词数据(中文)icon-default.png?t=M1L8https://www.njcie.com/python/pbda-data/7/doc_kw.zip读取方法为:

with open('doc_kw.dat', encoding='UTF-8') as f:
    for i in range(5):
        print(f.readline().strip())

如果仍然存在字符集错误,可以尝试使用“UTF-8”、“GB2312”或者“GBK”中任意一个来替换现有的encoding属性值。

3)文件写入

先来看新建文件并写入:

with open('C:\\temp\\exec.txt', 'w') as f:
    f.write('Hello!')

此时将会在 C 盘 temp 目录下建立一个 temp 文件夹,并生成一个 exec.txt 文件,内容就是“Hello”。open函数的第二个参数需要设定为写入模式 w(表示write,写入的意思),调用write方法将文本写入文件。注意,多次运行,该文件内容仍然还是不变,因为每次运行都会自动清空原有文件内容,这是 w 模式的特点。

要想实现追加写入,代码为:

with open('C:\\temp\\exec.txt', 'a') as f:
    f.write('Hello!')

该文件打开模式为 a(表示append,追加的意思) ,因此反复运行这段代码,可以发现文件中的“Hello!”出现次数会越来越多。

默认情况下,追加总是在文件的最后添加内容。通过写入重定位,可以在文件中间任意位置追加内容。比如在文件最前面增加一个标题行:

with open('C:\\temp\\u.data', 'r+') as f:
    old = f.read()
    f.seek(0)
    f.write('uid\tmid\trating\ttimestamp\n')
    f.write(old)

文件打开模式采取了 r+ 表示读写模式,请注意 w+ 也是读写模式,但是会首先清空文件。使用seek可以进行定位,0表示重新定位到文件开头,此时写入就会从第一行开始。请注意,如果没有最后的写回原有数据的语句,将会导致开头写入的内容会覆盖部分起始内容,然后仍然是剩下的原始数据文件内容,原始数据将会丢失部分开头内容。

当然,seek 也可以实现在文件中间插入数据,不过建议大家考虑将文件数据全部读出,然后对该数据进行插入更新操作,最终一起整体写入文件,相对更为简单方便。

配套学习资源、慕课视频:

Python大数据分析-李树青icon-default.png?t=M1L8https://www.njcie.com/python/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leeshuqing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值