NAV
lua

Introduction

Welcome LFS API

LFS 是非常非常快的文件系统,可以同时存储海量大文件和小文件,高并发。

许多存储方案或者优于存储大文件,或者优于存储小文件,在 LFS 中则一视同仁。所以既可以用来存储视频音乐,也可以用来存储图片。

使用 LFS 可以轻易构建出一个倒排:example

LFS 的有趣之处在于,DataFile 具有类似数组的特性,看起来就像是控制数组而不是数据。

LFS 使用 lua 作为脚本语言(快并且简单),可以提供更细致的逻辑处理。

共有 LFSvars, out, buffer 这几个全局对象。(清晰明了)

链接:github git@osc

LFS

LFS 中定义的类

Class Description
DataFile 普通的数据文件:提供原始数据的读写(最常用的类, 几乎所有的操作都基于此)
UniqueFile 唯一文件:通过 IndexKey 来标识记录的唯一性
InvertFile 倒排文件:用来存储指向一个 [相同属性] 的所有记录 ID
IndexKey 索引 key:将字符串或字节数组转换成可被索引的哈希
ByteArray 字节数组:提供对原始字节的高级读写

vars global

[read-only] 客户端传入的变量数组,下标从 0 开始。

length property

length:uint [read-only]

变量数组的长度。

getLength

getLength(index:uint):uint

返回数组中 index 指定位置的变量长度。

getType

getType(index:uint):int

返回数组中 index 指定位置的变量类型。

Return Type
1 byte
-1 ubyte
2 short
3 ushort
4 int
5 uint
6 float
7 double
8 long
-4 String
-5 StringBytes
-3 bytes
-2 Boolean
0 null

buffer global

buffer 是一个 ByteArray 对象。

当从 DataFile 等文件中读取文档时,会自动读入到 buffer 中,然后通过 ByteArray 的方法对数据进行访问。

sizeTotal property

sizeTotal:ulong [read-only]

当从 DataFile 等文件中读取文档时,sizeTotal 会返回文档的总大小。

out global

输出字节流:用来将数据返回给客户端。

setState

setState(state:int):void

设置返回给客户端的状态。(0 为成功)

通过设置 state 来简便指定当前执行是否成功。

getState

getState():int

返回当前的执行状态。若从未设置过 state,则一直为默认值:0。

setPosition

修改一个已经存在于 out 中的值

local resultState_position = out:getPosition(); -- 首先记录下 position
out:putInt(0); -- 占位(此时尚未知道执行结果。假设返回的数据结构要求 resultState 放在头部)
out:putString(str);
-- 省略部分语句
local current_position = out:getPosition(); -- 记录下当前的 position
out:setPosition(resultState_position); -- 设置回需要添加头的位置
out:putInt(resultState); -- 将 resultState 写入之前占位的地方
out:setPosition(current_position); -- 重新设置回最后的位置,因为接下来还需要返回其他内容
-- 省略部分语句
out:putString(str2);

setPosition(position:uint):void

设置当前的偏移。

getPosition

getPosition():uint

返回当前的偏移位置。

putString

putString(str:Bytes, offset:uint = 0, length:uint = 0):void

类似:ByteArray:writeBytes

putStringBytes

putStringBytes(strBytes:Bytes, offset:uint = 0, length:uint = 0):void

类似:ByteArray:writeBytes

putBytes

putBytes(bytes:Bytes, offset:uint = 0, length:uint = 0):void

类似:ByteArray:writeBytes

putBoolean

putBoolean(value:Boolean):void

putByte

putByte(value:byte):void

putUByte

putUByte(value:ubyte):void

putShort

putShort(value:short):void

putUShort

putUShort(value:ushort):void

putInt

putInt(value:int):void

putUInt

putUInt(value:uint):void

putLong

putLong(value:long):void

putFloat

putFloat(value:float):void

putDouble

putDouble(value:double):void

putNull

putNull():void

DataFile Class

普通的数据文件:提供原始数据的读写(最常用的类, 几乎所有的操作都基于此)

一个 DataFile 最多可以存储 2^32 - 1 个记录(每个记录即表示为一个独立的文档,所有的“记录”或“文档”表示相同的概念)

new constructor

new(path:String = null):DataFile

open

打开文件

local photosFile = LFS.DataFile.new();
photosFile:open("app/photos");

open(path:String):void

打开文件

setOne

该操作等同于

if (myFile:getTotalFile() == 0) then;
    myFile:write(0, nil, 0); -- 占用一个空的记录
    myFile:remove(0); -- 删除该记录,用来保证 getFileLength 的值是正确的
end;

setOne(value:Boolean):void

设置文档 id 是否跳过 0 从 1 开始。

setSize

setSize(id:long, sizeTotal:ulong, sizeBlockMin:uint = 0, flag:uint = 0):long

根据 id 设置文档的大小,返回真实的文档 id

参见 write

write

追加一个图片文档

local photoBytes = vars[1]; -- 从传入的数组中取出图片数据
local id = photosFile:write(-1, photoBytes);
out:putLong(id); -- 返回文档 id

更新文档

local text = "new document";
local id = myFile:write(-1, text, -1, 0, 0, 3);
text = "update text";
id = myFile:write(id, text, 6, 4, 0, 3); -- result: "new updatent"

write(id:long, buffer:byte[], bufferLength:ulong = MAX, offset:ulong = 0, sizeBlockMin:uint = 0, flag:uint = 0):long

根据 id 写入数据,并返回真实的记录 id(0 <= id < 2^32),如果返回的 id < 0 则表示失败。

Parameter Default Description
id 0 不能为空(-1 <= id < 2^32),-1 表示写入新的记录
buffer null 不能为空。如果为空,此时将写入空的记录,如果原来该记录存在数据,将会被删除
bufferLength MAX 默认等于 buffer.length(0 <= bufferLength <= buffer.length)
offset 0 起始偏移(注意:这是 id 指向的记录的偏移,而不是 buffer 的偏移)
sizeBlockMin 0 如果当前需要写入的数据长度小于 sizeBlockMin,则用字节 0 补齐(相当于为将要写的 block 分配可用空间,如果此记录的数据长度频繁增长,将会有效提高写入效率。比如:倒排文件(InvertFile)就是一个非常典型的用例)
flag 0 操作标识,有效值为 0, 1, 2, 3

flag

Value Description
0 先删除旧的数据,然后写入新的数据
2 在 0 的基础上覆盖写入数据。如果新的数据大于原来的数据,溢出的内容会写入到溢出的 block 里;但是,为了记录溢出的指针,旧的数据会产生数据迁移。(如果数据溢出频繁,应选择 3 的方式)
1 先删除旧的数据,然后写入新的数据,但会额外记录一个溢出块的指针(即使此时数据尚未溢出,也会记录一个空的指针)
3 在 1 的基础上覆盖写入数据。不同于 2 的是,此时不会涉及到旧数据的迁移,因为,在 1 的基础上已经分配了溢出指针的空间

read

读取一个图片文档

local id = 1;
local state = photosFile:read(id);
if (state == 1) then; -- 判断是否存在数据
    out:putBytes(buffer); -- 返回图片内容
end;

获取文档的总大小

local state = photosFile:read(2, 0, 1024);
if (state == 1) then;
    out:putInt(buffer.sizeTotal); -- 文档的总大小可以通过 buffer.sizeTotal 获取到
    out:putInt(buffer.length); -- 本次调用 read 读取的真正长度,buffer.length <= sizeMaxRead
end;

判断该记录是否为空,或者是否已经删除

local state = photosFile:read(3, 0, 1); -- 最多仅读取 1 个字节
if (state == 0) then;
    -- 该记录为空
elseif (state == -7) then;
    -- 该记录已经删除
end;

read(id:long, offset:ulong = 0, sizeMaxRead:uint = 0):int

根据记录 id 读取数据,返回成功或失败

Parameter Default Description
id 0 文档 id(0 <= id < 2^32)
offset 0 文档内的起始偏移,从此位置开始读取数据
sizeMaxRead 0 如果不为 0 则最多读取 sizeMaxRead 的数据(因为文档的总大小可能并不大于 sizeMaxRead)
Return Description
1 成功
0 成功,但这是一个空记录,数据长度为 0
-7 该记录已经删除
-2 id 不合法,超出有效范围(0 <= id < 2^32)
-4 通过 open 打开的文件不存在

remove

删除一个图片

local id = vars[1]; -- 从传入的数组中取出需要删除的图片 id
local state = photosFile:remove(id);
out:putInt(state); -- 返回删除的状态

remove(id:long):int

删除记录

Return Description
1 成功
-7 该记录已经删除
-2 id 不合法,超出有效范围(0 <= id < 2^32)
-4 通过 open 打开的文件不存在

getTotalFile

获取 “app/photos” 里的总文档数量

local photosFile = LFS.DataFile.new("app/photos");
out:putInt(photosFile:getTotalFile()); -- 返回总文档数量

getTotalFile():uint

返回总文档数量(包含已经删除的)

getFileLength

获取 “app/photos” 里的有效文档数量

local photosFile = LFS.DataFile.new("app/photos");
out:putInt(photosFile:getFileLength()); -- 返回有效文档数量

getFileLength():uint

返回有效文档数量

getFileLengthDeleted

获取 “app/photos” 里的已经删除的文档数量

local photosFile = LFS.DataFile.new("app/photos");
out:putInt(photosFile:getFileLengthDeleted()); -- 返回已经删除的文档数量

getFileLengthDeleted():uint

返回已经删除的文档数量

indexOf

indexOf(bytes:Bytes, fromIndex:uint = 0, endIndex:uint = MAX, length:uint = MAX, offset:ulong = 0, strict:Boolean = false):long

从前向后搜索每个文档,返回匹配的文档 id,如果 id < 0 则没有找到匹配的文档。

Parameter Default Description
bytes nil 匹配的内容
fromIndex 0 搜索的开始位置(开始文档 id)。默认为第一个文档。
endIndex MAX 搜索的结束位置(结束文档 id)。默认为最后一个文档。
length MAX bytes 的范围:bytes[0 - length]
offset 0 文档中从 offset 位置开始匹配 bytes[0 - length]
strict false 是否严格检查 sizeTotal 和 length 相等。(只有 offset 为 0 时才有意义)

lastIndexOf

lastIndexOf(bytes:Bytes, fromIndex:uint = 0, endIndex:uint = MAX, length:uint = MAX, offset:ulong = 0, strict:Boolean = false):long

从后向前搜索每个文档,返回匹配的文档 id,如果 id < 0 则没有找到匹配的文档。

Parameter Default Description
bytes nil 匹配的内容
fromIndex MAX 搜索的开始位置(开始文档 id)。默认为最后一个文档。
endIndex 0 搜索的结束位置(结束文档 id)。默认为第一个文档。
length MAX bytes 的范围:bytes[0 - length]
offset 0 文档中从 offset 位置开始匹配 bytes[0 - length]
strict false 是否严格检查 sizeTotal 和 length 相等。(只有 offset 为 0 时才有意义)

close

关闭打开的文件

myFile:close();
myFile:open("app/photos"); -- 打开其他文件

close():void

关闭已经打开的文件,然后可以重新打开其他文件

clear

清空 DataFile 对象

myFile:clear(); -- 清空 DataFile 占用的资源
myFile = nil; -- 彻底释放 myFile 占用的所有资源

clear():void

清空 DataFile,这将关闭已经打开的文件并释放内存

UniqueFile Class

唯一文件(哈希文件):利用 IndexKey 生成的哈希来快速访问指向的文档

UniqueFile 的用途:

new constructor

new(path:String = null):UniqueFile

open

打开文件

local dictFile = LFS.UniqueFile.new();
dictFile:open("app/dict");

open(path:String):void

打开文件

write

创建一个字典,启用唯一约束,避免存储相同的词汇(线程安全)

local indexKey = LFS.IndexKey.new();
indexKey:setKey("running man");
local id = dictFile:write(indexKey, "奔跑吧兄弟");
local id2 = dictFile:write(indexKey, "跑男"); -- id2 == id,但是 “跑男” 并没有覆盖 “奔跑吧兄弟”
out:putLong(id); -- 返回文档 id

存储 key->value(这里将 flag 设置为 3

local indexKey = LFS.IndexKey.new();
indexKey:setKey("current video");
myFile:write(indexKey, "奔跑吧兄弟", -1, 0, 0, 3);
myFile:write(indexKey, "跑男来了", -1, 0, 0, 3); -- 覆盖前一个记录

上传图片,并设置"文件名",之后就可以通过文件名来获取图片

通过此方法,模拟"文件路径"的访问方式

local photoBytes = vars[2];
local indexKey = LFS.IndexKey.new();
indexKey:setKey("2020/0130/1720.jpg"); -- 以"文件名"为 key 来存储图片
local id = photosFile:write(indexKey, photoBytes);

write(indexKey:IndexKey, buffer:byte[], bufferLength:ulong = MAX, offset:ulong = 0, sizeBlockMin:uint = 0, flag:uint = 0):long

根据 IndexKey 写入数据,并返回真实的记录 id(0 <= id < 2^32),如果返回的 id < 0 则表示失败

Parameter Default Description
indexKey null 不能为空,参见 IndexKey
buffer null 不能为空。如果为空,此时将写入空的记录,如果原来该记录存在数据,将会被删除
bufferLength MAX 默认等于 buffer.length(0 <= bufferLength <= buffer.length)
offset 0 起始偏移(注意:这是 id 指向的记录的偏移,而不是 buffer 的偏移)
sizeBlockMin 0 如果当前需要写入的数据长度小于 sizeBlockMin,则用字节 0 补齐(相当于为将要写的 block 分配可用空间,如果此记录的数据长度频繁增长,将会有效提高写入效率。比如:倒排文件(InvertFile)就是一个非常典型的用例)
flag 0 操作标识,有效值为 0, 1, 2, 3

flag

Value Description
0 直接存储文档内容。如果已经存在该 key,将不会覆盖旧的文档内容 [唯一约束]
2 在 0 的基础上覆盖写入数据。如果新的数据大于原来的数据,溢出的内容会写入到溢出的 block 里;但是,为了记录溢出的指针,旧的数据会产生数据迁移。(如果数据溢出频繁,应选择 3 的方式) [忽略唯一约束]
1 在存储文档内容之前,先记录额外的溢出块的指针(即使此时数据尚未溢出,也会记录一个空的指针) [唯一约束]
3 在 1 的基础上覆盖写入数据。不同于 2 的是,此时不会涉及到旧数据的迁移,因为,在 1 的基础上已经分配了溢出指针的空间 [忽略唯一约束]

read

根据"文件名"获取图片

local indexKey = LFS.IndexKey.new();
indexKey:setKey("2020/0130/1720.jpg");
local state = photosFile:read(indexKey);
if (state == 1) then; -- 判断是否存在数据
    out:putBytes(buffer); -- 返回图片内容
end;

获取正在播放的视频(key->value)

local indexKey = LFS.IndexKey.new();
indexKey:setKey("current video");
local state = myFile:read(indexKey);
if (state == 1) then;
    out:putBytes(buffer); -- 返回正在播放的节目:"跑男来了"
end;

read(indexKey:IndexKey, offset:ulong = 0, sizeMaxRead:uint = 0):int

根据 IndexKey 读取数据,返回成功或失败

Parameter Default Description
indexKey null 不能为空,参见 IndexKey
offset 0 文档内的起始偏移,从此位置开始读取数据
sizeMaxRead 0 如果不为 0 则最多读取 sizeMaxRead 的数据(因为文档的总大小可能并不大于 sizeMaxRead)
Return Description
1 成功
0 成功,但这是一个空记录,数据长度为 0
-7 该记录已经删除
-4 通过 open 打开的文件不存在

remove

删除 key 和 value

local indexKey = LFS.IndexKey.new();
indexKey:setKey("current video");
local state = myFile:remove(indexKey);
out:putInt(state); -- 返回删除的状态

remove(indexKey:IndexKey):int

删除记录

Return Description
1 成功
-7 该记录已经删除
-4 通过 open 打开的文件不存在

hasIndex

hasIndex(indexKey:IndexKey):long

判断是否存在该 key,返回文档 id,如果 id > 0 则存在该 key。

类似 read,但不区分记录是否为空

removeIndex

删除 key,但不删除已经存储的 value(文档数据)

该 value 依然可以被访问

local shareFile = LFS.UniqueFile.new("app/share");
local rawFile = LFS.DataFile.new(shareFile);
local indexKey = LFS.IndexKey.new();
indexKey:setKey("music");
local id = shareFile:hasIndex(indexKey); -- 删除之前,先获得文档 id
shareFile:removeIndex(indexKey); -- 仅仅删除 key,但不删除数据
if (id >= 0) then;
    rawFile:read(id); -- 通过 id 依然可以访问存储的文档
end;

重新给一个已经删除的 key 进行赋值

但,这将不会覆盖原来尚未删除的文档

而是,会重新将一个新的文档与该 key 绑定

local id = shareFile:hasIndex(indexKey);
shareFile:removeIndex(indexKey);
local id2 = shareFile:write(indexKey, "Blank Space"); -- id != id2,两个文档都可以被访问

removeIndex(indexKey:IndexKey):int

仅仅移除 Indexkey 指定的 key,返回 1 为成功。但已经存储的 value(文档数据) 不会删除,如果需要同时删除 value,请使用 remove

getTotalFile

getTotalFile():uint

返回总文档数量(包含已经删除的)

DataFile:getTotalFile

getFileLength

getFileLength():uint

返回有效文档数量

DataFile:getFileLength

getFileLengthDeleted

getFileLengthDeleted():uint

返回已经删除的文档数量

DataFile:getFileLengthDeleted

close

close():void

关闭已经打开的文件,然后可以重新打开其他文件

clear

clear():void

清空 UniqueFile,这将关闭已经打开的文件并释放内存

InvertFile class

由于倒排可能比较绕,所以展示一个完整的示例

在使用之前,先做一些准备工作(构建倒排索引)

1.存储新抓取的网页数据到网页集合中(获得 webId

local webRawFile = LFS.DataFile.new("app/web");
webRawFile:setOne(true); -- 由于 webId 不能为 0,所以设置为从 1 开始
local webId = webRawFile:write(-1, vars[2]); -- 存储新抓取的网页数据,并获得该 id

2.分析出网页中包含的词汇,并建立分词索引(添加新的词汇,并获得 wordId

local word = "爸爸去哪儿";
local indexKey = LFS.IndexKey.new();
indexKey:setKey(word);
local wordUniqueFile = LFS.UniqueFile.new("app/word"); -- 打开分词文件
local wordId = wordUniqueFile:write(indexKey, word); -- 将新的词汇加入索引(由于唯一约束,所以不会出现重复记录)

3.打开倒排文件,wordId->webId 录入倒排文件中

local sizeBlockMin = 1024 * 1024;
local word2web_InvertFile = LFS.InvertFile.new("app/word2web", sizeBlockMin, sizeBlockMin); -- 打开倒排文件
word2web_InvertFile:put(wordId, webId); -- 完成 wordId->webId 的倒排关系

到此为止,准备工作完成,倒排索引已经构建完成

搜索的过程:

1.先根据输入的词汇获得 wordId

local wordUniqueFile = LFS.UniqueFile.new("app/word"); -- 打开分词文件
local indexKey = LFS.IndexKey.new();
indexKey:setKey("爸爸去哪儿");
local wordId = wordUniqueFile:hasIndex(indexKey); -- 获得分词的 id

2.获得包含该分词的所有记录(从倒排中读取该集合中的所有 webId

local sizeMaxRead = 1024;
local state = word2web_InvertFile:read(wordId, 0, sizeMaxRead); -- 最多读取 4 的倍数长度字节
if (state == 1) then;
    local offset = buffer.length;
    local length = buffer:readUInt(); -- 读取有效记录数量
    local lengthDeleted = buffer:readUInt(); -- 读取已经移除的记录数
    local total = length + lengthDeleted; -- 计算总记录数量
    local id;
    while (total > 0) do;
        total = total - 1;
        if (buffer.bytesAvailable > 0) then; -- 如果 buffer 中还有有效字节
            id = buffer:readUInt();
            if (id ~= 0) then;
                out:putInt(id); -- 返回不为 0 的 id 记录
            end;
        else if (total > 0) then;
            word2web_InvertFile:read(wordId, offset, math.min(sizeMaxRead, total * 4)); -- 从 offset 位置开始分片读取
            offset = offset + buffer.length;
        end;
    end;
end;

搜索过程结束

倒排文件:用来存储指向一个 [相同属性] 的所有记录 ID

比如:为搜索引擎构建倒排索引

InvertFile 通过非常简单的方法来使这种操作变得非常简单

new constructor

new(path:String = null, sizeBlockMin:uint = 0, sizeBlockMinFirst:uint = 0):InvertFile

参数同 open

open

打开倒排文件

local sizeBlockMin = 1024 * 1024;
local word2web_InvertFile = LFS.InvertFile.new(); -- 分词指向网页的倒排表
webInvertFile:open("app/word2web", sizeBlockMin, sizeBlockMin);

open(path:String, sizeBlockMin:uint = 0, sizeBlockMinFirst:uint = 0):void

打开文件,请确保 sizeBlockMin, sizeBlockMinFirst 的值是有效的

Parameter Default Description
path null 文件路径
sizeBlockMin 0 每次需要分配的最小块大小,4 的倍数(因为倒排文件里的记录 id 是不断增长的,所以预先分配合适的空间,当此空间写满之后,会继续分配另一个块空间)
sizeBlockMinFirst 0 第一次需要分配的空间(第一次会额外分配 8 字节来记录有效数量和删除的数量,所以可以选择使用 sizeBlockMinFirst = sizeBlockMin + 8,也可以和 sizeBlockMin 相等)。另一种方案是:如果可以确定该倒排记录会在初期增长迅速,但达到一定程度时将不会频繁增长,那么这种情况可以将 sizeBlockMinFirst 设置为比 sizeBlockMin 大得多的值。

put

put(key:uint, id:uint, sizeBlockMin:uint = null, sizeBlockMinFirst:uint = null):int

添加 id 到 key 指向的倒排记录中,返回 >= 1 为成功。

参见 example 中的构建倒排索引过程。

Parameter Default Description
key 0 [相同属性]的文档 id。一般情况下为通过 UniqueFile 生成的 id(即先将单词通过 UniqueFile 生成唯一索引,获得返回的 id 即为 key。所以 InvertFile 通常和 UniqueFile 一起使用)
id 0 id 不能为 0。id 为另一个文件中的文档 id(比如将抓取的网页记录到一个 DataFile 中,并获得返回的 id)。
sizeBlockMin null 若不传此参数将使用 open 时的数值
sizeBlockMinFirst null 若不传此参数将使用 open 时的数值

has

has(key:uint, id:uint):long

判断 key 的集合中是否包含该 id,返回 id > 0 为成功。

remove

remove(key:uint, id:uint):int

从 key 的集合中移除该 id,返回 1 为成功

read

实际应用中,由于数组可能非常大,那么分片读取来提高效率

local sizeMaxRead = 1024;
local state = word2web_InvertFile:read(wordId, 0, sizeMaxRead); -- 最多读取 4 的倍数长度字节
if (state == 1) then;
    local offset = buffer.length;
    local length = buffer:readUInt(); -- 读取有效记录数量
    local lengthDeleted = buffer:readUInt(); -- 读取已经移除的记录数
    local total = length + lengthDeleted; -- 计算总记录数量
    local id;
    while (total > 0) do;
        total = total - 1;
        if (buffer.bytesAvailable > 0) then; -- 如果 buffer 中还有有效字节
            id = buffer:readUInt();
            if (id ~= 0) then;
                out:putInt(id); -- 返回不为 0 的 id 记录
            end;
        else;
            word2web_InvertFile:read(wordId, offset, math.min(sizeMaxRead, total * 4)); -- 从 offset 位置开始分片读取
            offset = offset + buffer.length;
        end;
    end;
end;

read(key:long, offset:ulong = 0, sizeMaxRead:uint = 0):int

DataFile:read

读取 key 的数组集合

InvertFile 中的数据格式为 uint 数组:[ length, lengthDeleted, id1, id2, id3, ... ]

取出数组中有效 id 的步骤为:

  1. 首先通过 total = length + lengthDeleted 计算出总的记录数量。(计算 total 非常重要的,因为 ... 中可能含有值为 0 的 id,这就是为什么 id 需要从 1 开始的原因。)
  2. 循环遍历数组的每一项 id(从第 3 个开始),判断该 id > 0,将 total 减 1。
  3. 重复 2 的步骤,直到 total 等于 0。

close

close():void

关闭已经打开的文件,然后可以重新打开其他文件

clear

clear():void

清空 InvertFile,这将关闭已经打开的文件并释放内存

IndexKey Class

索引 key:将字符串或字节数组转换成可被索引的哈希

new constructor

new():IndexKey

setKey

setKey(key:Bytes, size:uint = MAX):IndexKey

将 key 进行哈希,该操作会获得两个哈希值,参见下面的方法重载。

Parameter Default Description
key null 参见 key 的类型
size MAX 该 key 中从 0 开始的字节长度(默认为 key 的长度)

key 的类型

Type Description
String 普通字符串
Bytes 客户端传入的原始字节
ByteArray 字节数组(从该 position 向后的字节)

setKey(hashIndex:ulong, hash2:ulong):IndexKey

方法重载:通过此方法,用户可以设计自己的哈希方法。

Parameter Default Description
hashIndex 0 通过 index = hashIndex % length 来计算出索引位置
hash2 0 当 index 出现冲突时,用来进行区分的第二个哈希(注:hashIndex 不能和 hash2 相同)

setLength

setLength(length:uint):IndexKey

设置哈希表的长度。length 参与 setKey 的计算,所以需要在 setKey 之前设置。(可以适当设置一个较小的值)

Parameter Default Description
length 0 当 length 为 0 时,length = 5592405(即刚好占用一个 64M 的文件:2^26 / 12 = 5592405)

clear

clear():void

清空 IndexKey

ByteArray Class

字节数组:提供对原始字节的高级读写

new constructor

new():ByteArray

bytesAvailable property

bytesAvailable:uint [read-only]

可从字节数组的当前位置到数组末尾读取的数据的字节数。

每次访问 ByteArray 对象时,将 bytesAvailable 属性与读取方法结合使用,以确保读取有效的数据。

endian property

endian:int

更改或读取数据的字节顺序;BIG_ENDIAN: 1 或 LITTLE_ENDIAN: 0。默认值为 BIG_ENDIAN。

length property

length:uint

ByteArray 对象的长度(以字节为单位)。

如果将长度设置为大于当前长度的值,则用零填充字节数组的右侧。

如果将长度设置为小于当前长度的值,将会截断该字节数组。

position property

position:uint

设置或返回 ByteArray 中的当前位置。下一次调用读取方法时将在此位置开始读取,或者下一次调用写入方法时将在此位置开始写入。

writeBytes

writeBytes(bytes:Bytes, offset:uint = 0, length:uint = 0):void

将字节数组 bytes(起始偏移量为 offset)中包含 length(默认为 bytes 的长度)个字节的字节序列写入 ByteArray。

bytes 的类型

Type Description
String 普通字符串
Bytes 客户端传入的原始字节
ByteArray 字节数组(从该 position 向后的字节)

writeBoolean

writeBoolean(value:Boolean):void

writeByte

writeByte(value:byte):void

writeShort

writeShort(value:short):void

writeInt

writeInt(value:int):void

writeLong

writeLong(value:long):void

writeFloat

writeFloat(value:float):void

writeDouble

writeDouble(value:double):void

readBytes

readBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void

在 bytes 中 offset 指定的位置开始,写入 length(默认为:bytesAvailable)长度的字节。

readBytes(length:uint = 0):String

方法重载:读取 length(默认为:bytesAvailable)指定长度的字节,作为字符串返回。

readBoolean

readBoolean():Boolean

readByte

readByte():byte

readUByte

readUByte():ubyte

readShort

readShort():short

readUShort

readUShort():ushort

readInt

readInt():int

readUInt

readUInt():uint

readLong

readLong():long

readFloat

readFloat():float

readDouble

readDouble():double

clear

clear():void

清空 ByteArray

lua