⛄前言

CSVComma-Separated Values,逗号分隔值,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。CSV文件通常以 .csv 作为文件扩展名。

XLS就是Microsoft Excel工作表,是一种非常常用的电子表格格式。xls文件可以使用Microsoft Excel打开,另外微软为那些没有安装Excel的用户开发了专门的查看器Excel Viewer。使用Microsoft Excel可以将XLS格式的表格转换为多种格式:XML表格、XML数据、网页、使用制表符分割的文本文件(.txt)、使用逗号分隔的文本文件(.csv)等。

XLSXMicrosoft Office EXCEL 2007/.../2019文档及以上的扩展名。其基于Office Open XML标准的压缩文件格式取代以前专有的默认文件格式,在传统文件名扩展名后面添加字母”x“(即.docx取代.doc.xlsx取代.xls.pptx取代.ppt)。任何能够打开.xlsx文件的文字处理软件都可以将该文档转换为.xls文件,.xlsx文件比.xls文件所占用空间更小。

xlsx格式文档文件无法被EXCEL2003及以下版本EXCEL软件直接打开编辑,安装OFFICE2007兼容包后可以打开查看。手动将XLSX文件后缀修改为XLS无法改变文档文件的本质属性,是不能被EXCEL2003等低版本EXCEL直接打开编辑的。用户可在EXCEL软件成功打开EXCEL2007专有XLSX格式文档的前提下,采用另存为方式将其转换为EXCEL97—2003格式文档的XLS文件这样可与旧的版本兼容,但一些EXCEL2007文档专有的特性格式可能丢失。Excel xlsxlsx的详细区别如下:

  • 文件格式不同xls是一个特有的二进制格式,其核心结构是复合文档类型的结构,而xlsx的核心结构是XML类型的结构,采用的是基于XML的压缩方式,使其占用的空间更小。xlsx中最后一个x的意义就在于此。
  • 版本不同xlsexcel2003及以前版本生成的文件格式,不管有没有宏程序的话都是xls文件,而xlsxexcel2007及以后版本生成的文件格式,从2007开始做了区分,XLSM文件和XLSX文件都是excel2007及其以后的文件,但前者是含有宏启用,Excel中默认情况下不自动启用宏,默认是XLSXVBA中,如果不想保存代码,可以保存为xlsx,即可自动删除其中VBA代码,反之则保存为XLSM文件。
  • 兼容性不同xlsx格式是向下兼容的,可兼容xls格式。07版的Office Excel,能打开编辑07版(后缀.xlsx)的Excel文件,也能打开编辑03版(后缀.xls)的Excel文件,都不会出现乱码或者卡死的情况。03版的Office Excel,就只能打开编辑03版(后缀.xls)的Excel文件;如果打开编辑07版(后缀.xlsx)的Excel文件,则可能出现乱码或者开始能操作到最后就卡死,以后一打开就卡死。
  • 默认保存方式上xls是03版Microsoft Office Excel 工作表的格式,用03版Office,新建Excel默认保存的Excel文件格式的后缀是.xlsxlsx是07版Microsoft Office Excel 工作表的格式,用07版Office,新建Excel默认保存的的Excel文件格式后缀是.xlsx
  • 容量不同xls只有65536行、256列;xlsx可以有1048576行、16384列

JSONJavaScript Object Notation, JS对象简谱)是一种轻量级的数据交换格式。它基于 ECMAScript(欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

XML (Extensible Markup Language, 可扩展标记语言) ,标准通用标记语言的子集,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言可扩展性良好,内容与形式分离,遵循严格的语法要求,保值性良好等优点。

TXT文件是微软在操作系统上附带的一种文本格式,是最常见的一种文件格式,早在DOS时代应用就很多,主要存储文本信息,即为文字信息,现在的操作系统大多使用记事本等程序保存,大多数软件可以查看,如记事本,浏览器等等。

⛄Python之读写文件

👀CSV

(1)CSV库读取

csv.reader:以列表的形式返回读取的数据;
csv.writer:以列表的形式写入数据;
csv.DictReader:以字典的形式返回读取的数据;
csv.DictWriter:以字典的形式写入数据。

import csv
with open(r"D:\Desktop\data.csv") as file:
reader = csv.reader(file)
print(reader)
print("*"*20)
# 用next()函数读取文件时:如果只执行一次默认读取第一行。
headers = next(reader)
print(headers)
print("*"*20)
for row in reader:
print(row)
print(row[2])

# 输出结果
<_csv.reader object at 0x000001D6B95F1668>
********************
['name', 'gender', 'age', 'hobby']
********************
['小红', '女', '20', '跑步']
20
['小汤', '男', '22', '篮球']
22
['小李', '男', '24', '足球']
24

namedtuple(具名元组),因为元组的局限性:不能为元组内部的数据进行命名,所以往往我们并不知道一个元组所要表达的意义,在这里引入了collections.namedtuple 这个工厂函数,来构造一个带字段名的元组。具名元组的实例和普通元组消耗的内存一样多,因为字段名都被存在对应的类里面。

# 获取一行数据中的某一列数据
import csv
from collections import namedtuple
with open(r"D:\Desktop\data.csv") as file:
reader = csv.reader(file)
print(reader)
print("*"*20)
headers = next(reader)
# namedtuple(具名元组)返回一个具名元组子类 typename
Row = namedtuple('Row', headers)
print(headers)
print("*"*20)
for row in reader:
# 列表或元组前面加星号作用是将列表解开成两个独立的参数;
# 字典前面加两个星号,是将字典的值解开成独立的元素作为形参。
row = Row(*row)
# 获取一行数据中的某一列数据。
print(row.name,row.age)

# 输出结果
<_csv.reader object at 0x000001D6B95F1128>
********************
['name', 'gender', 'age', 'hobby']
********************
小红 20
小汤 22
小李 24

简单使用csv.DictReader

可以深入了解该函数的参数:

  • csv.DictReader()fieldnames参数
  • csv.DictReader()restkey参数
  • csv.DictReader()restval参数
import csv
with open(r"D:\Desktop\data.csv") as file:
'''
# 如果没有字段名,参数fieldnames
reader = csv.DictReader(file,fieldnames = ['name','gender','age','hobby'])
# next()方法用于移动指针
head_row = next(reader)
'''
reader = csv.DictReader(file)
print(reader)
print("*"*20)
for row in reader:
# OrderedDict是一种长相类似于列表的数据类型,该列表中嵌套着元组;
# 每个元组中的第一个元素为键,第二个元素为值(类似于字典)
print(row)
print(row["name"],row["hobby"])

# 输出结果
<csv.DictReader object at 0x000001D6B95F0388>
********************
OrderedDict([('name', '小红'), ('gender', '女'), ('age', '20'), ('hobby', '跑步')])
小红 跑步
OrderedDict([('name', '小汤'), ('gender', '男'), ('age', '22'), ('hobby', '篮球')])
小汤 篮球
OrderedDict([('name', '小李'), ('gender', '男'), ('age', '24'), ('hobby', '足球')])
小李 足球

(2)CSV库写入

csv.reader:以列表的形式返回读取的数据;
csv.writer:以列表的形式写入数据;
csv.DictReader:以字典的形式返回读取的数据;
csv.DictWriter:以字典的形式写入数据。

import csv
# 1. 创建文件对象(指定文件名,模式,编码方式),指定下次写入在这次的下一行
# 注意引入newline="",不然加入的数据会空一行
with open(r"D:\Desktop\data.csv", "a+", encoding="gbk", newline="") as f:
# 2. 基于文件对象构建 csv写入对象
csv_writer = csv.writer(f)
# 3. 构建列表头
# name = ['name','gender','age','hobby']
# csv_writer.writerow(name)
# 4. 写入csv文件内容
z = [["小ai", "男", 21, "篮球"],["小张", "男", 25, "篮球"]]
csv_writer.writerows(z)
with open(r"D:\Desktop\data.csv", "r+", encoding="gbk", newline="") as f:
reader = csv.reader(f)
headers = next(reader)
for row in reader:
print(row)

# 输出结果
['小红', '女', '20', '跑步']
['小汤', '男', '22', '篮球']
['小李', '男', '24', '足球']
['小ai', '男', '21', '篮球']
['小张', '男', '25', '篮球']

如果csvfile是文件对象,则打开它时应使用newline=""。如果没有指定newline="",则嵌入引号中的换行符将无法正确解析,并且在写入时,使用\r\n换行的平台会有多余的\r写入。由于csv模块会执行自己的(通用)换行符处理,因此指定newline=""应该总是安全的。

open()完成后必须调用close()方法关闭文件,因为文件对象会占用操作系统资源,并且操作系统同一时间能打开的文件数量也是有限的。由于文件读写时有可能产生IOError,一旦出错,后面的f.close()就不会调用。with open()则可以避免这样的情况。

模式 描述
t 文本格式打开文件(默认)。一般用于文本文件,如:txt
b 二进制格式打开文件。一般用于非文本文件,如:图片。
r 只读方式打开文件(默认模式)。文件的指针将会放在文件的开头,如果文件不存在会报错
w 只写方式打开文件。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,则创建新文件。
a 追加方式打开文件,同样是只写,不允许进行读操作。如果文件已存在,文件指针将会放在文件的结尾,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+ 打开一个文件用于读写。如果文件存在,则打开文件,将文件指针定位在文件头,新写入的内容在原有内容的前面;如果文件不存在会报错。
w+ 打开一个文件用于读写。如果文件存在,则打开文件,清空原有内容,进入编辑模式;如果文件不存在,则创建一个新文件进行读写操作。
a+ 以追加模式打开一个文件用于读写。如果文件存在,则打开文件,将文件指针定位在文件尾,新写入的内容在原有内容的后面;如果文件不存在,则创建一个新文件用于读写。
rb 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。一般用于非文本文件如图片等。
wb 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
ab 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb+ 以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。一般用于非文本文件如图片等。
wb+ 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如图片等。
ab+ 以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。

csv库常见的问题

  • csv.DictWriter():该函数返回的结果遍历一次之后,再次遍历返回的结果是空列表。
  • csv.reader():返回的结果是结构体,需要for循环才能调用,不能像list那样直接选取特定单元格。
  • 通过列名来查找指定列的操作麻烦。

(3)pandas库读取

使用pandas读取csv文件的优势:

  • 方便,有专门支持读取csv文件的pd.read_csv()函数;
  • csv转换成二维列表形式;
  • 支持通过列名查找特定列;
  • 相比csv库,事半功倍。
pandas.read_csv(filepath_or_buffer, sep=, delimiter=None, header=‘infer’, names=None, index_col=None, usecols=None, squeeze=False, prefix=None, mangle_dupe_cols=True, dtype=None, engine=None, converters=None, true_values=None, false_values=None, skipinitialspace=False, skiprows=None, skipfooter=0, nrows=None, na_values=None, keep_default_na=True, na_filter=True, verbose=False, skip_blank_lines=True, parse_dates=False, infer_datetime_format=False, keep_date_col=False, date_parser=None, dayfirst=False, cache_dates=True, iterator=False, chunksize=None, compression=‘infer’, thousands=None, decimal=’.’, lineterminator=None, quotechar='"', quoting=0, doublequote=True, escapechar=None, comment=None, encoding=None, dialect=None, error_bad_lines=True, warn_bad_lines=True, delim_whitespace=False, low_memory=True, memory_map=False, float_precision=None, storage_options=None)

# 常用参数详解
1)filepath_or_buffer:必须有的参数,其它都是按需求选用的。文件所在处的路径。
2)sep:指定分隔符,默认为逗号','
3)delimiter:str/default/None,定界符,备选分隔符(如果指定该参数,则sep参数失效)
4)header:int or list of ints, default ‘infer’,指定哪一行作为表头。默认设置为0(即第一行作为表头),如果没有表头的话,要修改参数,设置header=None
5)names:指定列的名称,用列表表示。一般我们没有表头,即header=None时,这个用来添加列名就很有用啦。
6)index_col:指定哪一列数据作为行索引,可以是一列,也可以多列。多列的话,会看到一个分层索引。
7)squeeze:布尔值,默认为False。如果解析的数据仅包含一列,则返回一个Series。
8)prefix:给列名添加前缀。如prefix="x",会出来"x1""x2""x3"
9)nrows:int, default None。需要读取的行数(从文件头开始算起)。
10)encoding:编码方式。
11)skiprows:list-like or integer, default None。在文件开始处要跳过的行号(索引为0)或要跳过的行数(整数)。
......
import pandas as pd
df = pd.read_csv(r"D:\Desktop\data.csv",encoding="gbk")
print(df)
print("*"*20)
print(df.index.values)
print(df.columns.values)
print(df.values)
# 通过位置选取
print("="*20)
print(df.iloc[:,0:3].values)
print(type(df.iloc[:,0:3].values))
print(df.iloc[:,0:3].values.tolist())
print(type(df.iloc[:,0:3].values.tolist()))
# 通过标签选取
print("-"*20)
print(df.loc[[0,3],["name","hobby"]].values)

# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
********************
[0 1 2 3 4]
['name' 'gender' 'age' 'hobby']
[['小红' '女' 20 '跑步']
['小汤' '男' 22 '篮球']
['小李' '男' 24 '足球']
['小ai' '男' 21 '篮球']
['小张' '男' 25 '篮球']]
====================
[['小红' '女' 20]
['小汤' '男' 22]
['小李' '男' 24]
['小ai' '男' 21]
['小张' '男' 25]]
<class 'numpy.ndarray'>
[['小红', '女', 20], ['小汤', '男', 22], ['小李', '男', 24], ['小ai', '男', 21], ['小张', '男', 25]]
<class 'list'>
--------------------
[['小红' '跑步']
['小ai' '篮球']]

(4)pandas库写入

DataFrame.to_csv(path_or_buf=None, sep=',', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, mode='w', encoding=None, compression='infer', quoting=None, quotechar='"', lineterminator=None, chunksize=None, date_format=None, doublequote=True, escapechar=None, decimal='.', errors='strict', storage_options=None)

# 常用参数详解
1)path_or_buf:字符串,放文件名、相对路径、文件流等。
2)sep:字符串,分隔符,跟read_csv()的一个意思。
3)na_rep:字符串,将NaN转换为特定值。
4)columns:列表,指定哪些列写进去。
5)header:默认header=0,如果没有表头,设置header=None,表示我没有表头呀!
6)index:关于索引的,默认True,写入索引
7)mode:{‘w’, ‘x’, ‘a’}, default ‘w’,写入方式。
8)encoding:编码方式。
......
import pandas as pd
name = ["小小","小耿"]
gender = ["男","男"]
age = [20,25]
hobby = ["跳绳","羽毛球"]

dict_data = {"name":name,"gender":gender,"age":age,"hobby":hobby}
df1 = pd.DataFrame(dict_data)
# mode = "a"为追加数据,index为每行的索引序号,header为标题
df1.to_csv("D:\Desktop\data.csv",mode="a",index=False,header=False,encoding="gbk")
df2 = pd.read_csv(r"D:\Desktop\data.csv",encoding="gbk")
print(df2)

# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球

👀Excel

python用于读写excel文件的库有很多,除了前面提到的pandas,还有xlrdxlwtopenpyxlxlwings等等。这里以pandas库为例对Excel进行操作

  • xlrd库:从excel中读取数据,支持xlsxlsx
  • xlwt库:对excel进行修改操作,不支持对xlsx格式的修改;
  • xlutils库:在xlwxlrd中,对一个已存在的文件进行修改;
  • openpyxl库:主要针对xlsx格式的excel进行读取和编辑;
  • xlwings库:对xlsxxlsxlsm格式文件进行读写、格式修改等操作;
  • xlsxwriter库:用来生成excel表格,插入数据、插入图标等表格操作,不支持读取;
  • Microsoft Excel API:需安装pywin32,直接与Excel进程通信,可以做任何在Excel里可以做的事情,但比较慢。

(1)读取Excel文件

read_excel()读取xlsx文件:

pd.read_excel(io, sheet_name=0, header=0, names=None, index_col=None, usecols=None, squeeze=False,dtype=None, engine=None, converters=None, true_values=None, false_values=None, skiprows=None, nrows=None, na_values=None, parse_dates=False, date_parser=None, thousands=None, comment=None, skipfooter=0, convert_float=True, **kwds)

# 常见参数详解
1)io:文件的路径。
2)sheet_name:读取的工作表的名称;可以是整型数字、列表名,如果读取多个sheet,也可以是它们组成的列表;以0为起始点。
3)header:指定哪几行做列名;默认header为0,如果设置为[0,1],则表示将前两行作为多重索引。
4)names:自定义列名;长度必须和excel的列大小相同;如果缺少列名,使用names指定列名字,会替代原来的列表头。
5)index_col:用作索引的列;可以是某列的名字,也可以是整型数字或列表。
6)usecols:指定读取的列;列从0开始,可以是列表,也可以使用Excel的列名,如'A''B'等字母。
7)squeeze:一列数据时,返回Series还是DataFrame。仅当Excel只有一列的时候起作用,squeeze为True时,返回Series,反之返回DataFrame。
8)skiprows:跳过指定行;skiprows=n,跳过前n行;skiprows=[a,b,c],跳过第a+1,b+1,c+1行(索引从0开始);使用skiprows后,可能会跳过行首,也就是列名。
9)nrows:需要读取的行数,表示只读取excel的前nrows行,包括表头。
10)skipfooter:跳过末尾n行。
......
import pandas as pd

# 读取xlsx,设置sheet位置,详细参数解释可以检索该函数
data = pd.read_excel(r"D:\Desktop\data.xlsx",sheet_name=0)
print(data)
print(type(data))
print("*"*20)
print(data.iloc[:,[0,1,3]].values)
print(data.iloc[:,[0,1,3]].values.tolist())

# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球
<class 'pandas.core.frame.DataFrame'>
********************
[['小红' '女' '跑步']
['小汤' '男' '篮球']
['小李' '男' '足球']
['小ai' '男' '篮球']
['小张' '男' '篮球']
['小小' '男' '跳绳']
['小耿' '男' '羽毛球']]
[['小红', '女', '跑步'], ['小汤', '男', '篮球'], ['小李', '男', '足球'], ['小ai', '男', '篮球'], ['小张', '男', '篮球'], ['小小', '男', '跳绳'], ['小耿', '男', '羽毛球']]

(2)写入Excel文件

to.excel()保存xlsx文件:

DataFrame.to_excel(excel_writer, sheet_name='Sheet1', na_rep='', float_format=None, columns=None, header=True, index=True, index_label=None, startrow=0, startcol=0, engine=None, merge_cells=True, encoding=None, inf_rep='inf', verbose=True, freeze_panes=None)

# 参数详解
1)excel_writer:字符串或ExcelWriter对象;文件路径或现有的ExcelWriter。
2)sheet_name:字符串,默认"Sheet1"将包含DataFrame的表的名称。
3)na_rep:字符串,默认''缺失数据表示方式。
4)float_format:字符串,默认None格式化浮点数的字符串。
5)columns:序列,可选要编写的列。
6)header:布尔或字符串列表,默认为Ture。写出列名。如果给定字符串列表,则假定它是列名称的别名。
7)index:布尔,默认的Ture写行名(索引)。
......

ExcelWriter()可以向同一个excel的不同sheet中写入对应的表格数据,首先需要实例化一个writer对象,传入的主要参数为已存在容器表格的路径及文件名称。

# 用于将DataFrame对象写入Excel工作表的类。默认值是对xls使用xlwt,对xlsx使用openpyxl。
class pandas.ExcelWriter(path, engine=None, date_format=None, datetime_format=None, mode='w', **engine_kwargs)

# 参数详解
1)path:str,xls或xlsx文件的路径。
2)engine:str (可选参数),用于编写的引擎,常见的引擎有"openpyxl""xlsxwriter"。如果为无,则默认为xlsxwriter,但是"xlsxwriter"模块不支持追加操作,需要追加新的sheet操作选择"openpyxl"参数,否则会报错。注意:只能作为关键字参数传递。
3)date_format:str,默认为None,格式字符串,用于写入Excel文件的日期(例如"YYYY-MM-DD")。
4)datetime_format:str,默认为None,写入Excel文件的日期时间对象的格式字符串。(例如"YYYY-MM-DD HH:MM:SS")。
5)mode:{"w","a"},默认为"w",要使用的文件模式(写或追加)。
6)if_sheet_exists:{'error','new','replace','overlay'},默认'error',写入的sheet name已存在时代码操作。默认'error'表示报错;'new'表示engine自动创建新的其他sheet name;'replace'表示覆盖原sheet数据,在写入之前删除工作表的内容;'overlay'表示将内容写入现有工作表而不删除旧内容。

为了与CSV编写器兼容,ExcelWriter在写入之前将列表和字典序列化为字符串。

在使用pd.ExcelWriter()的时候可能会出现问题:if_sheet_exists=’overlay’ 不起作用

查阅资料:if_sheet_exists{'error', 'new', 'replace', 'overlay'},如果pandas的版本过低,是没有overlay参数的,需要升级pandas版本。我的版本:pandas-2.0.1

# 追加数据
import pandas as pd
name = ["小伟","小猪"]
gender = ["男","男"]
age = [20,18]
hobby = ["跳绳","台球"]
dict_data = {"name":name,"gender":gender,"age":age,"hobby":hobby}
df = pd.DataFrame(dict_data)
with pd.ExcelWriter(r"D:\Desktop\data.xlsx", engine='openpyxl', mode='a',if_sheet_exists='overlay') as writer:
df1 = pd.DataFrame(pd.read_excel(r"D:\Desktop\data.xlsx", sheet_name='data'))
df_rows = df1.shape[0] #获取原数据的行数
# 将数据df写入excel中的sheet1表,从第一个空行开始写
# 为了避免覆盖现有内容,要告诉to_excel方法从新的一行开始写,参数startrow设为"原行数+1"
df.to_excel(writer, sheet_name='data',startrow=df_rows+1, index=False, header=False)
df2 = pd.read_excel(r"D:\Desktop\data.xlsx",sheet_name=0)
print(df2)

# 输出结果
name gender age hobby
0 小红 女 20 跑步
1 小汤 男 22 篮球
2 小李 男 24 足球
3 小ai 男 21 篮球
4 小张 男 25 篮球
5 小小 男 20 跳绳
6 小耿 男 25 羽毛球
7 小伟 男 20 跳绳
8 小猪 男 18 台球

写入Excel的几种情形与方式(覆盖、新增、追加、对齐),具体细节见:参考博客①参考博客②

import pandas as pd
import numpy as np
s1 = pd.DataFrame(np.array([['s1', 's1', 's1', 's1']]), columns=['a', 'b', 'c', 'd'])
s2 = pd.DataFrame(np.array([['s2', 's2', 's2', 's2']]), columns=['a', 'b', 'c', 'd'])

# (1)删除文件原有数据,只保留s2一份数据(最后一份)
# s1.to_excel(r"D:\Desktop\test.xlsx", sheet_name="111", index=False)
# s2.to_excel(r"D:\Desktop\test.xlsx", sheet_name="222", index=False)
with pd.ExcelWriter(r"D:\Desktop\test2.xlsx") as writer:
# (2) 删除文件原有数据,同时保留s1和s2两份数据
s1.to_excel(writer, sheet_name="111", index=False)
s2.to_excel(writer, sheet_name="222", index=False)

👀JSON

常见的处理JSON文件的第三方库(速度不同)包括:jsonsimplejsonujsonorjsonsimdjsonrapidjson。一般情况下的json文件,存储的是python中的一个dict。这里以map.geojson文件和CPython 本身的json模块为例,源文件内容如下。参考博客①参考博客②

{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [[[116.3591064789793, 40.0611769097348], [116.35882714532096, 40.06035824493355], [116.3588680234169, 40.06017052423036], [116.3592154872361, 40.05968557668524], [116.35964470724883, 40.05949263960517], [116.36125939205749, 40.05968557668524], [116.36073478982053, 40.06143241456951], [116.3591064789793, 40.0611769097348]]],
"type": "Polygon"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.35838429946176, 40.0595499993847],
"type": "Point"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.36078873507478, 40.06152377992771],
"type": "Point"
}
}
]
}

使用JSON函数需要导入json库:import json

函数 描述
json.loads() 将已编码的JSON字符串解码为Python对象
json.dumps() Python对象编码成JSON字符串
json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

# 参数详解
1)s:要解码的JSON字符串。
2)cls:指定用于解码JSON字符串的自定义类。
3)object_hook:指定一个回调函数,将解码后的JSON对象转换成其他Python对象。
4)parse_float:指定一个回调函数,将解码后的JSON浮点数转换成Python浮点数。
5)parse_int:指定一个回调函数,将解码后的JSON整数转换成Python整数。
6)parse_constant:指定一个回调函数,用于解析JSON中的常量(例如null,true,false)。
7)object_pairs_hook:指定一个回调函数,将解码后的JSON对象返回为Python的键值对。
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

# 参数详解
1)obj:转化成json的对象。
2)skipkeys:是否跳过无法被JSON序列化的key(包括str, int, float, bool, None)。
3)ensure_ascii:输出保证将所有输入的非ASCII字符转义。
4)check_circular:是否检查循环引用。
5)allow_nan:是否允许JSON规范外的float数据(nan, inf, -inf)。
6)indent:是一个正整数, 代表序列化后的缩进。
7)separators:是一个格式为 (item_separator, key_separator) 的元组, 默认取值为 (',',':')。
8)default:是一个函数, 当某个value无法被序列化时, 对其调用该函数。
9)sort_keys:是否对数据按照key进行排序。
# 读取json
import json
with open(r"D:\Desktop\map.geojson", 'r') as f:
content = f.read()
a = json.loads(content)
print(type(a))
print(a)
print("*"*20)
print(a["features"][2]["geometry"])

# 输出结果
<class 'dict'>
{'type': 'FeatureCollection', 'features': [{'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [[[116.3591064789793, 40.0611769097348], [116.35882714532096, 40.06035824493355], [116.3588680234169, 40.06017052423036], [116.3592154872361, 40.05968557668524], [116.35964470724883, 40.05949263960517], [116.36125939205749, 40.05968557668524], [116.36073478982053, 40.06143241456951], [116.3591064789793, 40.0611769097348]]], 'type': 'Polygon'}}, {'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.35838429946176, 40.0595499993847], 'type': 'Point'}}, {'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}}]}
********************
{'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}
# 将字典保存成json
import json
a = {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.36078873507478, 40.06152377992771],
"type": "Point"
}
}

b_str = json.dumps(a)
print(type(b_str))
with open(r"D:\Desktop\new_json.json", 'w') as f:
f.write(b_str)
with open(r"D:\Desktop\new_json.json", 'r') as f:
content = f.read()
a = json.loads(content)
print(a)

# 输出结果
<class 'str'>
{'type': 'Feature', 'properties': {}, 'geometry': {'coordinates': [116.36078873507478, 40.06152377992771], 'type': 'Point'}}

👀XML

Python中,有多个库可以用来读取和处理XML文档。以下是其中一些常用的库:

  • xml.etree.ElementTree(内置库):这是Python标准库中的一个模块,提供了基本的XML文档解析和操作功能。它具有简单的API和高效的性能,适合处理小型到中型的XML文档。
  • lxmllxmlPython中一个功能强大的XML/HTML解析库,基于libxml2libxslt库。它提供了与ElementTree相似的API,但具有更好的性能和更多的功能。lxml支持XPathXSLTXML Schema等高级特性,适用于处理大型和复杂的XML文档。
  • xmltodictxmltodict库可以将XML文档解析为Python字典,使XML数据的处理更加简便。它提供了一个简单的API,将XML数据转换为Python数据结构,便于数据的操作和处理。
  • minidomxml.dom.minidomPython标准库中的一个模块,提供了基本的DOM(文档对象模型)接口来解析和操作XML文档。尽管它的API相对较复杂,但它具有更多的功能和灵活性,适用于需要更高级控制的场景。

这些库都有各自的优点和适用场景。在选择库时,可以考虑以下因素:

  • 对于简单的XML操作和小型文档,内置库xml.etree.ElementTree是一个轻量级且易于使用的选择。
  • 如果需要更好的性能、更多的功能和高级特性(如XPathXSLT),可以选择lxml库。
  • 如果希望将XML数据解析为Python字典以便于处理,可以使用xmltodict库。
  • 如果对DOM接口熟悉并且需要更多的灵活性和控制能力,可以考虑使用minidom库。
# 说明
# 加载和读取xml文件,获取xml文档对象
from xml.dom import minidom
doc = minidom.parse(xmlfile)
# 获取xml文档根节点
root = doc.documentElement
# 节点属性
root.nodeName # 每个节点都有它的nodeName,nodeValue,nodeType属性
root.nodeValue # nodeValue是节点的值,只对本节点有效
root.nodeType # 节点类型;
root.ELEMENT_NODE
# 属性值的获取、修改、删除
root.getAttribute(attributeName) # 获取xml节点属性值
root.setAttribute(attributeName, value) # 修改或添加xml节点属性值
root.getElementsByTagName(TagName) # 根据标签获取xml节点对象集合
root.removeAttribute(attributeName) # 删除xml节点属性值
# 子节点的访问
root.childNodes # 获取子节点列表
root.childNodes[index].nodeValue # 获取xml节点值
root.firstChild # 访问第一个节点(相当于root.childNodes[0])
root.childNodes[0].data # 获得文本值
# 删除子节点
node.removeChild(childnode_in_node) # 删除node节点下面的子节点childnode_in_node
# 生成节点
node.createElement('activity') # 生成节点 # 文本节点.createTextNode('xxxxx')

(1)读取XML

XML示例文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<calories>650</calories>
<cropRegion x="0" y="0" width="0000" height="1234"/>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<calories>900</calories>
<cropRegion x="1" y="1" width="1111" height="2345"/>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<calories>900</calories>
<cropRegion x="2" y="2" width="2222" height="3456"/>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<calories>600</calories>
<cropRegion x="3" y="3" width="3333" height="4567"/>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<calories>950</calories>
<cropRegion x="4" y="4" width="4444" height="5678"/>
</food>
</breakfast_menu>

DOM解析XML文件

from xml.dom import minidom

# 解析xml文件(句柄或文件路径)
doc = minidom.parse(r"D:\Desktop\simple.xml")
# doc = minidom.parseString() # 解析xml字符串
print(doc)
print("*"*20)
# 获得根节点
root_node = doc.documentElement
print(root_node)
# 节点名称
print(root_node.nodeName)
# 节点类型(元素节点,文本节点,属性节点)
print(root_node.nodeType)
# 所有子节点,为列表
print(root_node.childNodes)
print("*"*20)
# 通过节点名称寻找节点,返回列表
filename_node = root_node.getElementsByTagName('name')
print(filename_node)
print("*"*20)
# 子节点为文本节点,文本节点有data属性即为文本值
filename = filename_node[1].childNodes[0].data
print(filename)
print("*"*20)
# 读取指定属性值,root.setAttribute(attributeName, value)更新修改属性值
cropRegion_node = root_node.getElementsByTagName('cropRegion')
width = cropRegion_node[1].getAttribute("width")
print(width)

# 输出结果
<xml.dom.minidom.Document object at 0x0000016F45D0EDC0>
********************
<DOM Element: breakfast_menu at 0x16f45d011f0>
breakfast_menu
1
[<DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45d01f70>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45d01b80>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45ccddc0>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f458e0dc0>, <DOM Text node "'\n\t'">, <DOM Element: food at 0x16f45cf05e0>, <DOM Text node "'\n'">]
********************
[<DOM Element: name at 0x16f45d01dc0>, <DOM Element: name at 0x16f45d018b0>, <DOM Element: name at 0x16f45ccdd30>, <DOM Element: name at 0x16f45cf0af0>, <DOM Element: name at 0x16f45cf0280>]
********************
Strawberry Belgian Waffles
********************
1111

(2)写入XML

# 写入文件
DOM树对象.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
# writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,第四个参数制定了换行格式,第五个参数制定了xml内容的编码。

# zip()函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。
# zip()方法在Python2和Python3中的不同:在Python3.x中为了减少内存,zip()返回的是一个对象。如需展示列表,需手动list()转换。
a = [1,2,3]
b = [4,5,6]
c = [4,5,6,7,8]
# 返回一个对象
zipped = zip(a,b)
print(zipped)
# list()转换为列表
print(list(zipped))
# 元素个数与最短的列表一致
print(list(zip(a,c)))
# 与zip相反,*zip()函数是zip()函数的逆过程,将zip对象变成原先组合前的数据
a1 = zip(*zip(a,b))
print(a1)
print(list(a1))

# 输出结果
<zip object at 0x0000016F45CD6200>
[(1, 4), (2, 5), (3, 6)]
[(1, 4), (2, 5), (3, 6)]
<zip object at 0x0000016F45CD0FC0>
[(1, 2, 3), (4, 5, 6)]

DOMXML文件

# 写入XML文件
from xml.dom import minidom
# (1)创建DOM树对象
dom = minidom.Document()
# (2)创建根节点,每次都要用DOM对象来创建任何节点
root_node = dom.createElement("people")
# (3)用DOM对象添加根节点
dom.appendChild(root_node)

# 用DOM对象创建元素字节点
name_node = dom.createElement("name")
# 用父节点对象添加元素子节点
root_node.appendChild(name_node)
# 设置该节点的属性
name_node.setAttribute("sex","男")
name_node.setAttribute("height","180")
# 用DOM创建文本节点,把文本节点(文字内容)看成子节点
name_text = dom.createTextNode("小汤")
# 用添加了文本的节点对象(看成文本节点的父节点)添加文本节点
name_node.appendChild(name_text)

# 用DOM对象创建元素字节点
hobby_node = dom.createElement("hobby")
# 用父节点对象添加元素子节点
root_node.appendChild(hobby_node)
# 用添加了文本的节点对象(看成文本节点的父节点)添加文本节点
hobby_node.appendChild(dom.createTextNode("篮球"))

score_node = dom.createElement("score")
for item, value in zip(["语文", "数学", "英语", "理综"], [150, 150, 150, 300]):
elem = dom.createElement(item)
elem.appendChild(dom.createTextNode(str(value)))
score_node.appendChild(elem)
root_node.appendChild(score_node)
try:
with open(r"D:\Desktop\write.xml",'w',encoding='UTF-8') as fh:
# dom.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
# 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
dom.writexml(fh, indent='', addindent='\t', newl='\n', encoding='UTF-8')
print('OK')
except Exception as err:
print('错误:{err}'.format(err=err))

输出的XML文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<people>
<name sex="男" height="180">小汤</name>
<hobby>篮球</hobby>
<score>
<语文>150</语文>
<数学>150</数学>
<英语>150</英语>
<理综>300</理综>
</score>
</people>

👀TXT

(1)读取TXT

源数据data.txt内容如下:

name	gender	age	hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球

操作txt文件,read()readline()readlines()、以及获取某一列内容,代码示例如下:

# (1)read()一次性读取所有文本
with open(r"D:\Desktop\data.txt", "r") as f: #打开文本
data1 = f.read() #读取文本
print(data1)
print("*"*20)
# (2)readline()读取第一行的内容
with open(r"D:\Desktop\data.txt", 'r') as f:
data2 = f.readline()
print(data2)
print("*"*20)
# (3)readlines()读取全部内容,以列表的格式返回结果
with open(r"D:\Desktop\data.txt", 'r') as f:
data3 = f.readlines()
print(data3)
for ann in data3:
# 去除文本中的换行符
ann = ann.strip('\n')
print(ann)
print("*"*20)
# (4)读取txt某一列数据,第一种方法
# 要读取第i列数据则可以读取每行的第i个数据再将其拼接起来
column_list = []
with open(r"D:\Desktop\data.txt", 'r') as f:
data = f.readlines()
for line in data:
# 去除文本中的换行符
ann = line.strip('\n')
a = ann.split("\t")
column_list.append(a[3])
print(column_list)
print("*"*20)
# (5)读取txt某一列数据,第二种方法
column_list2 = []
with open(r"D:\Desktop\data.txt", 'r') as f:
# 以行的形式进行读取文件
line2 = f.readline()
while line2:
ann2 = line2.strip('\n')
aa = ann2.split("\t")
column_list2.append(aa[2])
line2 = f.readline()
print(column_list2)
print("*"*20)
# (6)读取txt某一列数据,第三种方法
import codecs
column_list3 = []
with codecs.open(r"D:\Desktop\data.txt", mode = 'r') as f:
# 以行的形式进行读取文件
line3 = f.readline()
while line3:
ann3 = line3.strip('\n')
aaa = ann3.split("\t")
column_list3.append(aaa[1])
line3 = f.readline()
print(column_list3)

# 输出结果
name gender age hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球

********************
name gender age hobby

********************
['name\tgender\tage\thobby\n', '小红\t女\t20\t跑步\n', '小汤\t男\t22\t篮球\n', '小李\t男\t24\t足球\n', '小ai\t男\t21\t篮球\n', '小张\t男\t25\t篮球\n', '小小\t男\t20\t跳绳\n', '小耿\t男\t25\t羽毛球\n']
name gender age hobby
小红 女 20 跑步
小汤 男 22 篮球
小李 男 24 足球
小ai 男 21 篮球
小张 男 25 篮球
小小 男 20 跳绳
小耿 男 25 羽毛球
********************
['hobby', '跑步', '篮球', '足球', '篮球', '篮球', '跳绳', '羽毛球']
********************
['age', '20', '22', '24', '21', '25', '20', '25']
********************
['gender', '女', '男', '男', '男', '男', '男', '男']

(2)写入TXT

# 写入txt
hobby =["hobby", "跑步", "篮球", "足球", "篮球", "篮球", "跳绳", "羽毛球"]
name = ["name", "小红", "小汤", "小李", "小ai", "小张", "小小", "小耿"]
age = ["age", "20", "22", "24", "21", "25", "30", "25"]

with open(r"D:\Desktop\writeTXT.txt","a") as f:
length = len(age)
for i in range(length):
line = [hobby[i], name[i], age[i]]
lines = "\t".join(line)
# lines = hobby[i] + "\t" + name[i] + "\t" + age[i]
print(lines)
f.write(lines + '\n')
column_list = []
with open(r"D:\Desktop\writeTXT.txt","r") as f:
data = f.readlines()
# print(data)
for line in data:
# 去除文本中的换行符
ann = line.strip('\n')
a = ann.split("\t")
column_list.append(a[2])
print(column_list)

# 输出结果
hobby name age
跑步 小红 20
篮球 小汤 22
足球 小李 24
篮球 小ai 21
篮球 小张 25
跳绳 小小 30
羽毛球 小耿 25
['age', '20', '22', '24', '21', '25', '30', '25']

⛄Matlab之读写文件

使用过程中注意MATLAB版本差异问题。

MATLAB每一条语句后加分号与否的区别:

  • 代码后加分号,运行结果不会显示在命令窗口;

  • 代码后不加分号,当点击回车时,运行结果会立即在命令窗口(window command)显示。

👀CSV

(1)csvread()(不推荐)

CSV文件源数据:

name,gender,age,语文,数学,英语
小红,女,20,130,140,135
小汤,男,22,131,141,136
小李,男,24,132,142,137
小ai,男,21,133,143,138
小张,男,25,134,144,139
小小,男,20,135,145,140
小耿,男,25,136,146,141

利用csvread读取CSV文件

% 读取逗号分隔值格式的文件名,结果直接返回给result,CSV文件只能包含数值。
result = csvread("filename")
% 从CSV文件中读取数据(从R行和C列开始)
result = csvread("filename", R, C)
% 只读取由range=[R1 C1 R2 C2]指定的范围,其中(R1,C1)是要读取数据的左上角,(R2,C2)是右下角。也可以使用电子表格表示法指定RNG,如range="A1..B7",而非[0 0 6 1]。
result = csvread("filename",R1,C1,[R1 C1 R2 C2])

MATLAB代码:CTRL+R(注释)、CTRL+T(取消注释)

clc
clear all
result1 = csvread('D:\Desktop\data1.csv', 1, 2)
result2 = csvread('D:\Desktop\data1.csv', 1, 2, [1 2 6 4])
result3 = csvread('D:\Desktop\data1.csv', 1, 2, "C2..F8")

% 命令行窗口输出
result1 =
20 130 140 135
22 131 141 136
24 132 142 137
21 133 143 138
25 134 144 139
20 135 145 140
25 136 146 141
result2 =
20 130 140
22 131 141
24 132 142
21 133 143
25 134 144
20 135 145
result3 =
20 130 140 135
22 131 141 136
24 132 142 137
21 133 143 138
25 134 144 139
20 135 145 140
25 136 146 141

MATLAB帮助中心已经不推荐使用 csvread,请改用 readmatrix

(2)readmatrix()

参数详解见MATLAB帮助中心。

  • 从文本文件中读取矩阵
  • 从电子表格文件中读取矩阵
  • 使用导入选项从指定的工作表和范围中读取矩阵
  • 从指定的工作表和范围中读取矩阵
% (1)通过从文件中读取列向数据来创建数组,readmatrix函数可自动检测文件的导入参数。
% readmatrix基于文件的扩展名确定文件格式:
% .txt、.dat或.csv(带分隔符的文本文件)
% .xls、.xlsb、.xlsm、.xlsx、.xltm、.xltx或.ods(电子表格文件)
% 对于包含数值和文本混合数据的文件,默认情况下,readmatrix将数据作为数值数组导入。
result = readmatrix(filename)
% (2)还使用导入选项opts
result = readmatrix(filename,opts)
% (3)基于文件创建一个数组,并通过一个或多个名称-值对组参数指定其他选项。需要在输入参数之后指定名称-值对组。
% 要为数据设置特定的导入选项,您可以使用opts对象,也可以指定名称-值对组。当您指定除opts之外的名称-值对组时,readmatrix仅支持下列名称-值对组:
% 文本文件:DateLocale、Encoding
% 电子表格文件:Sheet、UseExcel
A = readmatrix(___,Name,Value)

利用readmatrix()读取CSV文件:

clc
clear all
% readmatrix第一个参数是文件名。第二个参数指输出类型。如果不带这个参数,那字符串那一列的输出结果是Nan值
% 加上之后,则全部输出文本类型,后面再把要作为数值型的内容转换数据类型。
result4 = readmatrix('D:\Desktop\data1.csv')
result5 = readmatrix('D:\Desktop\data1.csv', 'OutputType', 'string')

% 命令行窗口输出
result4 =
NaN NaN 20 130 140 135
NaN 7 22 131 141 136
NaN 7 24 132 142 137
NaN 7 21 133 143 138
NaN 7 25 134 144 139
NaN 7 20 135 145 140
NaN 7 25 136 146 141
result5 =
7×6 string 数组
"小红" "女" "20" "130" "140" "135"
"小汤" "男" "22" "131" "141" "136"
"小李" "男" "24" "132" "142" "137"
"小ai" "男" "21" "133" "143" "138"
"小张" "男" "25" "134" "144" "139"
"小小" "男" "20" "135" "145" "140"
"小耿" "男" "25" "136" "146" "141"

(3)importdata()

% (1)将数据加载到数组A中
A = importdata(filename)
% (2)从系统剪贴板而不是文件加载数据。
A = importdata('-pastespecial')
% (3)将delimiterIn解释为ASCII文件filename或剪贴板数据中的列分隔符。您可以将delimiterIn与以上语法中的任何输入参数结合使用。
A = importdata(___,delimiterIn)
% (4)从ASCII文件filename或剪贴板加载数据,并读取从第headerlinesIn+1 开始的数值数据。
A = importdata(___,delimiterIn,headerlinesIn)
% (5)支持上述语法中的任何输入参数,并在delimiterOut中额外返回检测到的输入ASCII文件中的分隔符,以及在headerlinesOut中返回检测到的标题行数。
[A,delimiterOut,headerlinesOut] = importdata(___)
clc
clear all
% 返回一个struct类型,默认将文本与数值分开
% 此方法虽然简便,但是貌似对数据量过大的数据不太友好
% matlab实现输出的几种方式(disp函数、fprintf函数、print函数)
result6 = importdata('D:\Desktop\data1.csv')
disp(result6)
data = result6.data
textdata = result6.textdata

% 命令行窗口输出
data: [7×4 double]
textdata: {8×6 cell}
data =
20 130 140 135
22 131 141 136
24 132 142 137
21 133 143 138
25 134 144 139
20 135 145 140
25 136 146 141
textdata =
8×6 cell 数组
{'name'} {'gender'} {'age' } {'语文' } {'数学' } {'英语' }
{'小红'} {'女' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小汤'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小李'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小ai'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小张'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小小'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}
{'小耿'} {'男' } {0×0 char} {0×0 char} {0×0 char} {0×0 char}

(4)readtable()

参数详解见MATLAB帮助中心。

  • 基于文本文件创建表
  • 忽略标题并填充缺失值
  • 基于文本文件创建表,无列标题
  • 基于文本文件创建格式表
  • 从文本文件读取外语日期
  • 基于包含行名称的电子表格创建表
  • 从电子表格中读取特定范围的数据
  • 检测并使用针对文本文件的导入选项
  • 检测并使用针对电子表格文件的导入选项
  • 读取包含任意变量名称的表格数据
  • 从文件中读取十六进制和二进制数字
  • XML文件创建XML导入选项
  • 注册自定义XML命名空间前缀
  • Microsoft Word文档中读取特定表
  • HTML网页读取表
% (1)通过从文件中读取列向数据来创建表。
% readtable基于文件的扩展名确定文件格式:
% .txt、.dat或.csv(带分隔符的文本文件)
% .xls、.xlsb、.xlsm、.xlsx、.xltm、.xltx或.ods(电子表格文件)
% .xml(可扩展标记语言(XML)文件)
% .docx(Microsoft® Word文档文件)
% .html、.xhtml或.htm(超文本标记语言(HTML)文件)
% 对于文本和电子表格文件,readtable为该文件中的每列在T中创建一个变量并从文件的第一行中读取变量名称。对于XML文件,readtable在T中为检测为表变量的每个元素或属性节点创建一个变量。变量名称对应于元素和属性名称。对于 Microsoft Word文档文件,默认情况下readtable从文档中的第一个表导入数据,为该文件中的每列在T中创建一个变量并从该表的第一行中读取变量名称。对于HTML文件,默认情况下readtable从第一个<TABLE>元素导入数据,为该文件中的每列在T中创建一个变量并从该表的第一行中读取变量名称。
% 默认情况下,readtable会根据在输入文件的每列中检测到的数据值来创建具有适当数据类型的变量。
T = readtable(filename)
% (2)使用导入选项opts创建表。
T = readtable(filename,opts)
% (3)基于文件创建一个表,并通过一个或多个名称-值对组参数指定其他选项。例如,您可以指定readtable是将文件的第一行读取为变量名称还是数据。
% 要为数据设置特定的导入选项,您可以使用opts对象,也可以指定名称-值对组。当您指定除opts之外的名称-值对组时,readtable仅支持下列名称-值对组:
% 文本和电子表格参数 -ReadVariableNames、ReadRowNames
% 仅文本参数 -DateLocale、Encoding
% 仅电子表格参数 -Sheet、UseExcel
T = readtable(___,Name,Value)
clc
clear all
result7 = readtable('D:\Desktop\data1.csv')

% 命令行窗口输出
result7 =
7×6 table
name gender age x__ x___1 x___2
______ ______ ___ ___ _____ _____

'小红' '女' 20 130 140 135
'小汤' '男' 22 131 141 136
'小李' '男' 24 132 142 137
'小ai' '男' 21 133 143 138
'小张' '男' 25 134 144 139
'小小' '男' 20 135 145 140
'小耿' '男' 25 136 146 141

(5)csvwrite()(不推荐)

% 可查看帮助中心函数说明
% 将矩阵M以逗号分隔值形式写入文件filename。
csvwrite(filename,M)
% 从指定的行和列偏移量开始将矩阵M写入文件filename。行和列参数从0开始,因此row=0和col=0指定文件中的第一个值。
csvwrite(filename,M,row,col)
  • 对于字符串类型csvwrite可能不支持;
  • 帮助中心:不推荐使用csvwrite,请改用writematrix
clc
clear all

csv_data = importdata('D:\Desktop\data1.csv')
data = csv_data.data;
textdata = csv_data.textdata;
csvwrite('D:\Desktop\output.csv',data, 0, 0)
% 输出结果为double
res1 = readmatrix('D:\Desktop\output.csv')
% 输出结果为string
res2 = readmatrix('D:\Desktop\output.csv', 'OutputType', 'string')

% 命令行窗口输出结果
csv_data =
包含以下字段的 struct:
data: [7×4 double]
textdata: {8×6 cell}
res1 =
20 130 140 135
22 131 141 136
24 132 142 137
21 133 143 138
25 134 144 139
20 135 145 140
25 136 146 141
res2 =
7×4 string 数组
"20" "130" "140" "135"
"22" "131" "141" "136"
"24" "132" "142" "137"
"21" "133" "143" "138"
"25" "134" "144" "139"
"20" "135" "145" "140"
"25" "136" "146" "141"

(6)writematrix()

参数详解见MATLAB帮助中心。

  • 将矩阵写入到文本文件
  • 将矩阵写入电子表格文件
  • 将矩阵写入指定的工作表和范围
  • 将数据追加到电子表格
  • 将矩阵数据追加到文本文件
% writematrix()将矩阵写入文件,自R2019a起
% (1)将同构数组A写入以逗号分隔的文本文件。文件名为数组的工作区变量名称,附加扩展名.txt。如果writematrix无法根据数组名称构造文件名,那么它会写入matrix.txt文件中。A中每个变量的每一列都将成为输出文件中的列。writematrix函数会覆盖任何现有文件。
writematrix(A)
% (2)写入具有filename指定的名称和扩展名的文件。
% writematrix 根据指定扩展名确定文件格式。扩展名必须是下列格式之一:
% .txt、.dat或.csv(带分隔符的文本文件)
% .xls、.xlsm或.xlsx(适用于Excel® 电子表格文件)
% .xlsb(适用于安装了Windows® Excel的系统上支持的Excel电子表格文件)
writematrix(A,filename)
% (3)支持上述语法中的任何输入参数,且可使用一个或多个Name,Value对组参数指定其他选项将数组写入文件中。
writematrix(___,Name,Value)
clc
clear all

csv_data = readmatrix('D:\Desktop\data1.csv', 'OutputType', 'string')
% 没有标题,可以根据自己创建的矩阵添加标题
writematrix(csv_data,'D:\Desktop\output1.csv')

% 命令行窗口输出结果
csv_data =
7×6 string 数组
"小红" "女" "20" "130" "140" "135"
"小汤" "男" "22" "131" "141" "136"
"小李" "男" "24" "132" "142" "137"
"小ai" "男" "21" "133" "143" "138"
"小张" "男" "25" "134" "144" "139"
"小小" "男" "20" "135" "145" "140"
"小耿" "男" "25" "136" "146" "141"

(7)dlmwrite()(不推荐)

帮助中心:不推荐使用dlmwrite,请改用writematrix

dlmwrite支持数值数据,不支持字符串类型。具体参数解释可以查看MATLAB帮助中心文档。

% (1)将数组M中的数值数据写入一个ASCII格式的文件filename,并使用默认分隔符(,)分隔各数组元素。如果文件filename已存在,则dlmwrite将覆盖该文件。
dlmwrite(filename,M)
% (2)将数据追加到现有文件filename的末尾。
dlmwrite(filename,M,'-append')
% (3)使用一个或多个名称-值对组参数另外指定分隔符、换行符、偏移量和精度选项。
dlmwrite(___,Name,Value)
% (4)将数组M写入文件filename,并使用指定分隔符delimiter分隔各数组元素。
dlmwrite(filename,M,delimiter)
% (5)从目标文件中指定的第row行和第col列开始写入数组。前导行和列用delimiter分隔的空元素填充。
dlmwrite(filename,M,delimiter,row,col)
clc
clear all

% 支持数值型
csv_data = importdata('D:\Desktop\data1.csv')
data = csv_data.data
% 添加到csv中,并且以逗号为分隔符
dlmwrite('D:\Desktop\output2.csv',data,'delimiter',',')
% 添加到csv中,并且从行后添加
dlmwrite('D:\Desktop\output2.csv',data,'delimiter',',','-append')
% 添加到csv中,并且以相对于已有数据偏移的方式
dlmwrite('D:\Desktop\output2.csv',data,'delimiter',',','-append','roffset',2,'coffset',2)

% 命令行窗口输出结果
csv_data =
包含以下字段的 struct:
data: [7×4 double]
textdata: {8×6 cell}
data =
20 130 140 135
22 131 141 136
24 132 142 137
21 133 143 138
25 134 144 139
20 135 145 140
25 136 146 141

(8)writetable()

参数详解见MATLAB帮助中心。也可实现:

  • 将表写入到文本文件
  • 将表写入空格分隔的文本文件
  • 将表写入包含行名称的文本文件
  • 将外语日期写入文本文件
  • 将外语字符写入文本文件
  • 将引用文本写入**CSV文件**
  • 将表写入到电子表格中特定的工作表和范围
  • 写入包含任意变量名称的表格数据
  • 将数据追加到表的底部
  • 保留现有列宽(将数据追加到文件底部时,保留电子表格文件的现有列宽)
  • 修改现有单元格格式
  • 将表写入**XML文件**
% (1)将表T写入逗号分隔的文本文件。文件名为表的工作区变量名称,附加扩展名.txt。如果writetable无法根据输入表名称构造文件名,那么它会写入table.txt 文件中。
% 对于文本文件和电子表格文件,T中每个变量的每列都成为输出文件中的一列。T的变量名称将成为文件第一行的列标题。
% 对于XML文件,T中的每列都成为输出文件中的一个XML节点。T的变量名称成为输出XML文件中元素节点的名称。
writetable(T)
% (2)写入具有filename指定的名称和扩展名的文件。
% writetable根据指定扩展名确定文件格式。扩展名必须是下列格式之一:
% .txt、.dat或.csv(带分隔符的文本文件)
% .xls、.xlsm或.xlsx(适用于Excel®电子表格文件)
% .xlsb(适用于安装了Windows® Excel的系统上支持的Excel电子表格文件)
% .xml(可扩展标记语言(XML)文件)
writetable(T,filename)
% (3)通过一个或多个Name,Value对组参数指定的其他选项将表写入文件中,并且可以包含以前语法中的任何输入参数。例如,您可以指定是否将变量名称写入为输出文件中的列标题。
writetable(___,Name,Value)
clc
clear all

LastName = {'Sanchez';'Johnson';'Li';'Diaz';'Brown'}
Age = [38;43;38;40;49]
Smoker = logical([1;0;1;0;1])
Height = [71;69;64;67;64]
Weight = [176;163;131;133;119]
BloodPressure = [124 93; 109 77; 125 83; 117 75; 122 80]
table_csv = table(LastName,Age,Smoker,Height,Weight,BloodPressure)
% 自定义列索引和行索引
table_csv.Properties.VariableNames = {'a','b','c','d','e','f'}
table_csv.Properties.RowNames = {'g','h','i','j','k'}
writetable(table_csv,"D:\Desktop\output3.csv")

👀Excel

函数详解见上,或者MATLAB帮助中心。

读取全部内容读取特定部分内容追加内容……

(1)xlsread()(不推荐)

  • 将工作表读取到数值矩阵
  • 读取元胞的范围
  • 读取列
  • 请求数值、文本和原始数据
  • 对工作表执行函数
  • 请求自定义输出
% (1)读取名为filename的 Microsoft®Excel®电子表格工作表中的第一个工作表,并在一个矩阵中返回数值数据。
num = xlsread(filename)
% (2)读取指定的工作表。
num = xlsread(filename,sheet)
% (3)从工作簿的第一个工作表的指定范围内读取数据。使用Excel范围语法,例如'A1:C3'。
num = xlsread(filename,xlRange)
% (4)读取指定的工作表和范围。
num = xlsread(filename,sheet,xlRange)
% (5)在basic导入模式下读取电子表格中的数据。如果您的计算机未安装Windows®版 Excel或者您正在使用MATLAB®Online™,xlsread会自动在basic导入模式下运行,该模式支持XLS、XLSX、XLSM、XLTX和XLTM文件。
% 如果不指定所有参数,请使用空字符向量''作为占位符,例如,num=xlsread(filename,'','','basic')。
num = xlsread(filename,sheet,xlRange,'basic')
% (6)支持上述语法中的任何输入参数,且可在元胞数组txt中返回文本字段,在元胞数组raw中返回数值数据和文本数据。
[num,txt,raw] = xlsread(___)
% (7)打开一个Excel窗口以便按交互方式来选择数据。选择工作表,将鼠标拖放到所需范围上,然后点击确定。只有安装了Microsoft Excel软件的Windows计算机才支持此语法。
___ = xlsread(filename,-1)
% (8)读取电子表格,对数据调用processFcn,并在数组num中以数值数据的形式返回最终结果。xlsread函数在元胞数组txt中返回文本字段、在元胞数组raw中返回数值和文本数据,并在数组custom中返回processFcn的第二个输出。xlsread函数不会更改电子表格中存储的数据。只有安装了Excel软件的Windows计算机才支持此语法。
% (其中processFcn是函数句柄)
[num,txt,raw,custom] = xlsread(filename,sheet,xlRange,'',processFcn)
clc
clear all

values = {1, 2, 3 ; 4, 5, 'x' ; 7, 8, 9}
headers = {'First','Second','Third'}
xlswrite('D:\Desktop\myExample.xlsx',[headers; values])
filename = 'D:\Desktop\myExample.xlsx'
data = xlsread(filename)

% 命令行窗口输出结果
values =
3×3 cell 数组
{[1]} {[2]} {[3]}
{[4]} {[5]} {'x'}
{[7]} {[8]} {[9]}
headers =
1×3 cell 数组
{'First'} {'Second'} {'Third'}
data =
1 2 3
4 5 NaN
7 8 9

(2)readmatrix()

clc
clear all
% readmatrix第一个参数是文件名。第二个参数指输出类型。如果不带这个参数,那么字符串那一列的输出结果是Nan值
% 加上之后,则全部输出文本类型,后面再把要作为数值型的内容转换数据类型。
data1 = readmatrix('D:\Desktop\data2.xlsx', 'OutputType', 'string')

% 命令行窗口输出结果
data1 =
7×6 string 数组
"小红" "女" "20" "130" "140" "135"
"小汤" "男" "22" "131" "141" "136"
"小李" "男" "24" "132" "142" "137"
"小ai" "男" "21" "133" "143" "138"
"小张" "男" "25" "134" "144" "139"
"小小" "男" "20" "135" "145" "140"
"小耿" "男" "25" "136" "146" "141"

(3)readtable()

clc
clear all
data2 = readtable('D:\Desktop\data2.xlsx')

% 命令行窗口输出结果
data2 =
7×6 table
name gender age x__ x___1 x___2
______ ______ ___ ___ _____ _____

'小红' '女' 20 130 140 135
'小汤' '男' 22 131 141 136
'小李' '男' 24 132 142 137
'小ai' '男' 21 133 143 138
'小张' '男' 25 134 144 139
'小小' '男' 20 135 145 140
'小耿' '男' 25 136 146 141

(4)xlswrite()(不推荐)

  • 将向量写入电子表格
  • 写入电子表格的特定工作表和范围
% (1)将矩阵A写入Microsoft®Excel®电子表格工作簿filename中的第一个工作表,从单元格A1开始写入。
xlswrite(filename,A)
% (2)将数据写入指定的工作表。
xlswrite(filename,A,sheet)
% (3)将数据写入工作簿的第一个工作表中由xlRange指定的矩形区域内。使用Excel范围语法,例如'A1:C3'。
xlswrite(filename,A,xlRange)
% (4)将数据写入指定的工作表和范围。
xlswrite(filename,A,sheet,xlRange)
% (5)使用先前语法中的任何输入参数返回写入操作的状态。当操作成功时,status为1。否则,status为0。
status = xlswrite(___)
% (6)还在结构体message中返回写入操作生成的任何警告或错误消息。
[status,message] = xlswrite(___)
clc
clear all

% 写入电子表格的特定工作表和范围
A = {'Time','Temperature'; 12,98; 13,99; 14,97}
sheet = 2
xlRange = 'E1'
xlswrite('D:\Desktop\mytest.xlsx',A,sheet,xlRange)

(5)writematrix()

clc
clear all

Excel_data = readmatrix('D:\Desktop\data2.xlsx', 'OutputType', 'string')
writematrix(Excel_data,'D:\Desktop\output2.xlsx')
% 我的MATLAB版本是R2019a,追加时显示参数名称 WriteMode无效
% writematrix(Excel_data,'D:\Desktop\output2.xlsx','WriteMode','append')

% 命令行窗口输出结果
Excel_data =
7×6 string 数组
"小红" "女" "20" "130" "140" "135"
"小汤" "男" "22" "131" "141" "136"
"小李" "男" "24" "132" "142" "137"
"小ai" "男" "21" "133" "143" "138"
"小张" "男" "25" "134" "144" "139"
"小小" "男" "20" "135" "145" "140"
"小耿" "男" "25" "136" "146" "141"

(6)writetable()

clc
clear all

LastName = {'Sanchez';'Johnson';'Li';'Diaz';'Brown'}
Age = [38;43;38;40;49]
Smoker = logical([1;0;1;0;1])
Height = [71;69;64;67;64]
Weight = [176;163;131;133;119]
BloodPressure = [124 93; 109 77; 125 83; 117 75; 122 80]
table_csv = table(LastName,Age,Smoker,Height,Weight,BloodPressure)
% 自定义列索引和行索引
table_csv.Properties.VariableNames = {'a','b','c','d','e','f'}
table_csv.Properties.RowNames = {'g','h','i','j','k'}
writetable(table_csv,"D:\Desktop\output3.xlsx")

% 命令行窗口输出结果
table_csv =
5×6 table
a b c d e f
_________ __ _____ __ ___ __________
g 'Sanchez' 38 true 71 176 124 93
h 'Johnson' 43 false 69 163 109 77
i 'Li' 38 true 64 131 125 83
j 'Diaz' 40 false 67 133 117 75
k 'Brown' 49 true 64 119 122 80

👀JSON

MATLAB读取JSON的方式利用JSONlab工具箱

①将下载的工具箱安装包解压缩放入MATLAB安装目录下的toolbox文件夹下;

②打开MATLAB,选择”主页“→”设置路径“,将工具箱所在文件夹导入。

JSON源文件

{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [[[116.3591064789793, 40.0611769097348], [116.35882714532096, 40.06035824493355], [116.3588680234169, 40.06017052423036], [116.3592154872361, 40.05968557668524], [116.35964470724883, 40.05949263960517], [116.36125939205749, 40.05968557668524], [116.36073478982053, 40.06143241456951], [116.3591064789793, 40.0611769097348]]],
"type": "Polygon"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.35838429946176, 40.0595499993847],
"type": "Point"
}
}, {
"type": "Feature",
"properties": {},
"geometry": {
"coordinates": [116.36078873507478, 40.06152377992771],
"type": "Point"
}
}
]
}

利用Matlab读取JSON

clc
clear all

% 读取json需要导入JSONlab工具箱
jsonData = loadjson('D:\Desktop\map.geojson')

% 命令行窗口输出结果
jsonData =
包含以下字段的 struct:
type: 'FeatureCollection'
features: [1×3 struct]

利用Matlab写入JSON

clc
clear all

% 创建结构体变量
data.type = 'Feature'
data.properties = {}
data.geometry.coordinates = [116.36078873507478, 40.06152377992771]
data.geometry.type = 'Point'

% 将结构体变量写入JSON文件
savejson('', data, 'D:\Desktop\test.json')
% 从JSON文件中读取数据
jsonData = loadjson('D:\Desktop\test.json')

% 命令行窗口输出结果
data =
包含以下字段的 struct:
type: 'Feature'
data =
包含以下字段的 struct:
type: 'Feature'
properties: {}
data =
包含以下字段的 struct:
type: 'Feature'
properties: {}
geometry: [1×1 struct]
data =
包含以下字段的 struct:
type: 'Feature'
properties: {}
geometry: [1×1 struct]
jsonData =
包含以下字段的 struct:
type: 'Feature'
properties: {0×1 cell}
geometry: [1×1 struct]

👀XML

参数详解见MATLAB帮助中心。

xmlread()读取XML文档并返回文档对象模型节点

  • XML文件读入文档对象模型 (DOM) 节点中

  • 将该XML文件读入MATLAB®结构体数组中

xmlwrite()写入XML文档对象模型节点

  • 创建XML文件

  • 以串行化文本形式获取文档对象模型 (DOM) 节点

% (1)读取指定的XML文件并返回一个Apache®Xerces-J文档对象,该对象表示该XML文件的解析版本。Apache Xerces-J实现用于XML处理的Java®API(JAXP)。使用JAXP函数来操作此文档对象。有关Apache Xerces-J的详细信息,请参阅https://xerces.apache.org/xerces-j/apiDocs/。
DOMnode = xmlread(filename)
% (2)还指定是否允许DOCTYPE声明。如果tf为false,则读取包含DOCTYPE声明的输入XML文件会导致错误。如果为true,xmlread则会为XML文件返回输出DOMnode。tf的默认值是true。
DOMnode = xmlread(filename,'AllowDoctype',tf)
% (1)将文档对象模型(DOM)节点DOMnode写入到文件filename。使用xmlwrite要求您使用用于XML处理的Java® API(JAXP)。有关详细信息,请参阅https://docs.oracle.com/javase/7/docs/api。
xmlwrite(filename,DOMnode)
% (2)以字符向量形式返回串行化DOM节点。
chr = xmlwrite(DOMnode)

(1)读取XML

XML源文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<calories>650</calories>
<cropRegion x="0" y="0" width="0000" height="1234"/>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<calories>900</calories>
<cropRegion x="1" y="1" width="1111" height="2345"/>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<calories>900</calories>
<cropRegion x="2" y="2" width="2222" height="3456"/>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<calories>600</calories>
<cropRegion x="3" y="3" width="3333" height="4567"/>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<calories>950</calories>
<cropRegion x="4" y="4" width="4444" height="5678"/>
</food>
</breakfast_menu>

利用xmlread()读取XML,同时利用函数 parseXML()将该XML文件读入MATLAB®结构体数组中:

% 创建一个解析函数以将一个XML文件读入MATLAB®结构体中,然后将一个示例XML文件读入MATLAB工作区中。要创建函数parseXML,请将以下代码复制并粘贴到m文件parseXML.m中。parseXML函数将一个XML文件中的数据解析为一个MATLAB结构体数组,该数组包含字段Name、Attributes、Data和Children。
function theStruct = parseXML(filename)
% PARSEXML Convert XML file to a MATLAB structure.
try
tree = xmlread(filename);
catch
error('Failed to read XML file %s.',filename);
end

% Recurse over child nodes. This could run into problems
% with very deeply nested trees.
try
theStruct = parseChildNodes(tree);
catch
error('Unable to parse XML file %s.',filename);
end


% ----- Local function PARSECHILDNODES -----
function children = parseChildNodes(theNode)
% Recurse over node children.
children = [];
if theNode.hasChildNodes
childNodes = theNode.getChildNodes;
numChildNodes = childNodes.getLength;
allocCell = cell(1, numChildNodes);

children = struct( ...
'Name', allocCell, 'Attributes', allocCell, ...
'Data', allocCell, 'Children', allocCell);

for count = 1:numChildNodes
theChild = childNodes.item(count-1);
children(count) = makeStructFromNode(theChild);
end
end

% ----- Local function MAKESTRUCTFROMNODE -----
function nodeStruct = makeStructFromNode(theNode)
% Create structure of node info.

nodeStruct = struct( ...
'Name', char(theNode.getNodeName), ...
'Attributes', parseAttributes(theNode), ...
'Data', '', ...
'Children', parseChildNodes(theNode));

if any(strcmp(methods(theNode), 'getData'))
nodeStruct.Data = char(theNode.getData);
else
nodeStruct.Data = '';
end

% ----- Local function PARSEATTRIBUTES -----
function attributes = parseAttributes(theNode)
% Create attributes structure.

attributes = [];
if theNode.hasAttributes
theAttributes = theNode.getAttributes;
numAttributes = theAttributes.getLength;
allocCell = cell(1, numAttributes);
attributes = struct('Name', allocCell, 'Value', ...
allocCell);

for count = 1:numAttributes
attrib = theAttributes.item(count-1);
attributes(count).Name = char(attrib.getName);
attributes(count).Value = char(attrib.getValue);
end
end
clc
clear all

sampleXMLfile = 'D:\Desktop\simple.xml';
% 显示simple.xml文件内容
type(sampleXMLfile)
% 将该XML文件读入DOM节点中
% DOMnode = xmlread(sampleXMLfile)
% 使用parseXML函数将示例文件info.xml解析为一个MATLAB结构体。
mlStruct = parseXML(sampleXMLfile)

% 命令行窗口输出结果
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy庐 -->
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<calories>650</calories>
<cropRegion x="0" y="0" width="0000" height="1234"/>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<calories>900</calories>
<cropRegion x="1" y="1" width="1111" height="2345"/>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<calories>900</calories>
<cropRegion x="2" y="2" width="2222" height="3456"/>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<calories>600</calories>
<cropRegion x="3" y="3" width="3333" height="4567"/>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<calories>950</calories>
<cropRegion x="4" y="4" width="4444" height="5678"/>
</food>
</breakfast_menu>

mlStruct =
包含以下字段的 1×2 struct 数组:
Name
Attributes
Data
Children

(2)写入XML

分两步编写XML文件:

①创建一个包含XML数据的文档对象模型 (DOM) 节点;

②将该DOM节点写入一个XML文件。

要实现的写入内容:

<?xml version="1.0" encoding="utf-8"?>
<toc version="2.0">
<tocitem target="upslope_product_page.html">Upslope Area Toolbox<!-- Functions -->
<tocitem target="demFlow_help.html">demFlow</tocitem>
<tocitem target="facetFlow_help.html">facetFlow</tocitem>
<tocitem target="flowMatrix_help.html">flowMatrix</tocitem>
<tocitem target="pixelFlow_help.html">pixelFlow</tocitem>
</tocitem>
</toc>

利用xmlwrite()写入XML文档:

clc
clear all

% 创建DOM节点对象和根元素,然后根据XML数据填充节点元素和节点属性。
docNode = com.mathworks.xml.XMLUtils.createDocument('toc');
% 确定根元素并设置version属性。
toc = docNode.getDocumentElement;
toc.setAttribute('version','2.0');
% 添加tocitem元素。此文件中的每个tocitem元素都有一个target属性和一个子文本节点。
product = docNode.createElement('tocitem');
product.setAttribute('target','upslope_product_page.html');
product.appendChild(docNode.createTextNode('Upslope Area Toolbox'));
toc.appendChild(product);
% 添加注释
product.appendChild(docNode.createComment(' Functions '));
% 为每个函数添加一个tocitem元素
functions = {'demFlow','facetFlow','flowMatrix','pixelFlow'};
for idx = 1:numel(functions)
curr_node = docNode.createElement('tocitem');

curr_file = [functions{idx} '_help.html'];
curr_node.setAttribute('target',curr_file);

% Child text is the function name.
curr_node.appendChild(docNode.createTextNode(functions{idx}));
product.appendChild(curr_node);
end
% 将DOM节点导出到名为infoUAT.xml的XML文件中,并使用type函数查看该文件
xmlwrite('D:\Desktop\infoUAT.xml',docNode);
type('D:\Desktop\infoUAT.xml');

% 命令行窗口输出结果
<?xml version="1.0" encoding="utf-8"?>
<toc version="2.0">
<tocitem target="upslope_product_page.html">Upslope Area Toolbox<!-- Functions --> <tocitem target="demFlow_help.html">demFlow</tocitem>
<tocitem target="facetFlow_help.html">facetFlow</tocitem>
<tocitem target="flowMatrix_help.html">flowMatrix</tocitem>
<tocitem target="pixelFlow_help.html">pixelFlow</tocitem>
</tocitem>
</toc>

👀TXT(函数例举)

  • textread()

  • textscan()

  • readmatrix()

  • writematrix()

  • readtable()

  • writetable()

  • load()

  • dlmread()

  • dlmwrite()

  • importdata()

  • save()

  • ……

⛄IDL之读写文件

IDL从磁盘上的文件读写数据,必须首先把一个逻辑设备号连接到一个特定的文件,然后进行文件操作如打开、关闭和读取等。IDL中的逻辑设备号范围是-2—128,其中1-99是可以用户任意指定的,100-128是根据get_lunfree_lun来管理的,其他是特殊函数专用的。IDL中文件操作的函数列表:

函数名字 作用
OpenR 以只读方式打开已存在文件;
OpenW 创建一个可以读写的新文件;
OpenU 以更新模式打开已存在文件;
File_Search() 对文件名进行特定的查找;
Dialog_Pickfile() 对话框方式选择文件;
Fstat() 返回一个已打开文件的信息;
EOF() 检测是否到文件末;
CLOSE 关闭一个文件;
Free_Lun 释放一个逻辑设备号并关闭文件;

IDL在读写该文件分为有两种格式化文件:自由文件格式和确定的文件格式。

自由文件格式是用逗号或空白(tab键和空格键)分开文件中的每个元素的ASCII文件。确定的格式文件是用格式说明按照给定的规范进行编排的。二者相比后者比前者更正规一些。

读写自由文件格式:IDL下用ReadF从文件中读入自由格式数据,Printf写入自由格式数据到文件中。IDL中读写自由格式文件遵循下面的几个规则:

  • 如果读入到字符串变量中,那么,在当前行剩下的所有字符都将读入该变量中;

  • 输入数据必须用逗号或空白分隔(空格键或 tab 键);

  • 输入通过数字变量完成。数组和结构都可作为数字变量的集合;

  • 如果当前读入行是空的,并且还有变量要求输入,则读取另一行;

  • 如果当前读入行不是空的,但是没有变量要求输入,则忽略此行剩下的数;

  • 尽量将数据转换为变量所希望的数据类型;

  • 复数数据必须有实数和虚数两部分,用逗号分隔,并用括号括起来。

读写确定的文件格式:读写确定文件格式可同样用ReadFPrintF命令,它们刚才已用于自由格式文件,但现在文件格式已由Format关键字明确声明。(在读写标准输入和输出时,也可将Format关键字用于ReadPrint令)。

👀CSV

CSV示例源文件:

lon,lat,area
101,50,20
102,51,22
103,52,24
104,53,21
105,54,25
106,55,20
107,56,25
108,57,20
109,58,18
110,59,20.58333333
111,60,20.36666667
112,61,20.15
113,62,19.93333333
114,63,19.71666667
115,64,19.5
116,65,19.28333333

读取CSV文件:

pro Demo02
; 打开csv文件
csv_file = 'D:\Desktop\data_p2.csv'
; 读取文件
; 第一行是索引,参数par_name(无论需不需要第一行索引数据,read_csv()函数默认都不会去读取第一行的数据)
data_csv = Read_csv(csv_file, header=par_name)
; 查看data的类型,是一个结构体
; Help, data_csv
; 输出第一列数据
Print, data_csv.(0)
; 输出第一行的索引数据
Print, par_name
; 输出列索引是lat的数据(第一种方法可以数它所在的列号按上面的方式进行读取并输出,也可按下面这种方法)
lon = Where(par_name EQ 'lat')
Print, data_csv.(lon)
END

; IDL控制台输出结果(结果样式与控制台的宽度有关)
% Compiled module: DEMO02.
101 102 103 104 105
106 107 108 109 110
111 112 113 114 115
116
lon lat area
50 51 52 53 54
55 56 57 58 59
60 61 62 63 64
65

写入CSV文件:

pro Demo04_csv
; 打开csv文件,获取数据
csv_file = 'D:\Desktop\data_p2.csv'
; 读取文件
; 第一行的索引给了,参数par_name(但是无论你需不需要第一行索引数据,read_csv()函数默认都不会去读取第一行的数据)
data_csv = Read_csv(csv_file, header=par_name)
; 查看data的类型,是一个结构体
; Help, data_csv
; 输出第一列数据
Print, data_csv.(0)
; 输出第一行的索引数据
Print, par_name
; 输出列索引是lat的数据(第一种方法你可以自己去数它所在的列号按上面的方式进行读取并输出,也可以按下面这种方法)
lon = Where(par_name EQ 'lat')
Print, data_csv.(lon)

; 写入csv文件
save_file = 'D:\Desktop\data_p3.csv'
data_size = size(data_csv.(2))
length = data_size[-1]
data_box = fltarr(3,length)
data_box[0,*] = data_csv.(0)
data_box[1,*] = data_csv.(1)
data_box[2,*] = data_csv.(2)
print,data_box
Write_csv, save_file, data_box
end

; IDL控制台输出结果
% Compiled module: DEMO04_CSV.
101 102 103
104 105 106
107 108 109
110 111 112
113 114 115
116
lon lat area
50 51 52
53 54 55
56 57 58
59 60 61
62 63 64
65
101.000 50.0000 20.0000
102.000 51.0000 22.0000
103.000 52.0000 24.0000
104.000 53.0000 21.0000
105.000 54.0000 25.0000
106.000 55.0000 20.0000
107.000 56.0000 25.0000
108.000 57.0000 20.0000
109.000 58.0000 18.0000
110.000 59.0000 20.5833
111.000 60.0000 20.3667
112.000 61.0000 20.1500
113.000 62.0000 19.9333
114.000 63.0000 19.7167
115.000 64.0000 19.5000
116.000 65.0000 19.2833
% Compiled module: WRITE_CSV.

👀XML

XML示例源文件:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<breakfast_menu>
<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<calories>650</calories>
<cropRegion x="0" y="0" width="0000" height="1234"/>
</food>
<food>
<name>Strawberry Belgian Waffles</name>
<price>$7.95</price>
<calories>900</calories>
<cropRegion x="1" y="1" width="1111" height="2345"/>
</food>
<food>
<name>Berry-Berry Belgian Waffles</name>
<price>$8.95</price>
<calories>900</calories>
<cropRegion x="2" y="2" width="2222" height="3456"/>
</food>
<food>
<name>French Toast</name>
<price>$4.50</price>
<calories>600</calories>
<cropRegion x="3" y="3" width="3333" height="4567"/>
</food>
<food>
<name>Homestyle Breakfast</name>
<price>$6.95</price>
<calories>950</calories>
<cropRegion x="4" y="4" width="4444" height="5678"/>
</food>
</breakfast_menu>

读取XML文件:

pro Demo02
XML_file = 'D:\Desktop\simple.xml'
XML = IDLffXMLDOMDocument(filename = XML_file)
name = XML.Getelementsbytagname('name')
name = name.item(4)
print,(name.getfirstchild()).getnodevalue()
; 获取属性值
cropRegion = XML.Getelementsbytagname('cropRegion')
cropRegion = cropRegion.Item(4)
print,cropRegion.GetAttribute('height')
; 销毁对象
Obj_destroy, name
Obj_destroy, XML
END

; IDL控制台输出结果
% Compiled module: DEMO02.
Homestyle Breakfast
5678

👀TXT

TXT示例源文件:

lon	lat	area
101 50 20
102 51 22
103 52 24
104 53 21
105 54 25
106 55 20
107 56 25
108 57 20
109 58 18
110 59 20.58333333
111 60 20.36666667
112 61 20.15
113 62 19.93333333
114 63 19.71666667
115 64 19.5
116 65 19.28333333

读取TXT文件:

pro Demo02
; 文件路径
fn = 'D:\Desktop\data_p1.txt'
; (1)第一种方法,打开txt文件
; 如果你只是读文件openr就可以了,openw既可以读也可以写(会覆盖原来的文件,慎用)
; 第一个lun用来表示这个文件的内存地址,第二个fn是该文件的路径,第三个/get_lun动态获取地址
openr, lun, fn, /get_lun
; 由于第一行是索引,索引是文字,索引下面是数字, 两者类型不一致,不能放在一个数组里面存储,所以需要跳过
; 第一个lun表示文件的编号或者说是内存地址的代称,第二个1表示需要跳过的行数,这里只跳过第一行,所以是1,第三个表示第二个参数的单位是行而不是列
skip_lun, lun, 1, /lines
; 创建存储的数组
; 通过记事本打开该文件事先查看到该文件的数据的行列数(共有3列17行,但是第一行跳过所以只需要16行)
data = fltarr(3,16)
; 获取文件的数据
readf, lun, data
; 检验一下,获取某一个数据
print, data[2, -1]
; 关闭文件
free_lun,lun

; (2)第二种方法,打开txt文件
openr, lun, fn, /get_lun
; 获得第一行的索引数据,也是有用的(获取列数)
; 预先有一个str变量存储
str = ''
; readf是秉承着有多少给多少,现在str是一个字符串,默认输出一行,如果你是数组,那么根据数组的行列数有多少给多少
; 对得到的存储有第一行索引数据的str变量进行分析,通过该字符串分析出整个数据有多少列
Readf, lun, str
; 默认以空格作为该字符串的分隔符
son_str_array = Strsplit(str, /extract)
; son_str_array里面有几个元素,那么整个数据就有几列
column = N_elements(son_str_array)
; 现在获取行数,第一行是索引,所以需要减去1
row = File_lines(fn) - 1
; 创建存储的数组
box_data = Fltarr(column, row)
; 获取数据(这里行数是从第二行开头开始的,因为前面已经readf, lun, str,文件指针已经指到第二行开头处)
Readf, lun, box_data
; 检验一下,获取某一个数据
Print, box_data[2, -1]
; 关闭文件
Free_lun, 1

; (3)第三种方法,打开txt文件
Openr, lun, fn, /get_lun
skip_lun, lun, 1, /lines
; 读取文件的行数
row = File_lines(fn) - 1
; 创建存储的列表,列数是通过txt记事本打开看到的
; 相对来说,列数比较固定,行数不确定
box_data2 = Fltarr(5, row)
Readf, lun, box_data
; 检验一下
Print, box_data[2, -1]
; 关闭文件
Free_lun, lun
END

; IDL控制台输出结果
% Compiled module: DEMO02.
19.2833
19.2833
19.2833

写入TXT文件:

pro print_test
; 写入txt
outfilepath='D:\Desktop\'
outfilename = STRCOMPRESS(outfilepath+'navi_route.txt',/remove_all)
openw,var_lun,outfilename,/get_lun
for i=1,365 do begin
z=i/2
if z gt 10 then begin
z=1024
endif else begin
z=150+i
endelse
printf,var_lun,FORMAT='(I3,I10)',i,z
endfor
close,var_lun
free_lun,var_lun

; 读取对应txt
infilepath='D:\Desktop\'
Cd,infilepath
thesefiles = File_search('navi_route.txt')
result=Intarr(2,365)
Openr,lun,thesefiles[0],/get_lun
FOR i=0,365-1 DO BEGIN
Readf,lun,FORMAT='(I3,I10)',day,value
result[0,i]=Long(day)
result[1,i]=Long(value)
ENDFOR
Free_lun,lun
Print,result
END

; IDL控制台输出结果
% Compiled module: PRINT_TEST.
1 151
2 152
3 153
4 154
5 155
6 156
7 157
8 158
9 159
10 160
11 161
... ...
358 1024
359 1024
360 1024
361 1024
362 1024
363 1024
364 1024
365 1024