JavaNIO:编写文件头-使用SeekableByteChannel

JavaNIO:编写文件头-使用SeekableByteChannel,java,nio,Java,Nio,我正在使用ByteBuffer及其操作(如putInteger(),putDouble()等)手动将数据对象序列化到文件中 我想写出的字段之一是字符串。举个例子,假设它包含一种货币。每种货币都有三个字母的ISO货币代码,例如,英镑对应英镑 假设我序列化的每个对象都有一个double和一个currency;您可以考虑序列化的数据看起来像: 100.00|GBP 200.00|USD 300.00|EUR 100 GBP USD EUR ~~~ ~~~ 100.00|1 200.00|2 300.

我正在使用ByteBuffer及其操作(如
putInteger()
putDouble()
等)手动将数据对象序列化到文件中

我想写出的字段之一是字符串。举个例子,假设它包含一种货币。每种货币都有三个字母的ISO货币代码,例如,英镑对应英镑

假设我序列化的每个对象都有一个double和一个currency;您可以考虑序列化的数据看起来像:

100.00|GBP
200.00|USD
300.00|EUR
100
GBP
USD
EUR
~~~
~~~
100.00|1
200.00|2
300.00|3
显然,在现实中,我并不是在划分数据(字段之间的管道,也不是换行符),它是以二进制形式存储的——只是使用上面的例子

使用每个条目对货币进行编码有点低效,因为我一直在存储相同的三个字符。相反,我希望有一个标题-它存储货币的映射。该文件看起来像:

100.00|GBP
200.00|USD
300.00|EUR
100
GBP
USD
EUR
~~~
~~~
100.00|1
200.00|2
300.00|3
文件中的前2个字节是短的,用十进制值100填充。这告诉我文件中有100个货币空格。接下来是3字节块,它们是按顺序排列的货币(仅限ASCII字符)

当我读回文件时,我所要做的就是用货币代码构建一个100元素的数组,这样我就可以廉价/高效地查找每行的相关货币

读回文件似乎很简单。但我很想听听关于写出数据的想法

我不知道所有的货币,我实际上支持任何三个字符的代码-即使它是无效的。因此,我必须建立一个表,动态地将货币转换为指数

我打算使用seekablybytechnel对我的文件进行寻址,并在每次找到以前未编制索引的新货币时返回到标题

这在文件中移动会产生明显的I/O开销。但是,我希望在编写的前几个数据对象中看到所有不同的货币。因此,它可能只在执行的前几秒钟进行搜索,然后在数小时内不必执行额外的搜索

另一种方法是等待数据流完成,然后写入一次头。但是,如果我的应用程序崩溃,并且我没有写出头,文件中的数据将无法恢复到其原始内容


寻找似乎是正确的做法,但我以前从未尝试过——我希望能提前听到恐怖故事,您的方法的问题在于您不想限制货币代码的数量,这意味着您不知道必须为标题保留多少空间。如果不经常执行,在普通本地文件中查找可能会很便宜,但将整个文件内容移动以为标头保留更多空间是大的

另一个问题是如何定义效率。如果不限制货币代码的数量,则必须注意单个字节不足以用于索引的情况,因此需要更复杂的动态多字节编码(可能是更复杂的解析)或固定的多字节编码(最终采用与货币代码本身相同的字节数)

因此,如果对您来说,典型情况下的空间效率比解码效率更重要,那么您可以利用这样一个事实,即这些代码都仅由ASCII字符组成。因此,您可以将每个货币代码编码为三个字节,如果接受一个填充字节,则可以使用单个
putin
/
getInt
来存储/检索货币代码,而无需进行任何标题查找


我不相信进一步优化这些代码会显著提高您的存储能力。该表不仅包含货币代码。其他数据很可能会占用更多空间。

您考虑过使用嵌入式数据库吗?否则,对我来说,你就像是在重新发明一个有事务的数据库一样。@Robert我存储的数据需要建立索引,以便快速访问。如果我的数据是固定宽度的,我可以非常快地找到第n个元素,方法是找到数据有效负载的开始,然后以字节为单位查找n*对象大小。我将存储数千万条记录,输入速率非常“突发”——在一天中的某些时间,我每秒可以收到数十万条记录。我正在寻找一些非常快速的东西,我不一定需要一些具备SQL类嵌入式数据库所有特性的东西。像Derby/HSQLDB这样的产品太慢了。好吧,如果你想自己编写一个优化版本,使用两个文件,一个用于货币,一个用于数据,那么你不必考虑偏移量……我没有说我不想限制货币代码的数量:-)我愿意提前声明,可能是在配置中。在上面的例子中,我会为100种货币预留足够的空间。如果我尝试输入第101种货币,我会抛出一个异常。。。。因此,我永远不想改变文件的内容来为更大的标题让路。例如,货币代码,还有其他一些示例中的字符数会更长,比如10。我正在考虑假设编码的索引号(1,2,3…)是短的,而不是字节。这将为我的所有用例提供足够的索引。我强调您的语句
如果不经常执行,在普通本地文件中搜索可能会很便宜。鉴于我愿意做出的限制(根据上述评论),听起来你认为这是一个合理的方法?在结尾写一次标题没有问题;如果您有多达100个代码,并且希望将此策略扩展到其他值类型,那么每出现一次就编写一个可能太多了。它总是关于最大数量是多少。我会在最后只写一封信