初级视频编辑室|草蜢非编论坛|初级视编室|草蜢视频编辑|会声会影|威力导演|电子相册

 找回密码
 加入初编室
搜索
查看: 1170|回复: 3
打印 上一主题 下一主题

[Director 多媒体爱好者] 用FileIO读取二进制数据

[复制链接]

296

主题

1132

帖子

2万

积分

超级版主

Rank: 8Rank: 8

论坛版主精华帖勋章

跳转到指定楼层
楼主
发表于 2014-11-24 21:34:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
onekey onekey
原著:David Pollock
  翻译:DCM

  我有一个project,需要直接从以二进制形式储存的数据库中读取数据。看来我需要诸如BinaryIO或者BinaryMaster的Xtra去从磁盘上读取了,但是利用FileIO,做稍许工作,也可以做到读写二进制文件。

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

  FileIO中的getLength和readChar函数

  幸运的是,FileIO有许多其它的函数让我们绕过这个限制。首先是Getlength,能够准确地得到文件的字节数(在文本文件中,一个字节代表一个ASCII字节,但在二进制中不同,在后面再来解释)。
  其次我们会以ReadChar代替ReadFile。ReadChar读取一个字节或字符后,移到下一个字节并等待。重要的是ReadChar并不关心读到字节是否是0,它将返回一个空字符串给Lingo交移到下一个字节。

  二进制数据

  现在我们有办法知道文件中有多少字节,也能够读取每一个字节了。接下来的事情是什么数据是我们所需要的。如果我们保存所有读取到的字节,问题不亚于用ReadFile函数了。在Lingo中,0字节等同于empty,或者" ",在字符串中不会增加任何东西。

  很明显的变通办法是将所有读出的数据作为一个字符串保存在线性列表里(也有其它办法,例如使用Image object),再由CharToNum函数将这些字符串数据转换成数字。这样,文件中每个字节的值都可加入线性列表中,我们就可以操作这些数据了。下面是其代码:

on readBinaryFile filePath
-- Call handler using the full file path

byteList = []
-- This list will contain all of the byte values retrieved
fileObj = new(xtra "fileIO")
fileObj.openFile(filePath, 1)
-- Open the file with read-only access

if fileObj.status() = 0 then
fileLength = fileObj.getLength()
-- Find the length of the file in bytes
repeat with index = 1 to fileLength
byteList.append(charToNum(fileObj.readChar()))
-- Append the value of each byte of the file to byteList
end repeat
end if

fileObj.closeFile()
-- Close the file
fileObj = 0
-- Clear the FileIO instance from memory
return byteList

end

  关键在于弄清Repeat循环,结合使用ReadChar函数,让FileIO保持从文件中读取数据,不管所遇到的字符值。这样我们就有办法完整地读取任何文件。

  读取长文件

  你会想到的一个问题是,使用readBinaryFile程序读取长文件时会返回一个极大的byteList 变量,占用许多内存。假如我们知道哪部分数据是我们想要的,可以这样作轻微的修改。

on readBinaryFile filePath, startByte, endByte
-- Optional parameters for specifying positions in the file
byteList = []
fileObj = new(xtra "fileIO")
fileObj.openFile(filePath, 1)

if fileObj.status() = 0 then
fileLength = fileObj.getLength()

if startByte.voidP then
-- Read entire file if parameters aren't supplied
startByte = 1
endByte = fileLength
end if


if (fileLength >= startByte) and (fileLength >= endByte) then
fileObj.setPosition(startByte-1)
-- Position FileIO to read from the correct point in the file
repeat with index = startByte to endByte
byteList.append(charToNum(fileObj.readChar()))
end repeat
end if
end if

fileObj.closeFile()
fileObj = 0
return byteList
end

  例子:读取MP3标签

  使用这个程序的真实例子是读取MP3文件标签。MP3文件标签存储在最后的128个字节中。本例子包含有一个Director movie,说明是如何做到这一点的(需要FileXtra和FileIO Xtra)。关于文件格式,可参考www.wotsit.org

  此例子程序从MP3文件中读取了诸如歌名、歌手、专辑名、年份、风格等信息。

on readMP3tags filePath

fileLength = getFileSizeInBytes (filePath)
if fileLength > 0 then
byteList = readBinaryFile (filePath, fileLength - 127, fileLength)
tagStr = ""
repeat with index = 1 to byteList.count
tagStr = tagStr & numToChar (byteList[index])
end repeat

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)]

repeat with index = 1 to tags.count
memberName = string (tags.getPropAt (index))
newText = clipString (tags[index])
member (memberName).text = newText
end repeat
end if

end
楼主热帖
河边已是一首歌
回复

使用道具 举报

206

主题

4527

帖子

7万

积分

初编室元帅

Rank: 14Rank: 14Rank: 14Rank: 14

活跃会员帅哥会员百帖纪念荣誉勋章论坛万元户

沙发
发表于 2014-11-24 21:59:33 | 只看该作者
谢谢楼主提供分享!!

42

主题

3547

帖子

2万

积分

初编室元帅

Rank: 14Rank: 14Rank: 14Rank: 14

板凳
发表于 2014-11-25 09:17:30 | 只看该作者
全是英文的,看不懂的。。。

131

主题

5845

帖子

12万

积分

初编室元帅

Rank: 14Rank: 14Rank: 14Rank: 14

帅哥会员活跃会员论坛万元户百帖纪念荣誉勋章

地板
发表于 2015-1-21 11:52:55 | 只看该作者
阳春白雪,逛一逛,看一看,顶一顶。
您需要登录后才可以回帖 登录 | 加入初编室

本版积分规则

手机版|小黑屋|初级视频编辑室

GMT+8, 2024-12-27 01:05 , Processed in 0.111689 second(s), 30 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表