20155335俞昆 《java程序设计》第八周总结
2016-2017-2 《Java程序设计》第X周学习总结
##认识NIO
在java中,输入与输出,基本上是以字节为单位进行的低层次处理,实际上多半是对字节数组中整个区块进行处理,对于dump()方法,必须处理byte[] ,必须指定写出的byte[]的起点和字节数。例如
Java..io套件中有一些装饰类,例如DataInputStream,dataOutputStream,BufferedReader与Bufferedwriter等,若只要对字节或字符串中感兴趣的数据区块进行标记,像是标记读取位置、数据有效位置,对于这些区块标记,提供了clear()、rewind()、flip()、compact()等高级操作,对于上面的dump()方法,若使用NIO的话,可以如下撰写:
现阶段可了解在程序示范中,只要确认将数据从Channel中读入Buffer(read()方法不返回-1),使用高级flip()方法标记Buffer中读入Buffer中读入的数据写到另一个Channel,最后使用clear()方法清除Buffer标记,在这个过程中,不用接触byte[]相关细节。
Channel架构与操作
NOI中Channel的相关接口与类,是位于java.nio.channle套件之中,Channel接口是AutoCloseable的子接口,因此都可以使用尝试关闭资源语法,channel接口上主要新增isopen()的方法。
ReadableByteChannel定义了read()方法,负责将ReadableByteChannel中的数据读取至ByteBuffer,writeableByteChannel定义了write()方法,负责将ByteBuffer的数据写到writeableByteChannel中,ScatteringByteChannel定义了read()方法,可以讲ScatteringByteChannel分配到ByteBuffer数组中,GatheringByteChannel定义的write()方法可以将ByteBuffer数组的数据写到GatheringByteChannel。
WriteableByteChannel的行为,ByteChannel的字接口SeekableByteChannel可以读取改变下一个要读取存储的位置。
Buffer的架构与操作
在NOI设计中,数据都在java。Nio.Buffer中的处理,Buffer是个抽象类,定义了clear()、flip()、reset()、rewind()等对数据区块的高级操作,这类操作返回类型都是Buffer,实际上返回this,因此在需要连续高级操作时,可以形成管线操作风格。
根据不同的数据处理类型需求,可以选择不同的·Buffer子类,他们都是抽象类,因此不 能直接实例化,然而Buffer的直接子类们都有一个allocate()的静态方法,让指定的Buffe容量,如果是ByteBuffer,容量是指内部操作时使用的byte[]长度,如果是FloatBuffer,容量是指Float[]长度,以此类推,Buffer容量大小可以使用capacity()方法取得,如果想使用Buffer内部的数组,可以使用array()的方法,如果有一个个数组想要转换为某个Buffer子类实例时,每个Buffer()子类实例都有warp()静态方法提供这个服务。
如果使用ByteBuffer,还有一个allocateDirect()方法,相对于allocate()方法配置的内存有JVM管理,allocateDirect()会利用操作系统的原生I/O操作,试着避免JVM的中介转接,理论上会比allocate()配置的内存更为有效,但是allocateDirect()的配置内存时会消耗较多系统资源,故建议只用在大型、存货长的ByteBuffer对象,并能观察除明显的功能差异的场合,通过isdirect()得知。
Buffer是个容器,填装的数据不会超过他的容量,实际读取或写入的数据界限索引值可以由limit()方法得知或限定。
Bufffer的操作可以先从clear(),flip(),与rewind()开始认识,当一个缓冲区刚被配置或调用clear方法后,limit()等于capacity(),position()会是0,。
以下是一个使用flip()完整的范例
Buffer上还有个mark()方法,可以在目前position上标记,存取buffer之后,若调用reset()方法,会将position设回被mark()标记的位置。Position与limit之间为剩余可存取的资料,可以使用remaining()方法得知还有多少长度,使用hasReamming()可以测试是否还有剩余可存取的数据。
NIO2的架构
应用程序开发者主要使用java.nio.flie与java.nio.file.attribute,包中必须操作的抽象类或接口,由文件系统提供者操作,应用程序无需担心底层如何实际存取文件系统,通常只有文件系统才需关心java.nio.file.spi包。
NIO2文件系统的中心是java.nio.file.spi.FileSystemProvider,本身为抽象类.,是文件系统提供者才能操作的类,作用是产生java.nio.file与java.nio.file.attribute中的各种抽象类或接口的操作对象。
对学习者而言,只要知道有FileSystemProvider的存在即可,我们可以通过java.nio.file包中FileSystem、paths、files、等类提供的静态方法,取得相关操作对象或进行各种文件系统的操作,这些静态方法内部会运用FileSystemProvider来取得所需的操作对象,完成操作。
要操作文档,先要指出文档路径。Path实例是在JVM中路径的代表对象,也是NIO2文件系统API操作的起点,NIO2文件系统API中有许多操作,都必须使用Path指定路径。
想要取得path实例,可以使用Paths.get方法,最基本的使用方式,就是使用字符串路径,可使用相对路径或绝对路径,例如:
Path workspace = Paths.get(“C:\\workspace”);
Path books = Paths.get(“Desktop\\books);
Path path = Path.get(args[0]);
Paths.get()的第二个参数开始接受不定长度的自变量,因此可以指定路径,之后的路径分段指定。例如以下指定用户目录下的Documents\Downloads:
Paths实例仅代表路径信息,该路径实际上对应的文档或文件夹不一定存在。Path提供一些方法取得路径的各种信息,例如:
路径元素以文件夹为单位,最上层索引为0。
Paths操作了Iterable接口,若要循序渐进取得Path中分段的路径信息,也可以使用增强式for循环语法或forBath()方法,例如:
Path.path = Path.get(System.getProperty(“users.home),””Documents”,”Documents”);
Path.forEach(out::println);
路径中有冗余信息,可以使用normorlize。
读取访问目录
如果想要取得文件系统根目录路径信息,可以使用FileSyatem的getRootDirectories()方法,这会返回Iterabe<String>对象,可用增强式for或循环或新增的forEach()方取得根目录的路径信息,例如:
也可以使用Files.newDirectoryStream()方法取得DirectoryStream接口操作对象,代表路径下的所有文档。
这个范例可以从命令行自变量指定目录路径,查询该目录下的文档:
尽量简单的总结一下本周学习内容
尽量不要抄书,浪费时间
看懂就过,看不懂,学习有心得的记一下
## [代码托管](码云学习项目链接)
http://git.oschina.net/tianmaxingkomg/xinjianxianmu
(statistics.sh脚本的运行结果截图)
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
参考:[软件工程软件的估计为什么这么难](http://www.cnblogs.com/xinz/archive/2011/04/05/2005978.html),[软件工程 估计方法](http://www.cnblogs.com/xinz/archive/2011/04/06/2007294.html)
- 计划学习时间:14小时
- 实际学习时间:16小时
- 改进情况:
(有空多看看[现代软件工程 课件
软件工程师能力自我评价表](http://www.cnblogs.com/xinz/p/3852177.html))
## 参考资料
- [Java学习笔记(第8版)](http://book.douban.com/subject/26371167/)
- [《Java学习笔记(第8版)》学习指导](http://www.cnblogs.com/rocedu/p/5182332.html)
- ...