TCL脚本完成二进制文件存取
王敏志
概述
项目电路板测试,特别是需要从FPGA收集一些测试数据的时候可以通过Altera提供的virtual JTAG接口来完成。开发调试平台需要使用TCL脚本来设计,收集到的数据可以存储到一个文件里面,对于TCL脚本来说,任何数据都被认为是字符,所以存储成文本格式是很方便的,但是由于项目测试另一个平台是利用LabView或者C++来分析数据,而LabView或者C++程序设计者希望数据存储在二进制文件中。笔者折腾用TCL读二进制文件以及TCL将数据存储成二进制格式文件,好长时间才搞定,特记录于此已备时间一长遗忘,因为不常用,备后续参考。
TCL读取二进制文件
一般读取文本文件很简单,代码如下所示:
set chan [open "file_t" r]
set myfile1 [open "file_t1" w]
while {[gets $chan line] >=0} {
puts $myfile1 $line
}
上述代码第一句是先打开一个文件“file_t”并开始读这个文件,这是一个文本文件。第二句是打开一个文件“file_t1”并开始写,如果这个文件不存在,那么就创建这个文件。最后的while循环是将第一个文件里的内容全部写入到第二个文件中。相当于复制黏贴。
文件file_t只是一个文本文件,文件里的内容如图1所示,笔者在使用Virtual JTAG处理数据的时候一般都是按照图1所示的格式存储,也即每一行只存储一个数据,所以在使用上述代码while循环里就可以直接逐一对数据读出并进行相关处理。
图1:文本文件中的内容
那么如果存在一个二进制格式的数据文件,应该如何将数据读出来呢?首先我们来看二进制数据文件的存放格式,如图2所示。
图2:二进制格式文件内容
图1和图2存放的内容都是一样的,注意二进制格式存放的时候需要定义每一个数据位宽,这里给每个数据定义为32-bit,所以我们看图2的第一个数据是0,第二个数据是0x100000,即1048576,后面数据依次类推。所以如果要将图2所示的数据读出来,那么在打开这个文件以后首先要对其进行配置,因为TCL默认认为打开的文件是字符格式,具体代码实现如下所示:
set chan [open "lg5mm.dat" r]
fconfigure $chan -translation binary
while {1} {
set data_read [read $chan 4]
;##一次读4个字节,即32bit,在循环体中,该命令似乎可以自动连续往后读。
binary scan $data_read "H*" tmp0;##将这4个字节转换成16进制数据
set m_val [get_m $tmp0]
set x_val [get_x $tmp0]
set y_val [get_y $tmp0]
pain_cross_star $m_val $x_val $y_val
incr cnt
if {$cnt > 10000} {
close $chan
break
}
第一句和上面一样,先是打开一个文件,并开始读。第二句是给刚刚打开的文件配置“二进制”属性。读的时候使用“read”命令,由于我们定义一个数据的位宽是32-bit,所以每次需要读四个字节。Binary scan是将读出来的32-bit数据转换成16进制数据,否则默认读出来的数据认为是字符格式。
TCL存储数据成二进制格式
上一节讲述了如何从二进制格式文件中读取数据并进行处理,这一节介绍一下如何将数据存储成类似图2所示的二进制格式文件。
首先我们还是来看看默认TCL脚本是如何存储数据到文件的,由于数据默认认为是字符格式,所以存储后的数据文件就是图1所示的格式。具体代码如第一节所示。即file_t1和file_t中的内容都是如图1所示那样。那么如何才能将file_t中的文件存储成图2所示那样呢?具体代码如下所示。
set chan [open "file_t" r]
set my_binfile [open "bin_file.dat" w]
fconfigure $my_binfile -translation binary
set a 0
while {[gets $chan line] >=0} {
set a [binary format "I1" $line]
puts -nonewline $my_binfile $a
}
第一句同样是打开一个要读取的文件,即file_t,第二句是打开一个文件,即bin_file.dat,如果文件不存在那么创建这个文件,打开属性是“w”。第三句是配置刚刚创建的文件配置成“二进制”属性。第四句定一个临时变量a,并赋值为0。While循环里从file_t逐行读出数据(千万记住每一行只有一个数据),将每行读出的数据首先转换成二进制格式,转换后将二进制格式数据写入二进制文件,注意此时带上写入参数“nonewline”。需要特别注意的是数据格式转换的时候使用了“I1”参数,“I”表示将一个或多个整数转换成32-bit,且字节顺序是Big-endian模式,如果“i”则是Little-endian模式。如果不是32-bit,那么可以查此命令找到相关参数(c/C指定8-bit,s/S指定16-bit等等)
分析及结论
二进制文件处理在项目测试阶段非常有用,在分析数据的时候如果数据量庞大,如果按照字符模式,且每一行只存放一个数据那么数据文件的容量将非常之大,如果采用二进制格式,可以大大减少文件存放容量,同时可以统一各个平台之间的数据格式,所谓一举多得啊。
用户1651405 2014-3-17 16:39
用户91462 2009-12-5 13:45
用户1364249 2008-5-3 11:52