在
IO
流定义中使用装饰模式
Java.io
包中大量的使用了设计模式中的装饰模式
decorator
和适配器模式
adapter
,使
IO
库具有很强的对称性和可扩展性,对称性表现在I/O
的对称和
byte/char
流的对称上。
抽象角色
public abstract class InputStream implements Closeable {public abstract int read () throws IOException ;}
这里节点流就是这个抽象角色的具体实现,例如
FileInputStream
装饰
(
抽象
)
角色用于通过继承定义过滤流
public class FilterInputStream extends InputStream {protected volatile InputStream in ;protected FilterInputStream ( InputStream in ){this . in = in ;}public int read () throws IOException {return in . read ();}}
装饰的具体角色真正添加功能,例如BufferedInputStream就是给节点流上添加缓存
public class BufferedInputStream extends FilterInputStream {public BufferedInputStream ( InputStream in ){this ( in , DEFAULT_BUFFER_SIZE );}public synchronized int read () throws IOException {if ( pos >= count ) ...
File
类
类
File
提供了一种与机器无关的方式来描述一个文件对象的属性
对于目录,
Java
把它简单的处理为一种特殊的文件,即文件名的列表
java.io.File
用于封装和平台无关的文件夹和文件夹对象,例如获取一个文件的字节数。这个写法是
针对
windows
平台的,如果使用
mac
或者
linux
平台,则需要使用
通过类
File
中提供的方法,可以得到文件或者目录的描述信息,包括名称、所在路径、可读性等,
还可以生成新的文件、目录、改变文件名、删除文件、列出一个目录中所有的文件或者与某个模式
匹配的文件等
常见的构造方法
File(String pathName)
以
path
为路径创建
File
对象,如果
pathname
是相对路劲,则默认的当前路
径在系统属性
user.dir
中存储
File(String parent,String child)
这里文件对象的路径为相对于
parent
路径的
child
路径
静态属性
Separator
存储当前系统的路径分隔符
注意:
\
在字符串中为转义字符,如果需要使用
\
则必须写成
\\
。一般推荐使用
/
File f1 = new File ( "c:\\windows\\setupact.log" );File f2 = new File ( "c:/windows/setupact.log" ); // 这里的 / 等价于上面的 \\File f3 = newFile ( "c:" + File . separator + "windows" + File . separator + "setupact.log" );System . out . println ( File . pathSeparator ); // 路径分隔符;如果写多个路径使用 ; 分割System . out . println ( File . separator ); // 目录的分隔符 \
访问文件名的方法
getName():String
获取文件名称
getPath():String
获取路径,如果构建
File
时使用的是相对路径,则这里返回的就是相对路径;如果
创建时参数为绝对路径,则返回绝对路径
getAbsolutePath():String
获取绝对路径
getParent():String
获取当前文件对象的上级
File
对象,如果构建文件对象时使用的是相对路径,则
这里返回为
null
文件检测相关方法
canWrite():boolean
是否可写
canRead():boolean
是否可读
首先
exists()
存在性判断,存在时再进行是否文件或者文件夹的判断
isFile():boolean
是否是文件,因为
File
对象可以封装文件和文件夹
isDirectory():boolean
是否为文件夹
isAbsolute():boolean
是否为绝对路径
lastModified():long
文件的最后修改时间
常见操作
createNewFile():boolean
创建一个新文件
这个方法中有个受检型异常需要进行处理,处理方法:
try/catch
结构或者在方法上
throws
抛出异常
如果文件不存在则返回
true
,表示创建成功;如果文件已经存在则返回
false
,表示创建失败
File ff = new File ( "abc.txt" );if ( ! ff . exists ())ff . createNewFile ();System . out . println ( ff . getAbsolutePath ());
static createTempFile(String prefix, string suffix):File
这个临时文件名称会有随机内容
临时文件的默认存放位置为操作系统默认的临时文件位置
c:\Users\Administrator\AppData\Local\Temp\
//C:\Users\Administrator\AppData\Local\Temp\abc7595623142286422875.bak//C:\Users\Administrator\AppData\Local\Temp\abc6103677978020067241.bakFile ff = File . createTempFile ( "abc" , ".bak" ); // 其中 abc 是文件的前缀内容, .bak 是文件的后缀,其中包含一段随机内容System . out . println ( ff . getAbsolutePath ());
exists():boolean
文件或者文件夹是否存在
length():long
获取文件大小,单位为字节,如果是文件夹则返回值没有指定
File ff = new File ( "c:\\test/aa.txt" );if ( ff . exists () && ff . isFile ())System . out . println ( ff . length ());
renameTo(File):boolean
修改名称,可以修改文件名和文件夹名称
delete():boolean
删除文件。也可以删除文件夹,要求文件夹为空,不能有文件和子文件夹
注意:因为具体的文件或者文件夹的删除操作是由操作系统负责实现的,所以
Java
不能保证一定能
够删除成功
!
deleteOnExit():void
退出系统时自动删除
目录操作方法
mkdir():boolean
只能创建一层文件夹,如果创建
d:/a1/a2/a3
时,当父文件夹
d:/a1/a2
不存在时则
创建失败
mkdirs():boolean
自动创建多级文件夹
list():String[]
获取当前文件夹的所有子文件信息
listFiles():File[]
获取当前文件夹的所有子文件信息,子文件为
File
对象
File f = new File ( "d:/abc" );System . out . println ( f . exists ());File [] fs = f . listFiles ();// 即使 abc 文件夹下为空时则返回的是一个长度为 0 的数组,而不是 null ;只有无权访问时才有返回 null的可能for ( File temp : fs )System . out . println ( temp );
static listRoots():File[]
列出系统的所有的根路径
文件过滤器
FilenameFilter
带参数的
listFiles
方法支持对于子文件进行过滤,只获取需要满足条件的文件对象
FilenameFilter
接口中包含一个
accept(File dir,String name)
方法,该方法用于对指定
File
的所有子目录或者文件进行迭代,如果方法返回true
则
list
方法会获取该目录或者文件
匿名内部类的写法
:
推荐写法
语法糖
Lambda
表达式
1、函数式接口
@FunctionInterfacepublic interface FilenameFilter {
2
、具体的表达式写法
File [] fs = f . listFiles (( dir , name ) -> {return name != null && name . endsWith ( ".ini" );});
简化写法
String [] nameList = file . list (( dir , name ) -> name . endWith ( “ . java” ) || newFile ( name ). isDirectory ()) ;
Path
和
Paths
以及
Files
Path
接口代表一个平台无关的平台路径
Files
提供工具方法操作文件
Paths
提供创建
Path
的静态工厂方法
Path
相关方法
Path path = Paths . get ( "c:" , "ddd" , "eee" ); // 对应 c:\dddd\eee 路径Path path = Paths . get ( "." ); // 获取当前路径对象path . toAbsolutePath () // 获取 path 对应的绝对路径path . toAbsolutePath (). getRoot () // 获取 path 对应的根路径
Files
工具方法
复制文件
Files.copy(Paths.get("T1.java"), new FileOutputStream("a.txt"))
一次性读取文件的所有行
List<String> lines=Files.readAllLines()
字节流
Java
把不同类型的输入、输出抽象为流
stream
,分为输入流和输出流,用统一的接口来表示
Java
开发环境中提供了包
java.io
,其中包括一系列的类来实现输入/输出处理
InputStream
是所有字节输入流的祖先,而
OutputStream
是所有字节输出流的祖先
public abstract class InputStream implements Closeablepublic abstract class OutputStream implements Closeable , Flushable
InputStream
InputStream
类是一个抽象类,方法包括:
int read()
int read(byte[])
int read(byte[],int,int)
void close()
关闭流
int available()
报告流中直接可读的字节数
skip(long)
跳过流中指定的字节
练习
1
:使用字节流读取一个文本文件,并显示其内容
OutputStream
OutputStream
也是一个抽象类。它的主要方法包括:
void write(int)
void write(byte[])
void write(byte[],int,int)
其中第一个方法的
int
型的参数对应要写入的字节,后两个方法的参数与
InputStream
类似。
void close()
关闭输出流
void flush()
强行将写入缓冲区中剩余的数据写入
File file = new File ( "d:\\FileTest.java" );if ( file . exists ()) {try ( InputStream is = new FileInputStream ( file );) {byte [] buffer = new byte [ 8192 ];int len = is . read ( buffer );while ( len > 0 ) {System . out . write ( buffer , 0 , len );len = is . read ( buffer );}} catch ( Exception e ) {e . printStackTrace ();}}
InputSream
和
OutputStream
中定义了
read()
和
write()
方法,它们被派生流类重载。字节流是字节序
列,它与外部设备中的字节存在着一一对应的关系,不存在字符的转换,被读写字节的个数与外部设备中的字节个数是相同的