(2018.03.02)
File
1.File类是java.io包下代表与平台无关的文件和目录;File能新建、删除、重命名文件和目录,File不能访问文件本身。需要使用输入/输出流来访问文件内容本身。
2.File类可以使用文件路径字符串来创建File实例,可以是绝对路径或者相对路径(相对于项目工作路径)
3.File提供方法操作文件或目录(Java讲义P665)
(API: http://tool.oschina.net/apidocs/apidoc?api=jdk_7u4 )
a.访问文件名相关的方法
b.文件检测的相关方法
c.获取常规文件信息
d.文件操作相关方法
e.目录操作相关方法
4.File类的list(FilenameFilter filter)方法,FilenameFilter接口包含了一个 accept(File dir, String name)方法:对指定File所有的子目录或者文件进行迭代,如果方法返回true,则list()方法会列出该子目录或者文件;name指文件或目录名。
IO流
1.Java把不同的输入/输出源(键盘、文件、网路连接)抽象表述为"流",通过流的方式允许Java程序使 用相同的方式来访问不同的 输入/输出源。
2.流的分类:
a.流向(站在从程序运行所在内存的角度): 输入流、 输出流;
b.操作数据单元(自己):字节流(8字节)、字符流(16字节);
c.流的角色:节点流、处理流;
1.节点流:可以从/向一个特定的IO设备(磁盘、网络)读/写数据的流;
(所有节点流都是直接以物理IO节点作为构造器参数的)
2.处理流: 对一个已存在的流进行连接或封装,通过封装后的流来实现数据读/写功能。(装饰器设计模式)
(只要流的构造参数不是一个物理节点,而是已经存在的流,那么这种流一定是处理流)
(只要使用相同的处理流,程序就可以采用完全相同的输入/输出代码来访问不同的数据源、而实际访问的数据源,随处理流包装的节点流变化而变化。)
3.流的模型概念
输入流而言:把输入设备抽象成一个水管,水管里每个水滴依次排列,输入流使用隐式的记录指针来表示当前正准备从哪个"水滴"开始读取,每当读取一个或多个水滴后,记录指针自动向后移动;
输出流而言:同样把设备抽象成一个水管,只是水管里面没有任何水滴,隐式指针标识当前水滴即将放入的位置;
4.处理流功能:性能的提高(增加缓冲)、操作的便捷;
(2018.03.03)
5.程序里打开的文件IO资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显示关闭文件IO资源。
6.关闭IO输出流,除了可以保证流的物理资源被回收之外,还可以将缓冲区中的数据flush到物理节点(因为在执行close()方法之前,自动执行输出流的flush()方法)
7.输入/输出流体系(注:粗体代表节点流,必须与指点的物理节点关联;斜体是抽象基类,无法创建实例。)
分类
|
字节输入流
|
字节输出流
|
字符输入流
|
字符输出流
|
备注
|
抽象基类
|
InuputStream
|
OutputStream
|
Reader
|
Writer
|
|
访问文件
|
FileInputStream
|
FileOutputStream
|
FileReader
|
FileWriter
|
|
访问数组
|
ByteArrayInputStream
|
ByteArrayOutputStream
|
CharArrayReader
|
CharArrayWriter
|
|
访问管道
|
PipedInputStream
|
PipedOutputStream
|
PipedReader
|
PipedWriter
|
实现进程之间通信功能的
|
访问字符串
|
|
|
StringReader
|
StringWriter
|
|
缓冲流
|
BufferedInputStream
|
BufferedOutputStream
|
BufferedReader
|
BufferedWriter
|
增加了缓冲功能
|
转换流
|
|
|
InputStreamReader
|
OutputStramWriter
|
将字节流转换为字符流
|
对象流
|
ObjectInputStream
|
ObjectOutputStream
|
|
|
实现对象序列化
|
抽象基类
|
FilterInputStream
|
FilterOutputStream
|
FilterReader
|
FilterWriter
|
|
打印流
|
|
PrintStream
|
|
PrintWriter
|
|
推回输入流
|
PushbackInputStream
|
|
PushbackReader
|
|
|
特殊流
|
DataInputStream
|
DataOutputStram
|
|
|
|
8.一个使用规则:如果进行输入/输出的内容是文本内容,则应该考虑使用字符流;如果进行输入输出的内容是二进制内容,则应该考虑使用字节流。
9.重定向标准输入输出流
标准输入:System.in 键盘
标准输出: System.out 显示器
重定向:System.setErr(PrintStream err)/System.setIn(InputStream in)/System.setOut(PrintStream out)就是将输入源或输出的目的地重定向为设置的。
10.Java虚拟机读写其他进程的数据
Process p = Runtime.getRuntime().exec("javac");
p代表由该Java程序启动的子程序,有3个方法:getErrorStream()、getInputStream()、getOutputStream()
11.RandomAccessFile丰富的文件内容访问类,可以读取文件内容,也可以向文件输出数据。支持随机访问的方式,程序可以直接跳转到文件的任意地方来读写程序。
a.(使用场景:如果只需要访问文件部分内容,而不是把文件重头读到尾;向已存在的文件后面追加内容;只能读写文件不能读写其他IO节点)
b.记录指针,字节为单位,初始位置为0;
c.创建时指定访问模式mode,有"r","rw","rws","rwd"
d.向后最佳内容,先将指针移至最后,然后写入
e.不能向指定位置插入内容,会覆盖
f.向指定文件、指定位置插入内容,则先将插入点后的内容保存在临时文件中,然后插入内容后追加。
g.多线程断电的网络下载工具,用到此方法。(如FlashGet)
12.对象序列化
a.目标:将对象保存在磁盘中,允许在网络中传输该对象。
b.机制:把内存中的Java对象转换成平台无关的二进制流(字节序列),从而允许把这种二进制流持久的保存在磁盘上或通过网络将这种二进制流传输到另一个网络节点。其他程序一旦获得了这种二进制流,都可以将这种二进制流恢复成原来的Java对象。
c.序列化(Serialize):将一个Java对象写入到IO流中。
d.反序列化(Deserialize):从IO流中恢复该Java对象。
e.所有在网路上传输的对象都应该是可序列化的,应该实现Serializable/Externalizable
13.序列化和反序列化
a.序列化Example:
ObjectOutputStream oos = new ObjectOutputStream(new FileOutPutStream("Object.txt"));
oos.writeObject(per);
//可序列化类有多个父类时,父类要么有无参构造器, 要么也是可序列化的,否则抛出InvalidClassException
b.反序列化Example:
ObjectInputStream ois = new ObjectInutStream(new FileInputStream("Object.txt"));
Person per = (Person)ois.readObject();
//反序列化仅仅读取的是Java对象的数据而不是Java类,采用反序列化恢复Java对象时,必须提供该Java对象所属类的class文件,否则将引发ClassNotFoundException异常。
//反序列化无需通过构造器来初始化Java对象。
14.对象引用的序列化
a.某个类的的成员变量的类型是引用类型,则这个引用类型必须是可序列化的,否则拥有该类型成员的类也是不可序列化的;
b.当多个对象引用到同一个对象时,Java序列化机制不会序列化多个相同的对象。
15.Java序列化机制:采用了一种特殊的序列化算法
a.所有保存到磁盘中的对象都有一个序列化编号;
b.当程序视图序列化一个对象时,会先检查对象书否被序列化过只有该对象从未(在本次虚拟机中)被序列化过,系统才会将该对象转换成字节序列输出;
c.如果某个对象已经被序列化过,程序将只是直接输出一个序列化编号,而不是再次重新序列化该对象,即使后面该对象的实例变量值已被改变,该实例变量值也不会被输出。
(只有第一次调用writeObject()方法来输出对象时才会将对象转化为字节序列,并写入到ObjectOutputStream)
16.自定义序列化
a.采用transient关键字修饰实例变量,则Java序列化时无需理会该实例变量,反序列化时其为初始值;
b.实现Serializable接口的类可以通过重写writeObject(ObjectOutputStream out)方法和readObject(ObjectInputStream in)方法来自定义序列化方式,实现序列化加密等;
c.writeReplace()方法可以在序列化对象时将对象替换成其他对象,即系统在调用writeObject()和writeReplace()方法时优先调用writeReplace();
d.readResolve()方法实现保护性复制整个对象,该方法会紧跟着readObject()之后被调用,其返回值会代替原来被反序列化的对象,原来readObject()反序列化对象将会被立即丢弃。
17.实现Externalizable,强制要求程序员自定义序列化,即重写writeExternal()和readExterna()方法,实现该接口的类必须提供public的无参构造器。
18.反序列化Java对象时必须提供Java对象的class文件,随着项目的升级,系统的class文件也会升级,保证兼容性需设置
a.private static final int seralVersionUID的值,该变量的值用于表示该Java类的序列化版本。
b.不利于程序在不同的JVM之间移植,不同编译器对该类变量的计算策略可能不同。
19.新IO(NIO)
a.目的:用于进行输入、输出;
b.采用内存映射文件的方式来处理输入/输出,新IO将文件或文件的一段区域映射大内存中,这样就可以像访问内存一样来访问文件了。
20.新IO的核心对象:Buffer(缓冲)、Channel(通道)
Buffer:被理解成一个容器,本质是一个数组,发送到Channel中的所有对象都必须首先放到Buffer中,而从Channel中读取的数据也必须先放到Buffer中。
Channel:对传统输入、输出系统的模拟,在新IO中所有数据都需要通过通道传输,相对于传统的InputStream和OutputStream,Channel提供了map()方法,可以直接将"一块数据"映射到内存中。传统的输入输出面向流处理,新IO面向块处理。
21.Buffer
a.抽象类、常用子类:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer
b.三个重要的概念:容量(capacity)、界限(limit)和位置(position)。可选标记(mark)
0 <= mark <= positon <= limit <= capacity
c.常用方法:allocate()、put()、get()、flip()、clear(),后两个知识对limit和position进行操作,不影响容器内数据。
d.flip():将limit设置为posiion,position设置为0,为输出数据准备
e.clear():将position设置为0,limit设置为capacity,为读入数据做好准备
22.Channel
a.Channel表示到实体(如硬件设备、文件、网络套接字或可以执行一个或多个不停的I/O操作)的程序组件的开放的连接。
b.不通过传统的构造器来创建,通过传统的节点InputStream/OutputStream的getChannel()方法返回对应的Channel,不同节点获得的Channel不同
c.常用的Channel有datagramChannel、FileChannel、PipeSinkChannel、Pipe.SourceChannel、SelectableChannel、serverSocketChannel、SocketChannel
d.常用方法:map()、read()、write()。map()用法用于将Channel对应的部分或全部数据映射成ByteBuffer;write()和read()则向Buffer中读取或向Buffer中写入数据。
23.编码 解码
编码:把明文的字符序列转换成计算机理解的二进制序列;
解码:把二进制序列转换成普通人能看懂的明文字符串。
24.Java默认使用Unicode字符集,很多操作系统并不使用,当从系统中读取数据到Java程序中时,可能出现乱码。使用Charset来处理字节序列和字符序列之间的关系,Charset是不可变类。
a.通过Charset.availableCharsets()获取Java支持的全部字符集;
b.Charset cs = Charset.forName("GBK")获取Chaeset对象;
c.CharsetEncoder cnEncoder = cs.newEncoder(); CharsetDecoder cnDecoder = cs.newDecoder();获得解码器(CharsetEncoder)和编码器(CharsetDecoder);
d.调用cnEncoder.encode()方法得到字节序列,调用cnDecoder.decode()方法得到字符序列。
e.Charset本身也有encode()和decode()方法。
25.文件锁:有效的阻止多个进程并发修改同一个文件。
a.JDK1.4的NIO开始,java提供文件锁的支持
b.FileLock fileLock = FieChannel.lock()/tryLock(),获取FileLock对象,从而锁定文件(排它锁),由所带的参数决定。
c.共享锁:允许多个进程来读取文件,但阻止其他进程获取改文件的排它锁;排它锁:锁住文件的读写。
d.fileLock.release()释放文件锁。
e.文件锁是Java虚拟机所持有的,两个Java程序在同一个Java虚拟机运行,不能对同一个文件加锁;
f.关闭FileChannel时,会释放Java虚拟机在改文件上的所有锁,避免对同一个文件打开多个FileChannel。
26.Java 7 的NIO.2
a.提供了全面的文件IO和文件系统的访问支持。
b.基于异步Channel的IO。
27.Path、Paths、Files
Path:代表一个平台无关的平台路径;
Files:包含了大量静态的工具方法来操作文件:
Paths:包含两个返回Path的静态工厂方法。
28.其他
a.使用FileVisitor遍历文件和目录
b.使用WatchService监控文件变化
c.通过Jaca7的NIO.2在java.nio.file.atribute包下提供大量的工具类来访问文件属性。