上一篇 | 下一篇

用FileIO读取二进制数据

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

  原著:David Pollock 奥古多媒体3N)vF'C/u
  翻译:DCM
}$o+Z(]{)Qr4]
J(crR'I-i   我有一个project,需要直接从以二进制形式储存的数据库中读取数据。看来我需要诸如BinaryIO或者BinaryMaster的Xtra去从磁盘上读取了,但是利用FileIO,做稍许工作,也可以做到读写二进制文件。奥古多媒体-F{T_|*G^D
奥古多媒体J2p'@S9TNT
  FileIO专注于一件事情:读写ASCII文本文件。不能读取二进制文件的主要原因是当遇到0字节时,被当作ASCII字符0-即空字符-文件结束的标志。因为二进制文件中有大量的0存在,你也就不能读出所需要的数据了。奥古多媒体Xi t/N-kzRS5S9q
奥古多媒体Os&Fv,PN\
  FileIO中的getLength和readChar函数
1Kj0?G9uHk"f 奥古多媒体#w4?Zwx:J6` V
  幸运的是,FileIO有许多其它的函数让我们绕过这个限制。首先是Getlength,能够准确地得到文件的字节数(在文本文件中,一个字节代表一个ASCII字节,但在二进制中不同,在后面再来解释)。奥古多媒体,s\"C8O3|-y
  其次我们会以ReadChar代替ReadFile。ReadChar读取一个字节或字符后,移到下一个字节并等待。重要的是ReadChar并不关心读到字节是否是0,它将返回一个空字符串给Lingo交移到下一个字节。奥古多媒体f }f p iw,G)N

"f'?8mR \+}   二进制数据
bE$rs|`*H1aX
Px0JN+}I.LFNJ   现在我们有办法知道文件中有多少字节,也能够读取每一个字节了。接下来的事情是什么数据是我们所需要的。如果我们保存所有读取到的字节,问题不亚于用ReadFile函数了。在Lingo中,0字节等同于empty,或者" ",在字符串中不会增加任何东西。
1s!T-bS6a6^ 奥古多媒体2fx"Cb)i
  很明显的变通办法是将所有读出的数据作为一个字符串保存在线性列表里(也有其它办法,例如使用Image object),再由CharToNum函数将这些字符串数据转换成数字。这样,文件中每个字节的值都可加入线性列表中,我们就可以操作这些数据了。下面是其代码:
LCO(lr!Hr 奥古多媒体fAV?^:AE
on readBinaryFile filePath
`$H| l9mq"iZE -- Call handler using the full file path
|1D(}d _A4r
/\v0A0n3u[/x byteList = []奥古多媒体vR2h ]`ob
-- This list will contain all of the byte values retrieved奥古多媒体-@H5h#c ei
fileObj = new(xtra "fileIO")奥古多媒体Yn b({@3W"V:b?
fileObj.openFile(filePath, 1)奥古多媒体*Rh0V M3Fek vE|Z
-- Open the file with read-only access
nXl-o{O7o~%o
tfnvR*N$f,^2e if fileObj.status() = 0 then
LX_#pBH fileLength = fileObj.getLength()
.` C;v\-YY9o -- Find the length of the file in bytes奥古多媒体_(~Uj0z F0K.{c
repeat with index = 1 to fileLength
Lh2va)Mi{ byteList.append(charToNum(fileObj.readChar()))
'~AQDby Ju -- Append the value of each byte of the file to byteList奥古多媒体:~J"G L7u8|}[v
end repeat
5~B6sX$em"T#G end if
Oa4\:?8jF,KM
4oS/g^i`j fileObj.closeFile()奥古多媒体WJ AzwOE*`2}}
-- Close the file
:_ M6B:m \pD"Br fileObj = 0奥古多媒体,C P\0J"PvR^0}
-- Clear the FileIO instance from memory奥古多媒体IE,ym7{F}
return byteList奥古多媒体@1f*F'fS5vN

1f6E o&k8bv/H&m Y+J end 奥古多媒体!cAa,Ioc]

)M9wS$y7G"`@   关键在于弄清Repeat循环,结合使用ReadChar函数,让FileIO保持从文件中读取数据,不管所遇到的字符值。这样我们就有办法完整地读取任何文件。奥古多媒体!T(_B,jJv4qw} h3Q/\
奥古多媒体NIm+f#^5a
  读取长文件 奥古多媒体EI&p6lE5~q
奥古多媒体/IgT%K2k x q I0J
  你会想到的一个问题是,使用readBinaryFile程序读取长文件时会返回一个极大的byteList 变量,占用许多内存。假如我们知道哪部分数据是我们想要的,可以这样作轻微的修改。奥古多媒体;E{j U0e"tH~
奥古多媒体/`Q.G$P1N F:C.jc
on readBinaryFile filePath, startByte, endByte
E){5o5iuf7p E5A~ -- Optional parameters for specifying positions in the file奥古多媒体,R/X)oXs q
byteList = []奥古多媒体4n"y.eN#y:h
fileObj = new(xtra "fileIO")
\t:AI yZ'q6npE fileObj.openFile(filePath, 1)
1H)@ |:?(s)vEg.`3o
X6LYbv-A7_(uMs if fileObj.status() = 0 then奥古多媒体4}D-I9E&]v6Y2l'l
fileLength = fileObj.getLength()奥古多媒体YN6^8Ag Eim"N
奥古多媒体 ~_9QF Y J*D
if startByte.voidP then
sc CBK E [ -- Read entire file if parameters aren't supplied奥古多媒体;E-}'zp/sn\DQ!PSJ
startByte = 1奥古多媒体^$Oj.I4}0pA
endByte = fileLength
RPg3w9a-w8q%bQ end if奥古多媒体"P)L,D2y"K`F-N

$^b9en {
T&hSv!Xr3_? if (fileLength >= startByte) and (fileLength >= endByte) then
V7iM g!a0_Ch fileObj.setPosition(startByte-1)奥古多媒体 Hn1s%p*_9},| NJ
-- Position FileIO to read from the correct point in the file奥古多媒体5YtBl2s'E^_
repeat with index = startByte to endByte奥古多媒体9VV@c p4m;Ay'{ T
byteList.append(charToNum(fileObj.readChar()))
?+` TN,ay0?%| end repeat奥古多媒体HFH@3A!PC EQ
end if
p1[WH k\4n end if 奥古多媒体G!j3Gz;D ]
奥古多媒体b2|&|/x`.I
fileObj.closeFile()奥古多媒体|$f3M8c3FbrB
fileObj = 0
;m V'[X)P6Q*}'p;a#z0u(o,i return byteList奥古多媒体(H ]O&is4V?$B#`)r
end 奥古多媒体:zP;?#tCP6DY1N+V
奥古多媒体Tx}z.j"k
  例子:读取MP3标签奥古多媒体$}8ovA.uA

8V*F:Y(YX)jD   使用这个程序的真实例子是读取MP3文件标签。MP3文件标签存储在最后的128个字节中。本例子包含有一个Director movie,说明是如何做到这一点的(需要FileXtra和FileIO Xtra)。关于文件格式,可参考www.wotsit.org
+_`ec{ 奥古多媒体1_cf-NwN5f H
  此例子程序从MP3文件中读取了诸如歌名、歌手、专辑名、年份、风格等信息。奥古多媒体AC'C3U#u%k]_

c:X:_&S;}t/{ on readMP3tags filePath奥古多媒体@ K;[rIsV*?7lH

%J)h`+ms6@ fileLength = getFileSizeInBytes (filePath)奥古多媒体zS/I V$X,E j|g*@
if fileLength > 0 then
9vWHDy'P byteList = readBinaryFile (filePath, fileLength - 127, fileLength)奥古多媒体5MA)G3gD{A$N&k'K
tagStr = ""
,A^)j4s3M} repeat with index = 1 to byteList.count奥古多媒体d-m,Qg ?l5O [
tagStr = tagStr & numToChar (byteList[index])
;?V U_!B@V1w end repeat奥古多媒体h k`v|DEt&rb

7B8mu5Xt0]aN3G6Lx 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)]奥古多媒体 gv^xg
奥古多媒体s!T$I%\2r5p/?
repeat with index = 1 to tags.count奥古多媒体v Hwhi(P? KFj
memberName = string (tags.getPropAt (index))奥古多媒体%@X DBjB
newText = clipString (tags[index])奥古多媒体W` h|9[
member (memberName).text = newText奥古多媒体7{9wf!? w3j*pWK.\
end repeat
o;V hXM'UW K end if奥古多媒体dG"j+W;LsYCj az

Uy1SCW!fS end奥古多媒体[N b{dT;s/V g

0PXI)a} 相关附件

字号: | 推荐给好友

 

评分:0

我来说两句

seccode