上一篇 | 下一篇

用FileIO读取二进制数据

发布: 2007-1-25 17:20 | 作者: David Pollock | 来源: 译自director-online.com | 查看: 622次

  原著:David Pollock 奥古多媒体"lQ~-K Kx
  翻译:DCM
@UsQljK.Dx/CJ,O 奥古多媒体%gl']Iu x
  我有一个project,需要直接从以二进制形式储存的数据库中读取数据。看来我需要诸如BinaryIO或者BinaryMaster的Xtra去从磁盘上读取了,但是利用FileIO,做稍许工作,也可以做到读写二进制文件。奥古多媒体(~#_h/nwb _'f's V

lrx d9gBqo   FileIO专注于一件事情:读写ASCII文本文件。不能读取二进制文件的主要原因是当遇到0字节时,被当作ASCII字符0-即空字符-文件结束的标志。因为二进制文件中有大量的0存在,你也就不能读出所需要的数据了。奥古多媒体e? Q.?!L U

4M0\,t;V(~6z tQn   FileIO中的getLength和readChar函数
6@T:cOU&f cs
!O:zga4c_   幸运的是,FileIO有许多其它的函数让我们绕过这个限制。首先是Getlength,能够准确地得到文件的字节数(在文本文件中,一个字节代表一个ASCII字节,但在二进制中不同,在后面再来解释)。奥古多媒体)n1k4Lw&S*S |BZx9o
  其次我们会以ReadChar代替ReadFile。ReadChar读取一个字节或字符后,移到下一个字节并等待。重要的是ReadChar并不关心读到字节是否是0,它将返回一个空字符串给Lingo交移到下一个字节。奥古多媒体X jK%A K2WS#}
奥古多媒体~Bl,Jg |
  二进制数据
G](@XY l}zd9e 奥古多媒体qJ#rR9|?y
  现在我们有办法知道文件中有多少字节,也能够读取每一个字节了。接下来的事情是什么数据是我们所需要的。如果我们保存所有读取到的字节,问题不亚于用ReadFile函数了。在Lingo中,0字节等同于empty,或者" ",在字符串中不会增加任何东西。
K2GbN)|+y4iw
|/k4noc[   很明显的变通办法是将所有读出的数据作为一个字符串保存在线性列表里(也有其它办法,例如使用Image object),再由CharToNum函数将这些字符串数据转换成数字。这样,文件中每个字节的值都可加入线性列表中,我们就可以操作这些数据了。下面是其代码:
N3nsv+a-SY&n 奥古多媒体~m*X7qA?
on readBinaryFile filePath奥古多媒体dm:d?1S
-- Call handler using the full file path奥古多媒体H+Y)W TI ^+Y'zh Z
奥古多媒体9wF a+J)gx5S!u4E,x
byteList = []
On1_1uOC9{ -- This list will contain all of the byte values retrieved
/M8IRu+O f0f~(Ez W| fileObj = new(xtra "fileIO")奥古多媒体7j-c5o@V#@#h [9th
fileObj.openFile(filePath, 1)
"K&{?z|4WDU4m -- Open the file with read-only access 奥古多媒体.d X#J6cT ^-[&T
奥古多媒体${8G;N'xQ*\ j.w
if fileObj.status() = 0 then
jx}3Y6p ]2M ~ fileLength = fileObj.getLength()奥古多媒体}IO3X1o
-- Find the length of the file in bytes奥古多媒体/n sa8_q L
repeat with index = 1 to fileLength
dk*y n4S byteList.append(charToNum(fileObj.readChar()))奥古多媒体DeQ5t|,H;h*P
-- Append the value of each byte of the file to byteList奥古多媒体 [(uqRK_
end repeat奥古多媒体B#BN E&F8{6L
end if
(a'~Os#Xi2H+d 奥古多媒体 J#sX*x|ag8sZp
fileObj.closeFile()
2Uji%A:]&I2w8g -- Close the file奥古多媒体 |y+kVq2O+B
fileObj = 0奥古多媒体 ?+m3v4M6t%Q
-- Clear the FileIO instance from memory
n#|1aW rL-D return byteList奥古多媒体 j9C.}-Q!`0`CP{0qO

.HBvIwTH end
8T1du6]?NZ-Z 奥古多媒体?oY!A6f0k~ x:u ~2gx
  关键在于弄清Repeat循环,结合使用ReadChar函数,让FileIO保持从文件中读取数据,不管所遇到的字符值。这样我们就有办法完整地读取任何文件。
B$aE;^+m3m,n7fS~
/~)W9T Kv{.oR   读取长文件
;_Bg*n#sCe 奥古多媒体%u6{h4io5v
  你会想到的一个问题是,使用readBinaryFile程序读取长文件时会返回一个极大的byteList 变量,占用许多内存。假如我们知道哪部分数据是我们想要的,可以这样作轻微的修改。奥古多媒体*n8wj%\dr1E

g'Q6uSE`(} on readBinaryFile filePath, startByte, endByte奥古多媒体"Qb4s|,KN p)l u$s
-- Optional parameters for specifying positions in the file奥古多媒体 f5Hu}j
byteList = []奥古多媒体3U&_7v ~ \%]u
fileObj = new(xtra "fileIO")
'BJ2u6I)ne1s8k fileObj.openFile(filePath, 1) 奥古多媒体MSyi,w
奥古多媒体"}$h6e2g*GY
if fileObj.status() = 0 then奥古多媒体Z4YH+_/_Y"c
fileLength = fileObj.getLength()
+f,dzuh0n-R9S`W 奥古多媒体V8P9GP7V ^
if startByte.voidP then奥古多媒体^;Fg-s9U^.G%f
-- Read entire file if parameters aren't supplied
D2P(~}Y startByte = 1
Aey4T%Qz endByte = fileLength奥古多媒体0mSsZzy4{^
end if
)\)H"n+c1FM)Ui0@]
3B3Pn%}(d
1e3f&e3a%^.d if (fileLength >= startByte) and (fileLength >= endByte) then
]HX3i(i5C fileObj.setPosition(startByte-1)
O"[4j Y*m [\ K -- Position FileIO to read from the correct point in the file
t|eeMEtA repeat with index = startByte to endByte
2o5}J#fL U byteList.append(charToNum(fileObj.readChar()))奥古多媒体ozs!J*A!Qm God
end repeat
0S7Z9H:T {*W end if
7v+jg,D.p snj2^\ end if
BBK uN`v0Tb
F@%z |0y L fileObj.closeFile()奥古多媒体/rW j8DQT!r}k
fileObj = 0奥古多媒体Wf![%fx K+`M%h
return byteList奥古多媒体z(C3j~7F+I*vX
end 奥古多媒体N8g,NdC#^

)?"Na+SVi#iQ8x   例子:读取MP3标签
a|,om^
\8B0_(i] gf*Z   使用这个程序的真实例子是读取MP3文件标签。MP3文件标签存储在最后的128个字节中。本例子包含有一个Director movie,说明是如何做到这一点的(需要FileXtra和FileIO Xtra)。关于文件格式,可参考www.wotsit.org
T)q+o,nm ]B
\1{P N|,R J G#r   此例子程序从MP3文件中读取了诸如歌名、歌手、专辑名、年份、风格等信息。奥古多媒体KGUz4c4]2m O;I

{&JIJp[%u;{ on readMP3tags filePath奥古多媒体b"yoe9UoV[9^xn

oYs4?|jo fileLength = getFileSizeInBytes (filePath)奥古多媒体P!F!{})I"a8v
if fileLength > 0 then奥古多媒体 @C*K@$RmU%?a
byteList = readBinaryFile (filePath, fileLength - 127, fileLength)
F#kIb [6O`m tagStr = ""奥古多媒体j6K/w'IKRs
repeat with index = 1 to byteList.count奥古多媒体G3[j2O0S"N Y
tagStr = tagStr & numToChar (byteList[index])
Ji?6\r['I e:p end repeat奥古多媒体,`o.JK+{2J7`;H(p

${wB R(y-P8c/R tags = [#title: tagStr.char[4..33], #artist: tagStr.char[34..63], #album: tagStr.char[64..93], #year: tagStr.char[94..97], #genre: getGenre (charToNum (tagStr.char[128]) + 1)]奥古多媒体2{8Y8IJnP_2~ [f+E

2f#r7|PI*~3a repeat with index = 1 to tags.count奥古多媒体S+Y1_.D~6]!u2E
memberName = string (tags.getPropAt (index))奥古多媒体] ag:[2CuD
newText = clipString (tags[index])
A3L1Q1E{ member (memberName).text = newText奥古多媒体/S!V p X[qT$t
end repeat
X4eM'ob}d z end if奥古多媒体ze*@2?dm(EY
奥古多媒体'G [B+PnKmYI
end
!z]u*V {0a{M(S ^c
j:r(h,I:p)I 相关附件

字号: | 推荐给好友

 

评分:0

我来说两句

seccode


音乐
落叶 画心 放生 天亮了 牡丹江 那滋味 擦肩而过 怀念过去 北京欢迎你 突然好想你 吻的太逼真 说好的幸福呢 坐上火车去拉萨 如果爱能早些说出来
愚爱 心碎 稻香 带我走 醉赤壁 魔杰座 我还想她 为你而活 一定要爱你 等爱的玫瑰 原谅我一次 越单纯越幸福 最后一次的温柔 给我一首歌的时间
白狐 光荣 火花 下雨天 小酒窝 樱花草 为你写诗 无可取代 无情的温柔 寂寞才说爱 忘不掉的伤 爱上你是个错 陪你一起看草原 地球人都知道我爱你
城府 假如 花海 兰亭序 爱太痛 舍不得 你若成风 女人如烟 外滩十八号 我们的纪念 摇滚怎么了 和寂寞说分手 爱上你是我的错 爱情里没有谁对谁错