Python文件和数据格式化
(1).文件的使用
1)文件的类型
文件是数据的抽象和集合,可以理解为文件是存储在辅助存储器上的数据序列,是数据存储的一种形式。具体来说,文件都是以二进制方式来存储的,但是它有不同的展现形态。在程序设计中一般有两种展现形态,分别叫文本文件和二进制文件。
文本文件和二进制文件只是文件的展示方式。从本质上来讲,所有文件都是以二进制形式存储在计算机上。但是形式上我们将存储的文件由程序读出进行使用时,那么文件就可以采用文本方式或二进制方式进行处理。这两种方式其实可以应用于任何文件上,但是有些文件天然是文本文件,有些文件天然是二进制文件。
因为文件是数据的抽象和集合,如果这些数据是由单一特定编码组成,那这样的文件就是文本文件,比如我们使用UTF-8编码将所有的信息进行组织,并且在一个文件中只用这样的编码去存储数据,那么这样的文件就叫文本文件。由于存在编码,文本文件也被看成是存储着的长字符串,简单来说,文本文件就是一个字符串,比如WIndows系统中的.txt文件、Python的源文件.py文件等。
二进制文件是指直接由比特0、1构成的文件,而在这个文件中,数据之间没有使用统一的字符编码。在这样的文件中,一般0、1是根据一些预定义的格式进行了结构组织,它形成了一些特定的文件类型,比如.png文件、.avi文件等,它们本身就是有很多的0、1按照特定的方式进行组织,对于这些0、1之上是不存在任何编码,这类文件就叫二进制文件。
所有文件都是以二进制0、1形式存储,有统一编码的称之为文本文件,没有统一编码的称之为二进制文件,但是无论什么类型的文件都可以以二进制方式打开。
2)文件的打开和关闭
Python和其他语言类似,在处理文件时遵循一个特定的步骤:打开-操作-关闭。
对于一个文件,如果不对它进行处理的时候,它体现的是一个文件的存储状态,此时文件在计算机的硬盘中存储。如果一个程序想处理一个文件,首先要使这个文件变成占用状态,在占用状态中,一个程序可以唯一的、排它的对文件进行相关的处理。那么文件的存储状态和文件的占用状态之间通过文件的打开和关闭进行转换,所以在文件处理之间我们需要对文件进行打开,处理完成后我们需要对文件进行关闭。在打开文件之后,我们可以对文件进行数据读入和数据输出,简称为读文件和写文件。
Python提供了三个常用的读文件函数,分别是read(size)、readline(size)和readlines(hint)。也提供了三个常用的写文件函数,分别是write(s)、writelines(lines)和seek(offset)。
A.文件的打开
打开一个文件使用open(<文件名>,<打开模式>)函数,<文件名>参数是文件的路径和名称,指的是当前要打开的文件与当前程序所对应的位置之间的关系;<打开模式>参数是打开模式,包括以文本形式打开,或以二进制形式打开,打开的过程是读信息还是写信息。
使用open()函数打开文件后,将其赋给一个变量名,这个变量名被称之为文件句柄。
A-1.<文件名>参数
<文件名>参数是文件的路径和名称,可以是文件的绝对路径和名称,也可以是文件的相对路径和名称。
举个例子:比如有一个文件在Windows平台上保存在D:\PYE\f.txt,我们在使用open()函数打开这个文件的时候,需要指定这个路径,那么它可以有四种表达方式。第一种方式,我们直接给出当前文件的绝对路径,但是需要注意Python中\表示转义,所以需要使用\\转义为\,所以<文件名>参数实际为"D:\\PYE\\f.txt";第二种方式,也是使用绝对路径,但是我们使用/来代替\,所以<文件名>参数实际为"D:/PYE/f.txt";第三种方式,使用相对路径,如果当前的程序在D:\目录下,那么<文件名>参数实际为"./PYE/f.txt";第四种方式,使用相对路径,如果当前程序在D:\PYE\目录下,那么<文件名>参数实际为"f.txt"。
无论采用哪种方式,最终目的是要让程序在它运行的当前目录下,能够很好的或者有效的找到这个文件。无论是绝对路径还是相对路径,只要能够找到这个文件,并且指定正确的文件名称,那么读取这个文件就会比较顺利
A-2.<打开模式>参数
Python语言提供了7种<打开模式>,它们之间并不是完全排它的。
文件的打开模式 | 描述 |
'r' | 只读模式,默认值,如果文件不存在,返回FileNotFoundError异常 |
'w' | 覆盖写模式,如果文件不存在则创建,如果文件存在则覆盖文件原有内容 |
'x' | 创建写模式,如果文件不存在则创建,如果文件存在则返回FileExistsError异常 |
'a' | 追加写模式,如果文件不存在则创建,如果文件存在则在文件最后增加内容 |
'b' | 二进制文件模式,即以二进制形式打开文件 |
't' | 文本文件模式,默认值,即以文本形式打开文件 |
'+' | 与r/w/x/a一起使用,在原有的功能基础上扩展为同时具备读写功能 |
文本形式和二进制形式:比如一个文件“中文测试.txt”,内容是一段字符串“中国是个伟大的国家!”,我们可以用文本形式理解它,也可以用二进制形式理解它。以文本形式理解它的时候,这个字符串使用了统一的编码,如果此时使用print函数将它打印(print(open("中文测试.txt","rt").read())),那么输出的结果就是“中国是个伟大的国家!”这样一段汉字。但是如果我们以二进制形式理解它,使用print函数将它打印(print(open("中文测试.txt","rb").read())),那么它返回的是一串由二进制构成的字符串“b'\xd6\xd0\xb9\xfa\xca\xc7\xb8\xf6\xce\xb0\xb4\xf3\xb5\xc4\xb9\xfa\xbc\xd2\xa3\xa1'”,简单说返回的是“中国是个伟大的国家!”对应的存储形态的二进制形式。
显然我们使用的时候,通过文本形式可以更好的理解这段信息,而二进制形式是它最原始的存储格式。所以在使用时,一个文件是文本文件,我们又需要对它里面的字符进行理解,那么我们就要用文本形式将它打开,如果我们仅仅需要使用它的存储形式,我们就用二进制形式将它打开并处理。
<打开模式>参数实例:
f=open("f.txt") #使用文本形式、只读模式这两个默认参数 f=open("f.txt","rt") #同上 f=open("f.txt","w") #文本形式、覆盖写模式 f=open("f.txt","a+") #文本形式、追加写模式和读模式 f=open("f.txt","x") #文本形式、创建写模式 f=open("f.txt","b") #二进制形式、只读模式 f=open("f.txt","wb") #二进制形式、覆盖写模式
B.文件的关闭
关闭一个文件使用<变量名>.close()函数,没有任何参数,<变量名>是打开时的文件句柄。
注意:如果一个程序中打开一个文件,而始终没有使用close()函数去关闭这个文件,那么在程序运行时这个文件始终是被打开状态,但是当程序退出,那么Python解释器会自动的将这个文件关闭。
3)文件内容的读取
Python提供了三个文件内容读取的方法,分别是.read、.readline和.readlines。
操作方法 | 描述 |
<f>.read(size=-1) |
默认读入文件全部内容,如果给出size参数具体值,那么读入文件中前size长度的字符信息 (注意:当存在文件句柄时,存在指针) >>> open("中文测试.txt").read(2) |
<f>.readline(size=-1) |
默认从文件中读入一行,如果给出size参数具体值,那么读入该行的前size长度的字符信息 >>> open("中文测试.txt").readline() |
<f>.readlines(hint=-1) |
默认读入文件所有行,以每一行为一个元素形成一个列表,每一个元素是一个字符串。 如果给出hint参数具体值,那么读入文件前hint行 >>> open("中文测试.txt").readlines() |
遍历文件实例:
#遍历全文本方法一。特点:一次读入,统一处理;弊端:如果文本文件特别大,一次性读入将会耗费非常多的时间和资源。 fname=input("请输入要打开的文件名称:") fo=open(fname,"r") txt=fo.read() #整个文件变成一个大的字符串 #省略对全文txt进行处理的步骤 fo.close() #遍历全文本方法二。特点:分阶段按数量读入,逐步处理,对于处理大文件这种方法更有效。 fname=input("请输入要打开的文件名称:") fo=open(fname,"r") txt=fo.read(2) while txt != "": #省略对全文txt进行处理的步骤 txt=fo.read(2) fo.close() #逐行遍历文件方法一。特点:一次读入,分行处理;弊端:如果文本文件特别大,一次性读入将会耗费非常多的时间和资源 fname=input("请输入要打开的文件名称:") fo=open(fname,"r") for line in fo.readlines(): #省略对全文txt进行处理的步骤 fo.close() #逐行遍历文件方法二。特点:分行读入,逐行处理 fname=input("请输入要打开的文件名称:") fo=open(fname,"r") for line in fo: #省略对全文txt进行处理的步骤 fo.close()
4)文件写入数据
Python提供了两种数据写入文件的方法以及一种辅助函数。
操作方法 | 描述 |
<f>.write(s) | 向文件写入一个字符串或一个字节流s |
<f>.writelines(lines) | 将一个元素全为字符串的列表lines,拼接成一行后直接写入文件,中间没有分隔符 |
<f>.seek(offset) |
用来改变当前文件操作指针位置的函数。offset有三个参数:0表示文件处理指针直接回到文件的开始处; 1表示文件处理指针回到文件的当前位置;2表示文件处理指针直接回到文件的结尾处 |
实例:
#实例一 fo=open("output.txt","w+") ls=["中国","美国","日本"] fo.writelines(ls) for line in fo: print(line) fo.close() #输出结果为空,因为数据在写入文件后,当前文件处理的指针处于写入的数据的结尾处,无法获取前面的数据,所以有了实例二。 #实例二,将实例一进行修改,打印文件修改后的信息 fo=open("output.txt","w+") ls=["中国","美国","日本"] fo.writelines(ls) fo.seek(0) #指针回到文件开始位置 for line in fo: print(line) fo.close() #此时输出结果为:中国美国日本
(2).一维数据的格式化和处理
1)数据组织的维度
从一个数据到一组数据,这是编写程序或者理解世界的一个很重要的跨度。一个数据表达一个含义,一组数据表达一个或多个含义。
对于一组数据,我们是采取线性方式(一维)进行组织,还是采用二维方式进行组织或者多为方式进行组织,这就能构成不同的数据组织形式。
其中,一维数据是由对等关系的有序或无序数据构成,采用线性方式组织。一维数据对应了传统Python程序中的列表、数组和集合等类型的概念。二维数据是由多个一维数据构成,是一维数据的组合形式,并且在生活中非常常见,比如:排行榜。进一步还有多维数据,它是由一维或二维数据在新的维度上的一种扩展二形成的,比如:排行榜已经是二维数据,但是当加入了时间维度,就构成了多维数据。除了一维数据、二维数据和多维数据之外,数据组织还有一种高维组织方式,它仅利用最基本的二元关系,来展示数据间的复杂结构,最常见的就是字典,如下:
对于数据来讲,还存在一个操作周期的概念。由于数据必须存在才能处理,所以将数据分为数据存储、数据表示和数据操作三个阶段。数据存储指的是数据在磁盘中的存储状态,在这一部分我们关心的是数据存储所使用的的格式。数据表示指的是程序表达数据的方式,在这一部分我没关心的是数据类型。如果数据能够由程序中的数据类型进行很好的表达,我们就可以借助这样的数据类型对数据进行操作,具体操作体现在相关的操作方式和算法。
2)一维数据的表示
如果一维数据之间存在顺序,我们可以使用列表类型来表达一维数据。列表类型是表达一维数据,尤其是一维有序数据最合理的数据结构。
如果一维数据之间没有顺序,我们可以使用集合类型来表达一维数据。集合类型是表达一维无序数据最好的结构。
我们可以使用for循环遍历一维数据,进而对每个数据进行处理。
3)一维数据的存储
我们将一维数据存储在硬盘上或者存储在文件中有很多种方式,其中最简单的方式是把数据之间采用空格进行分隔,即使用一个或多个空格分隔数据并且进行存储,只用空格分隔,不换行,这是一种简单的一维数据存储方式。
同理,我们可以将空格替换为任意一个字符或多个字符来作为分隔符,但需要保存数据中不存在改分隔符,这也是它的缺点。
4)一维数据的处理
这里的一位数据的处理指的是数据存储与数据表示之间的转换,也就是说就是如何将存储的一维数据读入程序并表达为列表或集合,或者反过来,如何将程序表示的数据写入到文件中。
从文件中读取一维数据:
#文件内容为“中国 日本 美国 法国 德国 英国” f=open("data.txt") str=f.read() ls=str.split() f.close() print(ls) #输出结果为['中国', '日本', '美国', '法国', '德国', '英国'] #文件内容为“中国n$n日本$n美国$n法国$n德国$n英国” f=open("data.txt") str=f.read() ls=str.split('$n') f.close() print(ls) #输出结果为['中国n', '日本', '美国', '法国', '德国', '英国']
将程序的一维数据写入到文件:
ls=['中国','美国','日本'] f=open("data.txt","w") f.write(' '.join(ls)) #join()函数是将前面的字符串作为分隔符添加到后面的字符串的字符之间(或列表的元素之间) f.close() #文件内容变为“中国 美国 日本” ls=['中国','美国','日本'] f=open("data.txt","w") f.write('$n'.join(ls)) f.close() #文件内容变为“中国$n美国$n日本”
(3).二维数据的格式化和处理
1)二维数据的表示
二维数据一般是一种表格形式,由于它的每一行具有相同的格式特点,一般采用列表类型来表达二维数据,这里所说的列表是二维列表。二维列表指的是它本身是一个列表,而列表中的每一个元素又是一个列表,其中每一个元素可以代表二维数据的一行或一列,若干行和若干列组织起来形成的外围列表就构成了二维列表。
在Python中表达二维数据一般采用二维列表,但在数据分析或大数据处理时,还有更高级或更有效的结构来表示二维数据。
使用二维列表表达二维数据时,可以使用两层for循环遍历每一个元素。在外围列表中,每一个元素可以对应二维数据的一行,也可以对应一列,具体对应一行还是一列,要根据具体应用用程序确定。
2)CSV数据存储格式与二维数据的存储
CSV全称Comma-Separated Values,指的是由逗号分隔的值,简单来说就是用逗号来分隔值的一种存储方式。用逗号来分隔值,是国际通用的一种一、二维数据存储格式,一般这样的文件以.csv作为扩展名,其中每行是一个一维数据,采用逗号来分隔,并且文件中没有空行,那么不同行就构成了另一个维度。
CSV文件可以使用Office Excel软件打开,并且保存。另外,一般的编辑软件都可以生成或转换为CSV格式。CSV格式是数据转换之间的通用的标准格式。如图,将表格转换为CSV格式。
在CSV数据存储格式中还有一些约定:1.如果某个元素在二维数据中缺失了,那么必须要为它保留一个逗号;2.在二维数据的表中,它的表头可以作为数据存储,也可以另行存储;3.逗号是英文半角逗号,逗号与数据之间没有额外的空格;4.二维数据可以按行存,也可以按列存,具有由程序决定,但是默认是先行后列,即外围列表的每一个元素是一行;5.在不同的编辑软件中转换CSV格式,当元素中需要包含逗号时,那么可能会在元素两端出现引号包裹,也可能采用转义符,需要按照实际情况进行处理。
3)二维数据的处理
从CSV格式的文件读入数据:
#读入文件内容为 #中国,日本,朝鲜,韩国 #法国,德国,意大利,俄罗斯 fo=open("测试文件.csv") ls=[] for line in fo: line=line.replace("\n","") ls.append(line.split(",")) fo.close() print(ls) #输出结果为[['中国', '日本', '朝鲜', '韩国'], ['法国', '德国', '意大利', '俄罗斯']]
将保存在列表中二维数据写入csv文件中:
ls=[['中国', '日本','韩国'],['美国','加拿大','古巴']] fo=open("测试文件.csv","w") for item in ls: fo.write(','.join(item)+'\n') f.close() #文件内容变为 #中国,日本,韩国 #美国,加拿大,古巴
二维数据的逐一处理:
ls=[[1,2],[3,4],[5,6]] for row in ls: for column in row: print(column,end=" ") #输出结果为1 2 3 4 5 6