今天学习了特殊RandomAccessFile和记录指针的特殊方法

特殊 RandomAccessFile
RandomAccessFile 不属于 IO 流,支持对文件的读取和写入随机访问
public class RandomAccessFile implements DataOutput, DataInput, Closeable
1.DataInput 接口中定义了基本数据类型的读操作 , 例如 readInt/readDouble
2.DataOutput 接口定义了基本数据类型的写操作 , 例如 writeInt/writeDouble
RandomAccessFile Java 输入 / 输出流体系中功能最丰富的文件内容访问类,既可以读取文件内容,也可以向文件输出数据。
RandomAccessFile 构造器
RandomAccessFile 类在创建对象时,除了指定文件本身,还需要指定一个 mode 参数指定
RandomAccessFile 的访问模式,该参数有如下四个值:
1.r 以只读方式打开指定文件。如果试图对该 RandomAccessFile 指定的文件执行写入方法则会抛出
IOException
2.rw 以读取、写入方式打开指定文件。如果该文件不存在,则尝试创建文件
3.rws 以读取、写入方式打开指定文件。相对于 rw 模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备,默认情形下(rw 模式下 ), 是使用 buffer , 只有 cache 满的或者使用
RandomAccessFile.close() 关闭流的时候儿才真正的写到文件
4.rwd与 rws 类似,只是仅对文件的内容同步更新到磁盘,而不修改文件的元数据
RandomAccessFile 写方法

 

RandomAccessFile 读方法

 

读取文件时如果到文件结尾是抛出异常 EOFException ,所以这里采用的是异常用于判断文件结束

 典型应用:多线程下载和断点续传

记录指针的特殊方法

与普通的输入 / 输出流不同的是 : RandomAccessFile 支持跳到文件任意位置读写数据,
RandomAccessFile 对象包含一个记录指针,用以标识当前读写处的位置,当程序创建一个新的
RandomAccessFile 对象时,该对象的文件记录指针对于文件头(也就是 0 处),当读写 n 个字节后,文件记录指针将会向后移动n 个字节。除此之外, RandomAccessFile 可以自由移动该记录指针
RandomAccessFile包含两个方法来操作文件记录指针:文件指针是按照字节数进行统计,取值范围为[0,file.length()]
long getFilePointer() :返回文件记录指针的当前位置
void seek(long pos) :将文件记录指针定位到 pos 位置
skipByte(int step); 相对当前位置跳过 step 个字节
如果文件中间的内容需要进行修改,注意新内容中的字串和原始文件内容的长度应该一致,否则可能会导致修改数据后面的内容无法正常读取
常见方法
void close() 关闭操作
int read(byte[] b) 将内容读取到一个 byte 数组之中
byte readByte() 读取一个字节
int readInt() 从文件中读取整型数据 … readDouble() 8 种简单类型
String readLine() 读取一行数据
void writeBytes(String s) 将一个字符串写入到文件之中,按字节的方式处理。 writeChars
void writeInt(int v) 将一个 int 型数据写入文件,长度为 4 位。 …writeDouble 8 种类型
void writeBytes(String s) 将一个字符串写入到文件之中,按字节的方式处理。 writeChars
void writeInt(int v) 将一个 int 型数据写入文件,长度为 4 位。 …writeDouble 8 种类型
 
NIO
JDK1.4 开始 Java 引入了一系列改进的输入 / 输出处理的新功能,统称为 NIO ,即新 IO ,新增了许多用于处理输入输出的类,新IO 采用内存映射文件的方式处理输入输出,新 IO 将文件或文件的一段区域映射到内存中,这样就可以像访问内存一样来访问文件,这种方式进行输入输出比传统的输入输出快的多
NIO 基础
Channel 通道和 Buffer 缓冲是 NIO 中的两个核心对象
1.Chanel 是对传统输入输出系统的模拟,通过 map 方法可以将一块数据映射到内存中
2.Buffer 本质是一个数组,发送到 Channel 中的所有对象都必须先放到 Buffer 中,而从 Channel 中读
取的数据必须先放到 Buffer
NIO 和多路复用的区别
IO 模型
同步阻塞 IO Blocking IO ):即传统的 IO 模型
同步非阻塞 IO Non-blocking IO ):默认创建的 socket 都是阻塞的,非阻塞 IO 要求 socket 被设置
NONBLOCK 。注意这里所说的 NIO 并非 Java NIO New IO )库
多路复用 IO IO Multiplexing ):即经典的 Reactor 设计模式,有时也称为异步阻塞 IO Java 中的
Selector Linux 中的 epoll 都是这种模型
异步 IO Asynchronous IO ):即经典的 Proactor 设计模式,也称为异步非阻塞 IO
java NIO就是采用多路复用IO模式
在多路复用 IO 模型中,会有一个线程( Java 中的 Selector )不断去轮询多个 socket 的状态,只有当
socket 真正有读写事件时,才真正调用实际的 IO 读写操作。因为在多路复用 IO 模型中,只需要使用一个线程就可以管理多个socket ,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket 读写事件进行时,才会使用 IO 资源,所以它大大减少了资源占用。
Buffer 的使用
Buffer 是一个抽象类,主要作用是用于装入数据,然后输出数据
1.最常见的子类 ByteBuffer 可以在底层字节数组上进行 get/set 操作
2.其它基本数据类型都有对应的 Buffer 类: CharBuffer ShortBuffer IntBuffer LongBuffer
FloatBuffer DoubleBuffer
静态方法 static XxxBuffer allocate(int capacity) 创建一个容量为 capacity XxxBuffer 对象
Buffer 中有 3 个重要概念:容量 capacity 、界限 limit 和位置 position
1.容量 capacity 表示该 Buffer 的最大数据容量,创建后则不能改变
2.界限 limit ,位于 limit 后的数据既不可被读,也不可被写
3.位置 position 用于指明下一个可以被读出的或者写入缓冲区的位置索引
标记 mark 位置
Buffer 类的常用方法
Channel 类的常用方法

 Channel可以直接将文件的部分或者全部直接映射成Buffer

注意:不能直接访问Channel中的数据,包括读取、写入都不行。Channel只能与Buffer进行交互

所有 Channel 不应该通过构造器来直接创建,而是通过传统的节点 InputStream OutputStream
getChannel 方法来返回对应的 Channel
常用的是 FileInputStream FileOutputStream getChannel() 返回的 FileChannel
Channel 中最常用的三个方法是 map() read() write()
异常: java.nio.charset.MalformedInputException 一般是编码转换时由于编码字符集错误导致的,可以修改Charset 中编码字符集名称解决。例如 GBK UTF-8
 
map() 方法将 Channel 对应的部分或全部数据映射成 ByteBuffer
selector
Java NIO 核心组件中的一个,用于检查一个或多个 NIO Channel 通道的状态是否处于可读、可写。如此可以实现单线程管理多个channels 也就是可以管理多个网络链接。
使用 Selector 的好处在于:使用更少的线程来就可以来处理通道了,相比使用多个线程,避免了线程上下文切换带来的开销
FileChannel 不能切换为非阻塞模式,更准确的来说是因为 FileChannel 没有继承SelectableChannel
多用于网络应用编程中
基本用法
1. Selector 的创建。通过调用 Selector.open() 方法创建一个 Selector 对象
        Selectorselector=Selector.open();
2. 注册 Channel Selector
channel.configureBlocking(false);
SelectionKeykey=channel.register(selector,Selectionkey.OP_READ);
Channel 必须是非阻塞的。
Chatset 字符集
所有文件在底层都是二进制文件,字符文件是系统将底层的二进制序列转换为字符,这里会涉及编码Encoder和解码 Decoder
将明文的字符序列转换为计算机理解的二进制序列称为编码
将二进制序列转换为明文字符串称为解码
Charset
availableCharsets() SortedMap<String,Charset> 获取当前 JDK 所支持的所有字符集
字符串别名
GBK 简体中文
ISO-8859-1 拉丁文
UTF-8 8 UCS 转换格式
Charsetc = Charset . forName ( "GBK" );
Java7 新增 StandardCharsets 类,其中包含了 ISO_8859_1 UTF_8 UTF-16 等类变量,这些类变量代表了最常见的字符集对应的Charset 对象
newDecoder():CharsetDecoder 获取该编码字符集对应的解码器
decode(ByteBuffer):CharBuffer 方法可以将字节序列 ByteBuffer 转换为 CharBuffer 字符序列
newEncoder():CharsetEncoder 获取该编码字符集对应的编码器
encode(CharBuffer):ByteBuffer 方法可以将字符序列 CharBuffer 转换为 ByteBuffer 字节序列
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值