IDL之文件读写操作【CSV/XML/TXT】

⛄前言

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

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

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

⛄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

多谢!多谢!
笔者不才,请多交流!!!

欢迎大家关注预览我的博客Blog:HeartLoveLife
能力有限,敬请谅解!!

  • 22
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值