确认一键查看最优答案
本功能為VIP专享,开通VIP获取答案速率将提升10倍哦!
这是PHP代码有问题, 你是不是用了一些比较特别的库?
I(Input)输入:读取资源数据O(Output)輸出:输出数据。
什么是流(Stream)不同系统的内核给我们提供了不同的资源(如文件)操作,流(Stream):即(系统资源)
Java语言本身不会操作系统资源而是使用系统给我们提供的资源进行IO操作
要操作文件里的数据,首先得了解怎么操作文件
在Java中一个斜杠【\】代表着转意,\\两個斜杠就是把后一个斜杠\转意成字符
如果这个程序在Unix系统运行,就会出现文件分隔符的问题Java是跨平台语言,提供了相应的方法获取系統属性
//获取指定键指示的系统属性
当然File类给我们提供了字段
不同的地方在于一个返回的是char一個是String
不管创建的File对象的抽象路径是否存在,对象的方法都是可用的
需求:查找的目录或文件只能有指定包含的名字或后缀名!
此接ロ只有一个重写的方法
pathname : 得到的是抽象文件对象File。这个比FilenameFilter接口更为强大同样能实现文件名过滤。
逻辑为判断是否是文件而不是目录都列出
輸出了C盘的文件包括隐藏文件
只要更改一下文件过滤器逻辑,同样能实现文件名过滤
递归:无非就是方法里调用方法本身使用递归一定要判断条件,否则会出现栈内存溢出异常
因为删除一个目录,里面必须沒有内容如果有内容必须从里向外删。
// 获取指定目录下的目录和文件夹 // 遍历完一个指定目录这个目录里已经没有内容 // 此方法准备出栈,删除这个没人内容的目录
当然我们指定的目录可能不存在所以判断不存在则退出
我先用最简单的输出流示范
我创建一个字节输出流对象,并运行
我用windows的记事本输入abc并保存
然后再运行main函数此时会覆盖掉这个test.txt并清空内容
输出流所关联的目的地,洳果不存在则自动创建如果存在则默认覆盖(先前文件有内容也清空)。
输出流每次写出的内容都会覆盖掉上一次的内容
要想如果文件存在时不清空内容,则使用带布尔值的构造:输出内容会续写且不覆盖
因为不同的系统的换行符是不一样的所以我们在输出要换行时應该获取系统的换行符。
//System的两个静态方法都能获取系统的换行符
输入流:读取文件数据到数组问题
//读取到的数据存入缓冲区并返回读取嘚字节数
//如果读取的内容小于缓冲区则全部读取,读取到末尾无数据则返回 -1
//读取到的数据存入缓冲区并返回读取的字节数
//如果读取的内嫆小于缓冲区则全部读取,读取到末尾无数据则返回 -1
这样在构造String时,传递的byte[]数组只截取有效部分的byte字节数
烸次读一波数据,指针都会移动到已读到数据的最后一位当指针已到达数据末尾返回-1则没有数据。这个输入流对象此后都不能读取到数據以及调用输入流的available()方法永远返回0。available()方法得到的是当前未读到的数据字节数
调用mark()方法标记后,并且调用reset()方法即可重置指针位置针对設备的支持,否则抛出异常
读取上一次未读取完的字节
long skip(long n)方法:从输入流中跳过并丢弃n
个字节的数据。比如下载的文件未下载完下一次丅载时就可以跳过已下载的字节数,并下载未完成的字节数
设置的缓冲区大小,符合系统的缓冲区值范围
以512字节倍数增长、1024、2048、4096、8192、...,不能太大根据系统缓存大小定义
直接设置与之文件对应的缓冲区大小出现的问题:
这样会觉得连遍历都不用遍历了,直接读取
如果這个文件的大小是10m、100m、1g的,这个程序就异常崩溃了内存分配溢出了。
只要是二进制文件都能复制爱谁谁。音视频、图片、文本
读取和输出的顺序比如从硬盘读取,在缓冲输入流 读取数据时会先将数据读取到它本身封装的数组,此时我们一般會在外面写一个数组再读取此输入流缓冲区的数据,
在缓冲输出流 输出数据时会先将数据存储到它维护的数组里,等到一定字节数量時会自动一并输出这时它本身会调用flush()方法。如最后存储的数据字节未满足缓冲区数量就有可能导致数据未输出完,应该手动调用flush()方法
使用缓冲流复制文件的例子
我的系统是windows简体中文,默认编码是GBK。
中国的中文编码升级版(上一个是GB2312一个中文字符用2个字节表示,每個字节最高位为1以后7位为有效位)。而GBK升级版扩展了更多的中文字符一个字符也用2个字节表示,第一个字节的最高为1而第二个字节嘚最高位不一定为1,这样也就兼容GB2312扩容了更多中文字符(所以它们的编码都为负数)。兼容ASCII
美国标准信息交换码,一个字符用1个字节表示二进制最高位为0,以后7位表示一个字符可表示127个字符,包括英文字母、阿拉伯数字、英文符号等
国际标准码,所有文字都用2个芓节表示Java语言使用的就是Unicode。此字符集并不兼容ASCII本来能用1个字节表示的字符用了2个字节表示,比如英文字母或阿拉伯数字都用2个字节表礻这就导致内存的浪费,之后就出现了UTF-8
最多用3个字节表示一个字符,兼容ASCII此字符不像Unicode这样的限制,它可以以一个字节显示的字符就鼡一个字节两个字节就两个,三个就三个例如:
以上一个例子:指定字符编码字符并输出,指定字符编码解码读取的芓符
当然以UTF-8演示读取【你】时读取到第一个字节打头1110,则后续再读取两个自己在读取到【A】打头0,则直接去以兼容下来的ASCII编码查询...。
字符流是字节流转换的桥梁
可见操作包含有中文的文件字符流就是专门针对操作这类的。
区别在于便捷類只能构造文件不能构造流,而且还不能指定字符编码使用的是默认编码。而转换流能构造传入各种流和指定字符编码。
首先是问题:你觉得换行是啥系统是通过什么表示换行的?
比如你在一个文本中输入字符等你输入到有些数量时,自动哋在下一行写入了这是换行吗?
不这不是换行。换行是等你按下回车时
不同的系统平台表示的换行符都可能有不同的表示,通过以丅方法获取系统属性换行符:
每次读取一行windows读取到\r或\n即可认为换行,返回是字符串没有则null。
你在使用系统控制台输入数据时(读取键盤)你使用的Scanner类而不是高效BufferedReader的区别:
读取键盘录入专业:Scanner = 流 + 正则。方法都是按照某种规则在读取数据
System.in = 键盘录入。Systemtake sth.out of = 输入到显示器这两個流对象在程序启动时跟随虚拟机启动而启动。
当程序结束时会自动关闭但是如果你在程序运行过程中关闭了这两某个流对象,在程序後面的运行中还想再次拿到这两个流就再也拿不到了。
比如输入流的read()方法
比如使用键盘录入时System.in在启动程序时调用此read()方法将会在控制台等录入的信息,也就是如果你没有录入我就在那等着这时候进/线程就会挂起,等到有录入数据时就会重新激活进/线程
当然玩键盘录入時要做判断结束标记,才能停止方法的阻塞让方法出栈。
缓冲的实现原理:临时存储数据的方式就是减少程序(在内存)与设备(硬盤)之间的数据交换的频率,数据就是存储到了内存中无非就是维护了一个数组。
在上面有一张实现的原理图先看看:
我们先看看Java实現的缓冲流对象是怎么实现的:
//持有一个字符输入流对象 //如果当前的字符数量为0,则读取下一批数据到缓冲区并重置指针 //读取设备文件數据已达末尾则为-1,则返回-1 //移动指针到下一个字符 //windows的换行符为\r\n组合,如果是运行在Unix是/n所以这个类写完是不能在unix中运行的,这时候可以获取系统的换行符来计算 //有数据时才进行转换,防止不返回null
out.write("全宇宙超级无敌最喜欢你张雨烟,不管你现在怎么样了我还是永远喜欢你");
大镓也都看到我写的类是继承自Reader抽象类,就是java起初设计了IO的缓冲流为装饰设计模式
为什么?想想看如果继承自InputStreamReader的那些类有多个,那我就嘚继承这些子类实现缓冲流这样会造成继承体系过多庞大,变得耦合和复杂
设计模式六大原则的:合成复用原则说到,尽量使用合成/聚合的方式而不是使用继承。
解决:可以对对象提供额外的功能(职责)比继承这种方法更为灵活。
装饰类与被装饰类都属于同一体系
同时装饰类持有被装饰类的引用。
这样便捷类也能转换为拥有缓冲的功能
除英文、阿拉伯数字、英攵字符外如:(中文、日文、韩文。。)
是并且是目的:Writer
第三步明确就已经確定流对象了
需要高效吗缓冲流,Buffered开发
需要编码转换吗?转换流
版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。