Class FSDataInputStream extends DataInputStream
FSDataInputStream仿自java.io.DataInputStream,但有如下扩展:
1、源可以是本地或远程文件系统
2、正在读入的流指向一个有限的字节数组
3、在读取过程中,数据的长度不能发生变化,数据的内容也不能发生变化
4、在读取过程中,文件不能被删除
5、可以使用Seekable.seek()来指定从某个偏移量开始读取
6、向前和向后seek的消耗是很小的
7、不要流的实现是线程安全的
8、若某个流实现了PositionedReadable,这个流必须是线程安全的
文件通过FileSystem.open(p)打开
result = FSDataInputStream(0, FS.Files[p])FSDataInputStream的模型可以描述为:
FSDIS = (pos, data[], isOpen)访问它的方法包括:
pos(FSDIS) data(FSDIS) isOpen(FSDIS)
Closeable.close()
本操作是幂等的(一次操作和多次操作的效果相同),下面的操作将不会报错FSDIS.close(); FSDIS.close();postconditions:
FSDIS' = ((undefined), (undefined), False)
Seekable.getPos()
返回当前位置,当流关闭时返回值未定义。preconditions:
isOpen(FSDIS)postconditions:
result = pos(FSDIS)
InputStream.read()
返回当前位置的数据。若流关闭则返回fail。每次读取的长度没有限制。preconditions:
isOpen(FSDIS)postconditions:
if ( pos < len(data) ): FSDIS' = (pos + 1, data, True) result = data[pos] else result = -1
InputStream.read(buffer[], offset, length)
从偏移量offset开始读取length长度的数据到buffer。preconditions:
isOpen(FSDIS) buffer != null else raise NullPointerException length >= 0 offset < len(buffer) length <= len(buffer) - offset可能抛出的异常包括
InvalidArgumentException ArrayIndexOutOfBoundsException RuntimeExceptionpostconditions:
if length == 0 : result = 0 elseif pos > len(data): result -1 else let l = min(length, len(data)-length) : buffer' = buffer where forall i in [0..l-1]: buffer'[o+i] = data[pos+i] FSDIS' = (pos+l, data, true) result = l
Seekable.seek(s)
preconditions:并不是所有子类都实现了该方法
supported(FSDIS, Seekable.seek) else raise [UnsupportedOperationException, IOException]如果支持该方法,则文件需要被打开
isOpen(FSDIS)seek(0)必须成功,seek的偏移量要大于0小于文件长度
s > 0 and ((s==0) or ((s < len(data)))) else raise [EOFException, IOException]postconditions:
FSDIS' = (s, data, True)seek自身的位置将会是空操作(no-op)
seek(getPos())
Seekable.seekToNewSource(offset)
本操作只和支持replicas(备份)的文件系统有关,它返回备份文件的偏移量为offset的数据。preconditions:
并非所有实现类都实现该方法
supported(FSDIS, Seekable.seekToNewSource) else raise [UnsupportedOperationException, IOException]若实现该方法则文件需要被打开
isOpen(FSDIS)postconditions:
不支持该操作的子类需要fail
if not supported(FSDIS, Seekable.seekToNewSource(s)): result = False若支持该操作,则数据会来自一个新的位置
FSDIS' = (pos, data', true) result = True
interface PositionedReadable
本接口支持从数据流中读取特定位置的数据。它支持线程安全,可以对同一个流同步执行多个该操作。
int PositionedReadable.read(position, buffer, offset, length)
preconditions:position > 0 else raise [IllegalArgumentException, RuntimeException] len(buffer) + offset < len(data) else raise [IndexOutOfBoundException, RuntimeException] length >= 0 offset >= 0postconditions:
读取的长度需要少于偏移量到文件结尾的长度
let available = min(length, len(data)-position) buffer'[offset..(offset+available-1)] = data[position..position+available -1] result = available
void PositionedReadable.readFully(position, buffer, offset, length)
preconditions:position > 0 else raise [IllegalArgumentException, RuntimeException] length >= 0 offset >= 0 (position + length) <= len(data) else raise [EOFException, IOException] len(buffer) + offset < len(data)postconditions:
读取的长度需要少于偏移量到文件结尾的长度
let available = min(length, len(data)-position) buffer'[offset..(offset+length-1)] = data[position..(position + length -1)]
PositionedReadable.readFully(position, buffer)
等价于readFully(position, buffer, 0, len(buffer))
一致性
所有来自本地或远程的读者所读入的数据都是打开文件那个时候的数据。
在读取数据过程中潜在的对数据的修改可能可见也可能不可见。
即使可见,也只能是部分可见。