Java流相关知识

流的概念
在Java程序中,对于数据的输入输出操作以流Stream方式进行,JavaSE提供各种各样的类用于使用相同的方法获取不同类型的数据,程序中通过标准的方法输入或者输出数据
流是处理输入/输出的一个洁净的方法,它不需要代码理解键盘和网络的不同。Java中流的实现是基于java.io包定义的类层次结构的

流的分类
从Java不同版本上来说,流可以分为BIO、NIO和AIO三大类。Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种Il0模型的封装。程序员在使用这些API的时候,不需要关心操作系统层面的知识,也不需要根据不同操作系统编写不同的代码。只需要使用ava的API就可以了。
BIO即同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成

假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。
​ NIO即同步非阻塞,一个线程不断的轮询每个输入输出的状态改变,如果有状态发生了改变,则进行下一步的操作

拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。
​ AIO即异步非阻塞I/O模型,无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。

对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了
​ 按流向分为输入流和输出流,可以从输入流读取数据但不能写,要从输入流读取数据,则必须有一个与这个流相关的字符源

​ 按传输单位分为字节流和字符流

Java具备平台无关性,这里的字节是指8位,字符是16位

字节流从InputStream/OutputStream派生出来,以字节为基本处理单位,一般用于操作二进制数据,字节次序是有意义的

字符流从Reader/Writer派生出来的,以16位的Unicode码表示字符为基本处理单位,一般用于操作字符数据

使用桥接流可以实现两个流之间的转换

​ 按功能还可以分为节点流和过滤流
​ 节点流:负责数据源和程序之间建立连接,结点流对特定的地方读写
​ 过滤流:用于给节点增加功能,过滤流使用结点流进行输入/输出并添加附加功能

过滤流的构造方式是以其他流位参数构造(这样的设计模式称为装饰模式)。Java的IO流使用装饰器模式,将IO流分成底层节点流和上层处理流。其中节点流用于和底层的物理存储节点直接关联。过滤流是连接在已存在的流之上,通过对数据的处理为程序提供更为强大的读写功能。
注意:IO流是一类很宝贵的资源,使用完后必须调用close()方法关闭流并释放资源。在关闭流时只用关闭最外层的流

字符流就是字节流读取文字字节数据后,不直接操作而是先查指定的编码表以获取对应的文字。简单的说:字符流=字节流+编码表

字符流的两个顶层父类:Reader和Writer
字节流的两个顶层父类: InputStream和OutputStream
输入输出靠reader和writer, inputstream和outputstream四个类和
子类支持·读入的内容有对象,字符,图像和声音等
File类
java.io.File用于封装和平台无关的文件夹和文件对象

例如获取一个文件的字节数

File ff=new File(“dd.txt”);
//1ength():1ong用于获取文件的字节数,如果文件不存在则返回01/一个汉字=2B
System.out.println(ff.length()+“B”);

这个写法是针对windows平台的,如果使用mac或者linux平台,则需要使用

常见的构造方法
·File(String pathName)以path为路径创建File对象,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储

new File(“dd.txt”);使用的就是相对路径,这个路径将从项目的根目录开始算起
使用的分隔符是/,不是\,因为\在java种表示转移字符,如果需要使用\,则必须写成\
new File(“d:/data/dd.txt”)使用绝对路径,这里从d:开始,当然是windows系统
String ss=system.getProperties().getProperty(“user.dir”);
System.out.println(ss);//D: \workspace\eclipse-2020\2022-01-04

File(String parent,String child)这里文件对象的路径为相对于parent路径的child路径,相当于parent+" /""+child

静态属性
Separator存储当前系统的路径分隔符
注意:\在字符串中为转义字符,如果需要使用\则必须写成\l。一般推荐使用/

访问文件的方式
getName():String获取文件名称
getPath():String获取路径,如果构建File时使用的是相对路径,则这里返回的就是相对路径;如果创建时参数为绝对路径,则返回绝对路径
getAbsolutePath():String获取绝对路径
getParent():String获取当前文件对象的上级File对象,如果构建文件对象时使用的是相对路径,则这里返回为null
文件检测相关方式
canWrite():boolean是否可写canRead():boolean是否可读
isFile():boolean是否是文件,因为File对象可以封装文件和文件夹
isDirectory():boolean是否为文件夹
isAbsolute():boolean是否为绝对路径lastModified():long文件的最后修改时间
常见操作
createNewFile():boolean创建一个新文件
这个方法中有个受检型异常,需要进行处理,处理方法: trylcatch结构或者在方法上throws抛出异常如果文件不存在则返回true,表示创建成功;如果文件已经存在则返回false,表示创建失败
static createTempFile(String prefix, string suffix);:File这个临时文件名称会有随机内容临时文件的默认存放位置为操作系统默认的临时文件位置
[c: \users\Administrator\AppData\Loca7\Temp]
exists():boolean文件或者文件夹是否存在
.length():long获取文件大小,单位为字节,如果是文件夹则返回值没有指定. renameTo(File):boolean修改名称,可以修改文件名和文件夹名称
delete():boolean删除文件。也可以删除文件夹,要求文件夹为空,不能有文件和子文件夹
注意:因为具体的文件或者文件夹的删除操作是由操作系统负责实现的,所以Java不能保证一定能够删除成功!
deleteOnExit():void退出系统时自动删除·目录操作方法
mkdir():boolean只能创建一层文件夹,如果创建d:/a1/a2/a3时,当父文件夹d:/a1/a2不存在时则创建失败
mkdirs():boolean自动创建多级文件夹
list():String[]获取当前文件夹的所有子文件信息
listFiles():File[]获取当前文件夹的所有子文件信息,子文件为File对象static listRoots():File[]列出系统的所有的根路径
文件过滤器FilenameFilter
带参数的listFiles方法支持对于子文件进行过滤,只获取需要满足条件的文件对象

FilenameFilter接口中包含一个accept(File dir,String name)方法,该方法用于对指定File的所有子目录或者文件进行迭代,如果方法返回true则list方法会获取该目录或者文件

匿名内部类的写法:推荐写法

语法糖Lambda表达式
1、函数式接口

@FunctionInterface
public interface FilenameFilter{

2、具体的表达式写法

File[] fs=f.1istFiles((dir,name)->{
return name !=nu11 &&name.endswith(" .ini");
});

简化写法

string[] nameList=file.list((dir,name)->name.endwith(".java")||new
File(name).isDirectory());

Path和Paths以及FilesPath接口
代表一个平台无关的平台路径Files提供工具方法操作文件
Paths提供创建Path的静态工厂方法Path相关方法

Files工具方法
复制文件Files.copy(Paths.get(“T1.java”), new FileOutputStream(“a.txt”))

一次性读取文件的所有行List lines=Files.readAllLines()

典型题目:例如获取c:\windows文件夹的大小【后代文件大小之和】和其中的文件个数等 – 递归

public class Test1 {
public static long number = 0; // 统计文件个数
public static long size = 0;// 统计所有文件大小之和
public static void main(String[] args) {
// File.pathSeparator 根据操作系统不同可以有:(Linux)和;(windows)两个,用于分割
多个路径
// File.separator用于分割路径的不同部分。路径中所使用分隔符有\和/两种写法
File file=new File(“c:/windows”);
list(file);
System.out.println(“总共文件个数为:”+number);
System.out.println(file.getAbsolutePath()+“总大小为:”+size);
}
public static void list(File file) {
if (file != null) {
if (file.isFile()) { //如果是文件
number++;
size += file.length();
}else if(file.isDirectory()){ //如果是文件夹
File[] children=file.listFiles();
if(children!=null && children.length>0)
for(File tmp:children)
list(tmp);
}
}
}
}

流模型
流是用于隐藏数据传输细节的操作模型,是数据传输的抽象表达,Java程序可以通过流来完成输入/输出 操作

根据操作方式的区别BIO阻塞同步、NIO非阻塞同步、AIO非阻塞异步
根据流的方向分为输入流和输出流
根据传输单位分为字节流和字符流
根据功能范围节点流和过滤流
装饰模式
装饰模式
Decorate允许向一个现有对象动态添加新功能,同时不改变结构,属于JavaSE 23种设计模式中的结构 型设计模型

用途:动态扩展功能
优点:装饰类和被装饰类可以独立发展,不会相互耦合
缺点:多层装饰比较复杂
要求:抽象

编码实现:4种角色

被装饰方抽象角色

public interface IShape{
void draw(); //public abstract,不是默认package
}

具体的装饰方实现,可以有多个不同实现类

public class Circle implemenets IShape{
public void draw(){
System.out.println(“画了一个圆圈”);
}
}

装饰抽象角色

public abstract class DecorateShape implements IShape{
private IShape target;//被装饰方对象,就是需要动态追加功能的对象
public DecodateShape(IShape target){
this.target=target;
}
public void draw(){
target.draw(); //具体的操作需要通过被装饰方提供实现
}
}

具体装饰角色

public class RedDecorateShape extends DecorateShape{
public RedDecorateShape(IShape target){
super(target);
}
public void draw(){
System.out.println(“使用红色”);
super.draw(); //调用父类中的被覆盖的方法
System.out.println(“恢复默认的颜色”);
}
}
测试类

//调用时进行组装
IShape circle=new Circle(); //节点流
IShape decorate=new RedDecorateShape(circle); //过滤流
decorate.draw();

//也允许这样使用
IShape decorate2=new BlueDecorateShape(decorate);

BIO编程
使用统一接口进行操作,具体实现细节无关

字节流
InputStream和OutputStream,都实现了Closeable接口,所以支持try-resources InputStream操作用于实现数据的读取操作

read():int 注意这里只是读取一个字节,0-255之间,-1表示流结束
read(byte[]):int 返回值表示读取的具体字节个数,-1流结束
close():void 关闭流
另外不重要的方法 read(byte[],int,int) available() skip(long)
OutputStream操作方法用于实现数据的写出操作

write(int):void 写出一个字节,int的低8位
write(byte[]具体数据,int起始下标,int长度):
void close():void 关闭流 不重要的方法
write(byte[])、flush()
样例:使用字节流进行文件的拷贝

public class Test4 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(“data/a1.txt”);
File file = new File(“out/”);
if(!file.exists())
file.mkdirs();
os=new FileOutputStream(“out/a1.bak”);//自动创建文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值