I/O流 技术 学习笔记
本文查阅方法:
??? 1、查阅目录 —— 查阅本文目录,确定想要查阅的目录标题
??? 2、快捷“查找” —— 在当前浏览器页面,按键 “Ctrl+F” 按键组合,开启浏览器的查找功能,
???????????? 在查找搜索框中 输入需要查阅的 目录标题,便可以直接到达 标题内容 的位置。
??? 3、学习小结 —— 文中的学习小结内容,是笔者在学习之后总结出的,开发时可直接参考其进行应用开发的内容, 进一步加快了本文的查阅 速度。(水平有限,仅供参考。)
?
?
?
?
?
?
?
?
?
?
本文目录
?
??学习小结
?
??1、IO(Input??Output)流?概述
?
????(1)IO流的简介
?
????(2)IO流常用基类
?
????(3)IO程序的书写流程
?
??2、字符流--?FileWriter
?
??3、处理IO输出流异常的完整代码
?
??4、文件的续写
?
??5、字符流--FileReader读取文件的两种方式
?
????(1)第一种方式:逐个字符地从文件中读取数据
?
????(2)第二种方式:通过字符数组进行读取。
?
????(3)注意事项:
?
??6、拷贝文本文件
?
??7、字符流的缓冲区?BufferedWriter?和?BufferedReader?
?
????(1)BufferedWriter?--?字符写入流缓冲区
?
????(2)BufferedReader?--?字符读取流缓冲区:
?
????(3)通过缓冲区复制文本文件
?
????(4)readLine的原理图解
?
????(5)自定义ReadLine()方法
?
??8、采用“装饰设计模式”的思想来改造IO流类----增强其功能。
?
????(1)装饰设计模式?介绍
?
????(2)装饰和继承的区别
?
????(3)以LineNumberReader?类为基础装饰设计模式应用Demo
?
??9、字节流FileInputStream?/?FileOutputStream?对文件的读写操作
?
????(1)InputStream?/?OutputStream?的基本操作?Demo
?
????(2)拷贝图片?
?
??10、字节流的缓冲区:?BufferedOutputStream?/?BufferedInputStream
?
????(1)复制mp3:演示缓冲区使用流程
?
????(2)自定义字节流的缓冲区--?探寻read()和write()的特点
?
??11、读取键盘录入:?System.in
?
??12、读取/写入?转换流:InputStreamReader与OutputStreamWriter
?
????(1)标准输入输出
?
????(2)改变标准的输入输出设备
?
??13、众多IO流对象的选用规律
?
??14、保存“异常信息”到日志文件
?
??15、File对象的创建、删除、判断、获取等功能。
?
??16、File对象?————?实现文件列表功能常用方法
?
??17、File对象?——?操作?文件列表/目录
?
????(1)列出目录下所有内容——递归方法(含带层次展现)
?
????(2)删除带内容的目录
?
????(3)创建展现多层级的Java文件列表并输出到文件
?
??18、Properties??存取配置文件
?
??19、PrintStream?以及?PrintWriter
?
??20、文件的?切割操作
?
??21、文件的合并操作?-----??SequenceInputStream?合并文件
?
??22、对象的序列化:ObjectOutputStream?和反序列化:ObjectInputStream??
?
??23、RandomAccessFile?随机读写访问文件
?
??24、操作基本数据类型?DataInputStream与DataOutputStream
?
??25、ByteArrayStream?操作字节数组的流对象。
?
??26、字符的编码和解码
?
????(1)编码?和?解码?的练习
?
????(2)转换流的字符编码
?
??
?
?
?
?
?
?
?
?
?
?
学习小结
?
(1)字符流的输入与输出
?
???public??void?test()?//此种写法虽然麻烦,但是效能高,也处理了异常,非常健壮,建议拷贝使用。
?
???{
?
??????BufferedReader?bufr?=?null;
?
??????BufferedWriter?bufw?=?null;
?
??????try{
?
?????????bufr?=?new?BufferedReader(new?FileReader("Text1.java"));
?
?????????bufw?=?new?BufferedWriter(new?FileWriter("Text2.txt"));
?
?????????String?line?=?null;
?
?????????while((line=bufr.readLine())!=null){
?
??????????bufw.write(line);
?
??????????bufw.newLine();??//写入换行符。
?
??????????bufw.flush();
?
?????????}
?
??????}catch?(IOException?e){
?
?????????throw?new?RuntimeException("读写失败");
?
??????}
?
??????finally
?
??????{
?
?????????try{
?
??????????if(bufr!=null)
?
????????????bufr.close();
?
?????????}catch?(IOException?e){
?
??????????throw?new?RuntimeException("读取关闭失败");
?
?????????}
?
?????????try{
?
??????????if(bufw!=null)
?
?????????????bufw.close();
?
?????????}catch?(IOException?e){
?
??????????throw?new?RuntimeException("写入关闭失败");
?
?????????}
?
??????}
?
???}
?
?
?
(2)字节流的输入与输出
?
????//采用了Buffered缓冲区,但是未考虑详细异常的字节流读取
?
????public?static?void?copy_1()throws?IOException{
?
??????BufferedInputStream?bufis?=?new?BufferedInputStream(new?FileInputStream("c:\\0.mp3"));
?
??????BufferedOutputStream?bufos?=?new?BufferedOutputStream(new?FileOutputStream("c:\\1.mp3"));
?
?
?
??????int?by?=?0;
?
??????while((by=bufis.read())!=-1){
?
?????????bufos.write(by);
?
??????}
?
??????bufos.close();
?
??????bufis.close();?????
?
???}
?
?
?
??//未采用字节流缓冲区Buffered,但是处理了异常的字节流读取。
?
???public?static?void?main(String[]?args){
?
??????FileOutputStream?fos?=?null;
?
??????FileInputStream?fis?=?null;
?
??????try{
?
?????????fos?=?new?FileOutputStream("c:\\2.bmp");
?
?????????fis?=?new?FileInputStream("c:\\1.bmp");
?
?
?
????//===============?开发时常用代码片段====================?
?
?????????byte[]?buf?=?new?byte[1024];
?
?????????int?len?=?0;
?
?????????while((len=fis.read(buf))!=-1){
?
??????????fos.write(buf,0,len);
?
?????????}
?
????//===============?开发时常用代码片段====================?
?
?
?
??????}catch?(IOException?e){
?
?????????throw?new?RuntimeException("复制文件失败");
?
??????}finally{
?
?????????try{
?
??????????if(fis!=null)
?
?????????????fis.close();
?
?????????}catch?(IOException?e){
?
??????????throw?new?RuntimeException("读取关闭失败");
?
?????????}
?
?
?
?????????try{
?
??????????if(fos!=null)
?
?????????????fos.close();
?
?????????}catch?(IOException?e){
?
??????????throw?new?RuntimeException("写入关闭失败");
?
?????????}
?
??????}
?
???}
?
?
?
(3)Properties??读取配置文件
?
????Properties?prop?=?new?Properties();
?
????FileInputStream?fis?=?new?FileInputStream("info.txt");
?
????prop.load(fis);??//将流中的数据加载进集合。
?
????String?value?=?prop.getProperty("lisi");??//取出属性值的操作
?
????fis.close();
?
?
?
?
?
(4)File对象的创建、判断
?
????FileInputStream?fis?=?null;//注:该输入流?根据实际情况?赋值。
?
????File?dir?=?new?File("abc\\kkk\\a");//你讲文件放置到该目录下面。
?
????if(!dir.exists()){??//判断该目录是否已实际存在
?
??????dir.mkdirs();??//若不存在,则创建出实际目录
?
????}
?
????File?newFile=new?File(dir,"newText.jpg");??//将目标目录与拟存放后的新文件名创建新的文件绝对路径
?
????FileOutputStream?fos?=new?FileOutputStream(newFile);
?
????byte[]?buf?=?new?byte[1024];
?
??????int?len?=?0;
?
??????while((len=fis.read(buf))!=-1){
?
??????fos.write(buf,0,len);????//向新的文件中写入数据。
?
??????}
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
1、IO(Input??Output)流?概述
?
??(1)IO流的简介??
?
????简介:IO流用来处理设备之间的数据传输,Java对数据的操作是通过流的方式,Java用于操作流的对象都在IO包中?
?
?????分类:流按操作数据分为两种:字节流与字符流。?
?
??????????流按流向分为:输入流,输出流。?
?
??(2)IO流常用基类?
?
?????字节流的抽象基类:?
?
??????InputStream?,OutputStream。?
?
?????字符流的抽象基类:?
?
??????Reader?,Writer?。?
?
?????注:由这四个类派生出来的子类名称都是?
?
???????以其父类名作为子类名的后缀。?
?
???????????如:InputStream的子类FileInputStream。?
?
???????????如:Reader的子类FileReader。?
?
??(3)IO程序的书写流程?
?
?????导入IO包中的类?
?
????编写IO代码
?
?????进行IO异常处理?
?
?????在finally?中对流进行关闭?
?
?
?
?
?
?
?
?
?
?
2、字符流--?FileWriter
?
??FileWriter是专门用于操作文件的Writer子类对象。FileWriter。??后缀名是父类名。?前缀名是该流对象的功能。
?
????语法:???
?
????创建流对象,建立数据存放文件?
?
????????FileWriter?fw?=?new?FileWriter(“Test.txt”);?
?
?????调用流对象的写入方法,将数据写入流?
?
????????fw.write(“text”);?
?
?????关闭流资源,并将流中的数据清空到文件中。?
?
????????fw.close();?
?
?
?
??Demo如下:
?
??class??FileWriterDemo
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
?
????????//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
?
????????//其实该步就是在明确数据要存放的目的地。
?
????????FileWriter?fw?=?new?FileWriter("demo.txt");
?
????????//调用write方法,将字符串写入到流中。
?
????????fw.write("abcde");
?
????????//刷新流对象中的缓冲中的数据。
?
????????//将数据刷到目的地中。
?
????????//fw.flush();
?
?
?
????????//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
?
????????//将数据刷到目的地中。
?
????????//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
?
????????fw.close();
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
3、处理IO输出流异常的完整代码
?
????这是处理写文件时控制异常的完整代码,建议我们在实际开发中,尽量写这种代码,将会是代码更加的严谨和健壮。?
?
??????????????FileWriter?fw?=?null;?
?
??????????????try{?
?
??????????????????fw?=?new?FileWriter("Test.txt");?
?
??????????????????fw.write("text");?
?
??????????????}?
?
??????????????catch?(IOException?e){?
?
??????????????????System.out.println(e.toString());?
?
??????????????}?
?
??????????????finally{?
?
??????????????????If(fw!=null)?
?
??????????????????try{?
?
????????????fw.close();?
?
??????????}catch?(IOException?e){?
?
????????????System.out.println(e.toString());?
?
??????????}?
?
??????????????}?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
4、文件的续写
?
??在开发中,向已经存在的文件的末尾,继续续写数据的功能非常重要,下面两个构造函数可以实现:
?
????FileWriter(String?fileName,?boolean?append)?
?
????FileOutputStream(String?name,?boolean?append)
?
????根据给定的文件名以及指示是否附加写入数据的?boolean?值来构造?FileWriter/FileOutputStream对象
?
?
?
??Demo样例:
?
????FileWriter??fw=new?FileWriter("demo.txt",true);
?
????fw.write("nihao\r\n?xiexie");????//在文件中写入换行显示的数据,
?
????fw.close();?????//windows的记事本里识别的换行符,仅支持?\r\n,?
?
??????????????//而linux等系统以及?EditPlus?中则支持\n换行。
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
5、字符流--FileReader读取文件的两种方式
?
??(1)第一种方式:逐个字符地从文件中读取数据
?
????Demo:
?
????class??FileReaderDemo
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException{
?
??????????//创建一个文件读取流对象,和指定名称的文件相关联。
?
??????????//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
?
??????????FileReader?fr?=?new?FileReader("demo.txt");
?
??????????//调用读取流对象的read方法。
?
??????????//read():一次读一个字符。而且会自动往下读。??
?
??????????int?ch?=?0;
?
??????????while((ch=fr.read())!=-1){
?
?????????????System.out.println(
?
??????????}
?
??????????/*
?
??????????while(true){
?
?????????????int?ch?=?fr.read();
?
?????????????if(ch==-1)
?
????????????break;
?
?????????????System.out.println("ch="+(char)ch);
?
??????????}
?
??????????*/
?
??????????fr.close();
?
???????}
?
????}
?
?
?
?逐个字符读取文件原理图解
?
?
?
?
?
??
?
?
?
??(2)第二种方式:通过字符数组进行读取。
?
????Demo:
?
????class?FileReaderDemo2?
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException{
?
??????????FileReader?fr?=?new?FileReader("demo.txt");??
?
??????????//定义一个字符数组。用于存储读到字符。
?
??????????//该read(char[])返回的是读到字符个数。
?
??????????char[]?buf?=?new?char[1024];
?
??????????int?num?=?0;
?
??????????while((num=fr.read(buf))!=-1){
?
?????????????System.out.println(new?String(buf,0,num));
?
??????????}??
?
??????????fr.close();
?
???????}
?
????}
?
?
?
字符数组进行读取文件图解?
?
?
?
?
?
?
?
?
??(3)注意事项:
?
????a.定义文件路径时,可以用“/”或者“\\”?。?
?
????b.在创建一个文件时,如果目录下有同名文件将被覆盖。?
?
????c.在读取文件时,必须保证该文件已存在,否则出异常。?
?
?
?
??
?
?
?
?
?
?
6、拷贝文本文件
?
??拷贝文本文件原理:是有两个过程完成的。
?
????(1)读取数据:读取源文件中的数据到内存中。
?
????(2)写入数据:将读到的数据从内存中写入到目标位置一个文件中。
?
?
?
??示例剖析:将C盘一个文本文件复制到D盘。
?
????复制的原理:
?
????其实就是将C盘下的文件数据存储到D盘的一个文件中。
?
????步骤:
?
????1,在D盘创建一个文件。用于存储C盘文件中的数据。
?
????2,定义读取流和C盘文件关联。
?
????3,通过不断的读写完成数据存储。
?
????4,关闭资源。
?
?
?
??示例Demo:
?
??class?CopyText?
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException{
?
????????copy_2();
?
?????}
?
?
?
?????public?static?void?copy_2(){
?
????????FileWriter?fw?=?null;
?
????????FileReader?fr?=?null;
?
????????try{
?
???????????fw?=?new?FileWriter("SystemDemo_copy.txt");
?
???????????fr?=?new?FileReader("SystemDemo.java");
?
???????????char[]?buf?=?new?char[1024];
?
???????????int?len?=?0;
?
???????????while((len=fr.read(buf))!=-1){
?
????????????fw.write(buf,0,len);
?
???????????}
?
????????}catch?(IOException?e){
?
???????????throw?new?RuntimeException("读写失败");
?
????????}finally{
?
???????????if(fr!=null)
?
????????????try{
?
?????????????fr.close();
?
????????????}catch?(IOException?e){?????}
?
???????????if(fw!=null)
?
????????????try{
?
?????????????fw.close();
?
????????????}catch?(IOException?e){????}
?
????????}
?
?????}
?
?????//从C盘读一个字符,就往D盘写一个字符。
?
?????public?static?void?copy_1()throws?IOException
?
?????{
?
????????//创建目的地。
?
????????FileWriter?fw?=?new?FileWriter("RuntimeDemo_copy.txt");
?
????????//与已有文件关联。
?
????????FileReader?fr?=?new?FileReader("RuntimeDemo.java");
?
????????int?ch?=?0;
?
????????while((ch=fr.read())!=-1){
?
???????????fw.write(ch);
?
????????}??
?
????????fw.close();
?
????????fr.close();
?
?????}
?
??}
?
?
?
?
?
?文件复制过程图例
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
7、字符流的缓冲区?BufferedWriter?和?BufferedReader?
?
?
?
???缓冲区的出现提高了对数据的读写效率,要结合流才可以使用。是在流的基础上对流的功能进行了增强。?
?
?????对应类?
?
??????BufferedWriter??--?字符写入流缓冲区
?
??????BufferedReader??--?字符读取流缓冲区
?
???缓冲区是为了提高流的操作效率而出现的。所以在创建缓冲区之前,必须要先有流对象。
?
?
?
??(1)BufferedWriter?--?字符写入流缓冲区
?
????备注:该缓冲区中提供了一个跨平台的换行符。newLine();
?
?
?
????示例Demo:
?
??????class??BufferedWriterDemo
?
??????{
?
?????????public?static?void?main(String[]?args)?throws?IOException
?
?????????{
?
????????????//创建一个字符写入流对象。
?
????????????FileWriter?fw?=?new?FileWriter("buf.txt");
?
????????????//为了提高字符写入流效率。加入了缓冲技术。
?
????????????//只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可。
?
????????????BufferedWriter?bufw?=?new?BufferedWriter(fw);
?
????????????for(int?x=1;?x<5;?x++){
?
???????????????bufw.write("abcd"+x);
?
???????????????bufw.newLine();//若要在写入的文本中实现换行格式的效果,就需要调用newLine()方法写入换行符。
?
???????????????bufw.flush();
?
????????????}
?
????????????//记住,只要用到缓冲区,就要记得刷新。
?
????????????//bufw.flush();
?
????????????//其实关闭缓冲区,就是在关闭缓冲区中的流对象。
?
????????????bufw.close();
?
?????????}
?
??????}
?
?
?
?
?
?
?
??(2)BufferedReader?--?字符读取流缓冲区:
?
????该缓冲区提供了一个一次读一行的方法?readLine,方便于对文本数据的获取。
?
????当返回null时,表示读到文件末尾。
?
????备注:readLine方法返回的时候只返回回车符之前的数据内容,并不返回回车符。
?
?
?
????示例Demo:
?
????class??BufferedReaderDemo
?
????{
?
????????public?static?void?main(String[]?args)?throws?IOException{
?
??????????//创建一个读取流对象和文件相关联。
?
??????????FileReader?fr?=?new?FileReader("buf.txt");
?
??????????//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
?
??????????BufferedReader?bufr?=?new?BufferedReader(fr);
?
?
?
??????????String?line?=?null;
?
??????????while((line=bufr.readLine())!=null){
?
?????????????System.out.print(line);
?
??????????}
?
??????????bufr.close();
?
????????}
?
????}???
?
?
?
?
?
??(3)通过缓冲区复制文本文件
?
?
?
????示例Demo:
?
????//需求:通过缓冲区复制一个.java文件。
?
????class??CopyTextByBuf
?
????{
?
???????public?static?void?main(String[]?args)?
?
???????{
?
??????????BufferedReader?bufr?=?null;
?
??????????BufferedWriter?bufw?=?null;
?
??????????try{
?
?????????????bufr?=?new?BufferedReader(new?FileReader("BufferedWriterDemo.java"));
?
?????????????bufw?=?new?BufferedWriter(new?FileWriter("bufWriter_Copy.txt"));
?
?????????????String?line?=?null;
?
?????????????while((line=bufr.readLine())!=null){
?
??????????????bufw.write(line);
?
??????????????bufw.newLine();??//若要在写入的文本中实现换行格式的效果,就需要调用newLine()方法写入换行符。
?
??????????????bufw.flush();
?
?????????????}
?
??????????}catch?(IOException?e){
?
?????????????throw?new?RuntimeException("读写失败");
?
??????????}
?
??????????finally
?
??????????{
?
?????????????try{
?
??????????????if(bufr!=null)
?
???????????????bufr.close();
?
?????????????}catch?(IOException?e){
?
??????????????throw?new?RuntimeException("读取关闭失败");
?
?????????????}
?
?????????????try{
?
??????????????if(bufw!=null)
?
???????????????bufw.close();
?
?????????????}catch?(IOException?e){
?
??????????????throw?new?RuntimeException("写入关闭失败");
?
?????????????}
?
??????????}
?
???????}
?
????}
?
?
?
?
?
??(4)readLine的原理图解
?
?
?
?
?
?
?
?
?
?
?
?
??(5)自定义ReadLine()方法
?
????明白了BufferedReader类中特有方法readLine的原理后,可以自定义一个MyBufferedReader类中包含一个功能和readLine一致的方法。
?
来模拟一下BufferedReader
?
?
?
????示例Demo:
?
????class?MyBufferedReader?extends?Reader
?
????{?
?
???????private?Reader?r;
?
???????MyBufferedReader(Reader?r){
?
??????????this.r?=?r;
?
???????}
?
???????//可以一次读一行数据的方法。
?
???????public?String?myReadLine()throws?IOException{
?
??????????//定义一个临时容器。原BufferReader封装的是字符数组。
?
??????????//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
?
??????????StringBuilder?sb?=?new?StringBuilder();
?
??????????int?ch?=?0;
?
??????????while((ch=r.read())!=-1){
?
?????????????if(ch=='\r')
?
??????????????continue;
?
?????????????if(ch=='\n')
?
??????????????return?sb.toString();
?
?????????????else
?
??????????????sb.append((char)ch);
?
??????????}
?
??????????if(sb.length()!=0)
?
?????????????return?sb.toString();
?
??????????return?null;??
?
???????}
?
???????/*
?
???????覆盖Reader类中的抽象方法。
?
???????*/
?
???????public?int?read(char[]?cbuf,?int?off,?int?len)?throws?IOException{
?
??????????return?r.read(cbuf,off,len)?;
?
???????}
?
???????public?void?close()throws?IOException{
?
??????????r.close();
?
???????}
?
???????public?void?myClose()throws?IOException{
?
??????????r.close();
?
???????}
?
????}
?
????class??MyBufferedReaderDemo
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException{
?
??????????FileReader?fr?=?new?FileReader("buf.txt");
?
??????????MyBufferedReader?myBuf?=?new?MyBufferedReader(fr);
?
??????????String?line?=?null;
?
??????????while((line=myBuf.myReadLine())!=null){
?
?????????????System.out.println(line);
?
??????????}
?
??????????myBuf.myClose();
?
???????}
?
????}
?
?
?
?
?
?
?
?
?
?
?
?
8、采用“装饰设计模式”的思想来改造IO流类----增强其功能。
?
??(1)装饰设计模式?介绍
?
????装饰设计模式:当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类,这种增强类功能的方式称之为“装饰设计模式”。
?
????装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。
?
?
?
????示例Demo:
?
????class?Person
?
????{
?
???????public?void?chifan(){
?
??????????System.out.println("吃饭");
?
???????}
?
????}
?
????class?SuperPerson?
?
????{
?
???????private?Person?p?;
?
???????SuperPerson(Person?p){
?
??????????this.p?=?p;
?
???????}
?
???????public?void?superChifan(){
?
??????????System.out.println("开胃酒");
?
??????????p.chifan();
?
??????????System.out.println("甜点");
?
??????????System.out.println("来一根");
?
???????}
?
????}?
?
????class??PersonDemo
?
????{
?
???????public?static?void?main(String[]?args){
?
??????????Person?p?=?new?Person();
?
??????????//p.chifan();
?
??????????SuperPerson?sp?=?new?SuperPerson(p);
?
??????????sp.superChifan();
?
???????}
?
????}
?
?
?
?
?
??(2)装饰和继承的区别
?
????我们使用装饰类增强原有类功能的思想,与继承的方式很相似,但是二者在实际的使用中,是有着一定区别的
?
????下面以模拟?自定义增强Reader体系中的各种装饰类?继承关系?来分析?二者的区别
?
??????MyReader//专门用于读取数据的类。
?
???????|--MyTextReader
?
????????|--MyBufferTextReader
?
???????|--MyMediaReader
?
????????|--MyBufferMediaReader
?
???????|--MyDataReader
?
????????|--MyBufferDataReader???????
?
??????Demo:
?
??????class?MyBufferReader
?
??????{
?
?????????MyBufferReader(MyTextReader?text){
?
?
?
????????}
?
?????????MyBufferReader(MyMediaReader?media){
?
?
?
????????}
?
??????}
?
?
?
??????上面这个类扩展性很差,倘若找到其参数的共同类型,通过多态的形式,可以提高扩展性。
?
??????Demo:
?
??????class?MyBufferReader?extends?MyReader
?
??????{
?
?????????private?MyReader?r;
?
?????????MyBufferReader(MyReader?r){
?
?
?
?????????}
?
??????}?
?
??????MyReader//专门用于读取数据的类。
?
???????|--MyTextReader
?
???????|--MyMediaReader
?
???????|--MyDataReader
?
???????|--MyBufferReader
?
?
?
??????以前是通过继承将每一个子类都具备缓冲功能,那么继承体系会复杂,并不利于扩展。现在优化思想,单独描述一下缓冲内容,将需要被缓冲的对象,传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区,这样继承体系就变得很简单,优化了体系结构。
?
?
?
??????装饰模式比继承要灵活,避免了继承体系臃肿,而且降低了类与类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。???????
?
?
?
??(3)以LineNumberReader?类为基础装饰设计模式应用Demo
?
??????示例Demo:LineNumberReader?(跟踪行号的缓冲字符输入流)?与?自定义MyLineNumberReader
?
?
?
??????//原?LineNumberReader?功能Demo
?
??????class?LineNumberReaderDemo?
?
??????{
?
?????????public?static?void?main(String[]?args)throws?IOException?{
?
????????????FileReader?fr?=?new?FileReader("PersonDemo.java");
?
????????????LineNumberReader?lnr?=?new?LineNumberReader(fr);//跟踪行号的缓冲字符输入流
?
????????????String?line?=?null;
?
????????????lnr.setLineNumber(100);//?设置当前行号。
?
????????????while((line=lnr.readLine())!=null){
?
???????????????System.out.println(lnr.getLineNumber()+":"+line);//获得当前行号。
?
????????????}
?
????????????lnr.close();
?
?????????}
?
??????}?
?
?
?
??????//自定义?类似LineNumberReader?功能的类Demo
?
??????class?MyLineNumberReader?
?
??????{
?
?????????private?Reader?r;
?
?????????private?int?lineNumber;
?
?????????MyLineNumberReader(Reader?r){
?
????????????this.r?=?r;
?
?????????}
?
?????????public?String?myReadLine()throws?IOException{
?
????????????lineNumber++;
?
????????????StringBuilder?sb?=?new?StringBuilder();
?
????????????int?ch?=?0;
?
????????????while((ch=r.read())!=-1){
?
???????????????if(ch=='\r')
?
????????????????continue;
?
???????????????if(ch=='\n')
?
????????????????return?sb.toString();
?
???????????????else
?
????????????????sb.append((char)ch);
?
????????????}
?
????????????if(sb.length()!=0)
?
???????????????return?sb.toString();
?
????????????return?null;
?
?????????}
?
?????????public?void?setLineNumber(int?lineNumber){
?
????????????this.lineNumber?=?lineNumber;
?
?????????}
?
?????????public?int?getLineNumber(){
?
????????????return?lineNumber;
?
?????????}
?
?????????public?void?myClose()throws?IOException{
?
????????????r.close();
?
?????????}
?
??????}
?
?
?
??????//采用了装饰模式的?MyLineNumberReader??Demo
?
??????class?MyLineNumberReader?extends?MyBufferedReader
?
??????{
?
?????????private?int?lineNumber;
?
?????????MyLineNumberReader(Reader?r){
?
????????????super(r);
?
?????????}
?
?????????public?String?myReadLine()throws?IOException{
?
????????????lineNumber++;
?
????????????return?super.myReadLine();
?
?????????}
?
?????????public?void?setLineNumber(int?lineNumber){
?
????????????this.lineNumber?=?lineNumber;
?
?????????}
?
?????????public?int?getLineNumber(){
?
????????????return?lineNumber;
?
?????????}
?
??????}
?
?
?
??????class??MyLineNumberReaderDemo
?
??????{
?
?????????public?static?void?main(String[]?args)?throws?IOException{
?
????????????FileReader?fr?=?new?FileReader("copyTextByBuf.java");
?
????????????MyLineNumberReader?mylnr?=?new?MyLineNumberReader(fr);
?
????????????String?line?=?null;
?
????????????mylnr.setLineNumber(100);
?
????????????while((line=mylnr.myReadLine())!=null){
?
???????????????System.out.println(mylnr.getLineNumber()+"::"+line);
?
????????????}
?
????????????mylnr.myClose();
?
?????????}
?
??????}
?
?
?
?
?
?
?
?
?
?
?
?
9、字节流FileInputStream?/?FileOutputStream?对文件的读写操作
?
??字节流:InputStream?/?OutputStream?的基本操作与字符流类相同?
?
?????但它不仅可以操作字符,还可以操作其他媒体文件需求。例如想要操作图片数据,这时就要用到字节流。
?
?
?
??(1)InputStream?/?OutputStream?的基本操作?Demo
?
????Demo样例:
?
????class??FileStream
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException{
?
??????????readFile_3();
?
???????}
?
???????public?static?void?readFile_3()throws?IOException{??//使用available()函数定义正好的缓冲区
?
??????????FileInputStream?fis?=?new?FileInputStream("fos.txt");
?
?
?
??????????//??int?num?=?fis.available();
?
??????????byte[]?buf?=?new?byte[fis.available()];//定义一个刚刚好的缓冲区,不用在循环了,但有可能因文件太大造成内存溢出。
?
??????????fis.read(buf);
?
??????????System.out.println(new?String(buf));
?
??????????fis.close();
?
???????}
?
?
?
???????public?static?void?readFile_2()throws?IOException{??//定义一定容量的缓冲区进行循环的读取/写入操作,?推荐使用的方式,高效又安全。
?
??????????FileInputStream?fis?=?new?FileInputStream("fos.txt");
?
??????????byte[]?buf?=?new?byte[1024];
?
??????????int?len?=?0;
?
??????????while((len=fis.read(buf))!=-1){
?
?????????????System.out.println(new?String(buf,0,len));
?
??????????}
?
??????????fis.close();??
?
???????}?
?
???????public?static?void?readFile_1()throws?IOException{??//逐个字节地读取并写入数据到文件。
?
??????????FileInputStream?fis?=?new?FileInputStream("fos.txt");
?
??????????int?ch?=?0;
?
??????????while((ch=fis.read())!=-1){
?
?????????????System.out.println((char)ch);
?
??????????}
?
??????????fis.close();
?
???????}
?
???????public?static?void?writeFile()throws?IOException{??//将数据写入到文件
?
??????????FileOutputStream?fos?=?new?FileOutputStream("fos.txt");??
?
??????????fos.write("abcde".getBytes());
?
??????????fos.close();??
?
???????}
?
????}
?
?
?
?
?
??(2)拷贝图片?
?
????思路:
?
??????a.用字节读取流对象和图片关联。
?
??????b.用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
?
??????c.通过循环读写,完成数据的存储。
?
??????d.关闭资源。
?
?
?
????示例Demo:
?
????class??CopyPic
?
????{
?
???????public?static?void?main(String[]?args){
?
??????????FileOutputStream?fos?=?null;
?
??????????FileInputStream?fis?=?null;
?
??????????try{
?
?????????????fos?=?new?FileOutputStream("c:\\2.bmp");
?
?????????????fis?=?new?FileInputStream("c:\\1.bmp");
?
?????????????byte[]?buf?=?new?byte[1024];
?
?????????????int?len?=?0;
?
?????????????while((len=fis.read(buf))!=-1){
?
??????????????fos.write(buf,0,len);
?
?????????????}
?
??????????}catch?(IOException?e){
?
?????????????throw?new?RuntimeException("复制文件失败");
?
??????????}finally{
?
?????????????try{
?
??????????????if(fis!=null)
?
?????????????????fis.close();
?
?????????????}catch?(IOException?e){
?
??????????????throw?new?RuntimeException("读取关闭失败");
?
?????????????}
?
?
?
?????????????try{
?
??????????????if(fos!=null)
?
?????????????????fos.close();
?
?????????????}catch?(IOException?e){
?
??????????????throw?new?RuntimeException("写入关闭失败");
?
?????????????}
?
??????????}
?
???????}
?
????}
?
?
?
?
?
?
?
?
?
?
?
?
10、字节流的缓冲区:?BufferedOutputStream?/?BufferedInputStream
?
????字节流的缓冲区同样是提高了字节流的读写效率。?下面就以一个Demo来介绍一下。
?
?
?
??(1)复制mp3:演示缓冲区使用流程
?
????示例Demo:
?
????class??CopyMp3
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException{
?
??????????long?start?=?System.currentTimeMillis();
?
??????????copy_2();
?
??????????long?end?=?System.currentTimeMillis();
?
??????????System.out.println((end-start)+"毫秒");
?
???????}
?
???????public?static?void?copy_2()throws?IOException
?
???????{
?
??????????MyBufferedInputStream?bufis?=?new?MyBufferedInputStream(new?FileInputStream("c:\\9.mp3"));
?
??????????BufferedOutputStream?bufos?=?new?BufferedOutputStream(new?FileOutputStream("c:\\3.mp3"));
?
?
?
??????????int?by?=?0;
?
??????????//System.out.println("第一个字节:"+bufis.myRead());
?
??????????while((by=bufis.myRead())!=-1){
?
?????????????bufos.write(by);
?
??????????}
?
??????????bufos.close();
?
??????????bufis.myClose();
?
???????}
?
???????//通过字节流的缓冲区完成复制。
?
???????public?static?void?copy_1()throws?IOException{
?
??????????BufferedInputStream?bufis?=?new?BufferedInputStream(new?FileInputStream("c:\\0.mp3"));
?
??????????BufferedOutputStream?bufos?=?new?BufferedOutputStream(new?FileOutputStream("c:\\1.mp3"));
?
?
?
??????????int?by?=?0;
?
??????????while((by=bufis.read())!=-1){
?
?????????????bufos.write(by);
?
??????????}
?
??????????bufos.close();
?
??????????bufis.close();?????
?
???????}
?
????}
?
?
?
??(2)自定义字节流的缓冲区--?探寻read()和write()的特点
?
????示例Demo:
?
??????class?MyBufferedInputStream
?
??????{
?
?????????private?InputStream?in;
?
?????????private?byte[]?buf?=?new?byte[1024*4];?????
?
?????????private?int?pos?=?0,count?=?0;
?
?
?
?????????MyBufferedInputStream(InputStream?in){
?
????????????this.in?=?in;
?
?????????}
?
?????????//一次读一个字节,从缓冲区(字节数组)获取。
?
?????????public?int?myRead()throws?IOException{
?
????????????//通过in对象读取硬盘上数据,并存储buf中。
?
????????????if(count==0){
?
???????????????count?=?in.read(buf);
?
???????????????if(count<0)
?
????????????????return?-1;
?
???????????????pos?=?0;
?
???????????????byte?b?=?buf[pos];
?
???????????????count--;
?
???????????????pos++;
?
???????????????return?b&255;
?
????????????}else?if(count>0){
?
???????????????byte?b?=?buf[pos];
?
???????????????count--;
?
???????????????pos++;
?
???????????????return?b&0xff;
?
????????????}
?
????????????return?-1;
?
?????????}
?
?????????public?void?myClose()throws?IOException{
?
????????????in.close();
?
?????????}
?
??????}
?
?
?
??????下面我们来分析一下:字节流的读一个字节的read方法为什么返回值类型不是byte,而是int
?
??????11111111-111111110000000000101001001010100101010010101001010??//返回的一串二进制代码的前8位有可能是8个1;
?
?
?
??????byte:?-1??--->??int?:?-1;
?
??????00000000?00000000?00000000?11111111??255
?
??????11111111?11111111?11111111?11111111????//此处是为了与我们的校验值?-1(int)?进行比对,进行自动补位而类型提升。
?
?
?
??????11111111??-->提升了一个int类型?那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
?
??????那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
?
??????怎么补0呢?
?
???????11111111?11111111?11111111?11111111????????????????????????
?
??????&00000000?00000000?00000000?11111111?
?
??????------------------------------------
?
???????00000000?00000000?00000000?11111111?
?
??????0000-0001
?
??????1111-1110
?
??????000000001
?
??????1111-1111??-1
?
?
?
??????结论:??????。
?
??????因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
?
??????那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
?
??????所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。???????
?
??????而在写入数据时,只写该int类型数据的最低8位。
?
??????注:这两种操作都被封装:
?
??????????“返回数据时自动补位24个0”?————?封装在read()方法里面;
?
??????????“写入数据时只写该int类型数据的最低8位”?————?封装在write()方法里面。
?
?
?
?
?
?
?
?
?
?
11、读取键盘录入:?System.in
?
??java.lang.System类中给我们提供了两个对象。
?
????System.out?--??InputStream:对应的是标准输出设备,控制台。
?
????System.in??--??PrintStream:对应的标准输入设备:键盘。
?
??我们根据其所属的数据类型,就可以当作一种输入流?或是?输出流?,就可以进行键盘的读取操作与控制台的输出。
?
?
?
??示例Demo:
?
??//需求:通过键盘录入数据,当录入一行数据后,就将该行数据进行打印,如果录入的数据是over,那么停止录入。
?
??class??ReadIn
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????InputStream?in?=?System.in;
?
????????StringBuilder?sb?=?new?StringBuilder();
?
????????while(true){
?
???????????int?ch?=?in.read();
?
???????????if(ch=='\r')
?
????????????continue;
?
???????????if(ch=='\n'){
?
????????????String?s?=?sb.toString();
?
????????????if("over".equals(s))
?
???????????????break;
?
????????????System.out.println(s.toUpperCase());
?
????????????sb.delete(0,sb.length());
?
???????????}else
?
????????????sb.append((char)ch);
?
????????}
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
12、读取/写入?转换流:InputStreamReader与OutputStreamWriter
?
????转换流:InputStreamReader?,?OutputStreamWriter?
?
?????转换流的由来?
?
????????a.字符流与字节流之间的桥梁?
?
????????b.方便了字符流与字节流之间的操作?
?
?????转换流的应用?
?
????????字节流中的数据都是字符时,转成字符流操作更高效。?
?
????转换流的使用之一:作为字符和字节之间的桥梁,通常涉及到字符编码转换时,需要用到转换流。
?
?
?
??(1)标准输入输出
?
????示例Demo1:
?
????class??TransStreamDemo
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException
?
???????{
?
??????????//获取键盘录入对象。
?
??????????//InputStream?in?=?System.in;
?
??????????//将字节流对象转成字符流对象,使用转换流。InputStreamReader
?
??????????//InputStreamReader?isr?=?new?InputStreamReader(in);
?
??????????//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
?
??????????//BufferedReader?bufr?=?new?BufferedReader(isr);
?
?
?
??????????//键盘录入的最常见写法。
?
??????????BufferedReader?bufr?=?new?BufferedReader(new?InputStreamReader(System.in));
?
?
?
????????//??OutputStream?out?=?System.out;
?
????????//??OutputStreamWriter?osw?=?new?OutputStreamWriter(out);
?
????????//??BufferedWriter?bufw?=?new?BufferedWriter(osw);
?
??????????BufferedWriter?bufw?=?new?BufferedWriter(new?OutputStreamWriter(System.out));
?
??????????String?line?=?null;
?
??????????while((line=bufr.readLine())!=null)
?
??????????{
?
?????????????if("over".equals(line))
?
??????????????break;
?
?????????????bufw.write(line.toUpperCase());
?
?????????????bufw.newLine();
?
?????????????bufw.flush();
?
??????????}
?
??????????bufr.close();
?
???????}
?
????}?
?
?
?
?
?
??(2)改变标准的输入输出设备
?
????示例Demo1:
?
????//System.setIn(InputStream?in);???---?改变标准的输入设备
?
????//System.setOut(PrintStream?out);?---?改变标准的输出设备
?
????class??TransStreamDemo2
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException
?
???????{
?
??????????//现将标准的输入和输出设备都换成文件。
?
??????????System.setIn(new?FileInputStream("PersonDemo.java"));
?
??????????System.setOut(new?PrintStream("zzz.txt"));
?
??????????//键盘的最常见写法。
?
??????????BufferedReader?bufr?=?new?BufferedReader(new?InputStreamReader(System.in));??
?
??????????BufferedWriter?bufw?=?new?BufferedWriter(new?OutputStreamWriter(System.out));
?
??????????String?line?=?null;
?
??????????while((line=bufr.readLine())!=null)
?
??????????{
?
?????????????if("over".equals(line))
?
??????????????break;
?
?????????????bufw.write(line.toUpperCase());
?
?????????????bufw.newLine();
?
?????????????bufw.flush();
?
??????????}
?
??????????bufr.close();
?
???????}
?
????}
?
?
?
?
?
?
?
?
?
?
?
?
13、众多IO流对象的选用规律
?
??通过四个步骤来确认完成。
?
??a.明确源和目的。
?
???????源:输入流。InputStream???Reader
?
?????目的:输出流。OutputStream??Writer。
?
??b.操作的数据是否是纯文本。
?
?????是:字符流。
?
?????不是:字节流。
?
??c.明确设备:当体系明确后,再明确要使用哪个具体的对象。
?
??????源设备:内存,硬盘,键盘。
?
????目的设备:内存,硬盘,控制台。
?
??d.是否需要提高效率:
?
????选择使用?:BufferedReader??和??BufferedWriter???
?
?
?
??Demo1需求:复制文件?--?将一个文本文件中数据存储到另一个文件中。
?
???关于源的分析
?
?????a.源:因为是源,所以使用读取流。InputStream?Reader?
?
?????b.是不是操作文本文件。
?
???????是!这时就可以选择Reader
?
???????这样体系就明确了。接下来明确要使用该体系中的哪个对象。
?
?????c.明确设备:硬盘。上一个文件。
?
???????Reader体系中可以操作文件的对象是?FileReader
?
?????d.是否需要提高效率:是!。加入Reader体系中缓冲区?BufferedReader.
?
???????FileReader?fr?=?new?FileReader("a.txt");
?
???????BufferedReader?bufr?=?new?BufferedReader(fr);
?
???关于目的分析
?
?????a.目的:OutputStream?Writer
?
?????b.是否是纯文本。
?
??????是!Writer。
?
?????c.设备:硬盘,一个文件。
?
??????Writer体系中可以操作文件的对象FileWriter。
?
?????d.是否需要提高效率:是!。加入Writer体系中缓冲区?BufferedWriter?
?
???????FileWriter?fw?=?new?FileWriter("b.txt");
?
???????BufferedWriter?bufw?=?new?BufferedWriter(fw);
?
?
?
??Demo2需求:将键盘录入的数据保存到一个文件中。
?
??关于源的分析
?
?????a.源:InputStream?Reader
?
?????b.是不是纯文本?是!Reader?
?
?????c.设备:键盘。对应的对象是System.in.
?
???????不是选择Reader吗?System.in对应的不是字节流吗?
?
???????为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
?
???????所以既然明确了Reader,那么就将System.in转换成Reader。
?
???????用了Reader体系中转换流,InputStreamReader
?
????????InputStreamReader?isr?=?new?InputStreamReader(System.in);
?
?????d.需要提高效率吗?需要!BufferedReader
?
?????BufferedReader?bufr?=?new?BufferedReader(isr);
?
??关于目的分析
?
?????a.目的:OutputStream??Writer
?
?????b.是否是存文本?是!Writer。
?
?????c.设备:硬盘。一个文件。使用?FileWriter。
?
??????FileWriter?fw?=?new?FileWriter("c.txt");
?
?????d.需要提高效率吗?需要。
?
???????BufferedWriter?bufw?=?new?BufferedWriter(fw);?
?
?
?
??Demo3需求:扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
?
??关于目的分析?
?
?????a.目的:OutputStream??Writer
?
?????b.是否是存文本?是!Writer。
?
?????c.设备:硬盘。一个文件。使用?FileWriter。
?
???????可是FileWriter是使用的默认编码表:GBK,而在存储时,需要加入指定编码表utf-8,但指定的编码表只有转换流可以指定。
?
???????所以要使用的对象是OutputStreamWriter。该转换流对象要接收一个字节输出流,那么可以操作文件的字节输出流是:FileOutputStream
?
???????OutputStreamWriter?osw?=?new?OutputStreamWriter(new?FileOutputStream("d.txt"),"UTF-8");
?
?????d.需要高效吗?需要。
?
??????BufferedWriter?bufw?=?new?BufferedWriter(osw);
?
??所以记住:转换流什么时候使用:作为字符和字节之间的桥梁。通常涉及到字符编码转换时,需要用到转换流。
?
?
?
?
?
?
?
?
?
?
?
?
14、保存“异常信息”到日志文件
?
??注:本例仅作思路参考,开发时?大多使用log4j?这个开源的插件。
?
?
?
??示例Demo1:保存异常信息
?
??class??ExceptionInfo
?
??{
?
?????public?static?void?main(String[]?args)throws?IOException?
?
?????{
?
????????try
?
????????{
?
???????????int[]?arr?=?new?int[2];
?
???????????System.out.println(arr[3]);??//会产生数组角标越界的异常
?
????????}
?
????????catch?(Exception?e)
?
????????{???
?
???????????try
?
???????????{
?
????????????Date?d?=?new?Date();
?
????????????SimpleDateFormat?sdf?=?new?SimpleDateFormat("yyyy-MM-dd?HH:mm:ss");
?
????????????String?s?=?sdf.format(d);
?
????????????PrintStream?ps?=?new?PrintStream("exeception.log");
?
????????????ps.println(s);
?
????????????System.setOut(ps);????
?
???????????}
?
???????????catch?(IOException?ex)
?
???????????{
?
????????????throw?new?RuntimeException("日志文件创建失败");??//这是给上一层调用人员使用的
?
???????????}
?
???????????e.printStackTrace(System.out);??//这是将异常的日志信息保存到文件中。
?
????????}
?
?????}
?
??}
?
?
?
??示例Demo2:将系统信息保存到文件中
?
??class??SystemInfo
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????Properties?prop?=?System.getProperties();
?
????????//System.out.println(prop);
?
????????prop.list(new?PrintStream("sysinfo.txt"));
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
?
?
15、File对象的创建、删除、判断、获取等功能。
?
??File对象的作用:
?
????a.用来将文件或者文件夹封装成对象?
?
?????b.方便对文件与文件夹的属性信息进行操作。?
?
?????c.File对象可以作为参数传递给流的构造函数。?
?
?
?
??File类常见方法:
?
????(1)构造方法?
?
??????File(File?parent,?String?child)?
?
????????????根据?parent?抽象路径名和?child?路径名字符串创建一个新?File?实例。?
?
??????File(String?pathname)?
?
????????????通过将给定路径名字符串转换为抽象路径名来创建一个新?File?实例。?
?
??????File(String?parent,?String?child)?
?
????????????根据?parent?路径名字符串和?child?路径名字符串创建一个新?File?实例。?
?
??????File(URI?uri)?
?
????????????通过将给定的?file:?URI?转换为一个抽象路径名来创建一个新的?File?实例。?
?
?
?
????(2)创建。
?
???????boolean?-?createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
?
????????????????????????和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
?
???????boolean?-?mkdir():创建文件夹。
?
???????boolean?-?mkdirs():创建多级文件夹。
?
?
?
????(3)删除。
?
???????boolean?-?delete():删除失败返回false。如果文件正在被使用,则删除不了返回false。
?
??????????void?-?deleteOnExit();在程序退出时删除指定文件。
?
?
?
????(4)判断。
?
???????boolean?-?exists():文件是否存在.
?
???????boolean?-?isFile():测试此抽象路径名表示的文件是否是一个标准文件。
?
???????boolean?-?isDirectory();测试此抽象路径名表示的文件是否是一个目录。
?
???????boolean?-?isHidden();?测试此抽象路径名指定的文件是否是一个隐藏文件。
?
???????boolean?-?isAbsolute();?测试此抽象路径名是否为绝对路径名。
?
?
?
????(5)获取信息。
?
???????String?-?getName():?返回由此抽象路径名表示的文件或目录的名称。
?
???????String?-?getPath():将此抽象路径名转换为一个路径名字符串。
?
???????String?-?getParent():返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回?null。
?
???????String?-?getAbsolutePath():?返回此抽象路径名的绝对路径名字符串。
?
?????????long?-?lastModified():?返回此抽象路径名表示的文件最后一次被修改的时间。
?
?????????long?-?length():?返回由此抽象路径名表示的文件的长度。
?
?
?
??示例Demo:
?
??class?FileDemo?
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????method_5();
?
?????}
?
?????public?static?void?method_5()
?
?????{
?
????????File?f1?=?new?File("c:\\Test.java");
?
????????File?f2?=?new?File("d:\\hahah.java");
?
????????sop("rename:"+f2.renameTo(f1));
?
?????}
?
?????public?static?void?method_4()
?
?????{
?
????????File?f?=?new?File("file.txt");
?
????????sop("path:"+f.getPath());
?
????????sop("abspath:"+f.getAbsolutePath());
?
????????sop("parent:"+f.getParent());//该方法返回的是绝对路径中的父目录。如果获取的是相对路径,返回null。
?
?????????//如果相对路径中有上一层目录那么该目录就是返回结果。
?
?????}???
?
?????public?static?void?method_3()throws?IOException
?
?????{
?
????????File?f?=?new?File("d:\\java1223\\day20\\file2.txt");
?
????????//f.createNewFile();
?
????????//f.mkdir();
?
????????//记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
?
????????//通过exists判断。
?
????????sop("dir:"+f.isDirectory());
?
????????sop("file:"+f.isFile());
?
????????sop(f.isAbsolute());
?
?????}
?
?????public?static?void?method_2()
?
?????{
?
????????File?f?=?new?File("file.txt");
?
????????//sop("exists:"+f.exists());
?
????????//sop("execute:"+f.canExecute());
?
????????//创建文件夹
?
????????File?dir?=?new?File("abc\\kkk\\a\\a\\dd\\ee\\qq\\aaa");
?
????????sop("mkdir:"+dir.mkdirs());
?
?????}
?
?????public?static?void?method_1()throws?IOException
?
?????{
?
????????File?f?=?new?File("file.txt");
?
????????//sop("create:"+f.createNewFile());
?
????????//sop("delete:"+f.delete());??
?
?????}
?
?????//创建File对象
?
?????public?static?void?consMethod()
?
?????{
?
????????//将a.txt封装成file对象。可以将已有的和为出现的文件或者文件夹封装成对象。
?
????????File?f1?=?new?File("a.txt");
?
????????//
?
????????File?f2?=?new?File("c:\\abc","b.txt");
?
????????File?d?=?new?File("c:\\abc");
?
????????File?f3?=?new?File(d,"c.txt");
?
????????sop("f1:"+f1);
?
????????sop("f2:"+f2);
?
????????sop("f3:"+f3);
?
????????File?f4?=?new?File("c:"+File.separator+"abc"+File.separator+"zzz"+File.separator+"a.txt");
?
?????}
?
?????public?static?void?sop(Object?obj)
?
?????{
?
????????System.out.println(obj);
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
16、File对象?————?实现文件列表功能常用方法
?
??能够实现文件列表的一些方法与接口:
?
????(1)File[]?listFiles():?返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。?
?
?
?
????(2)String[]?listFiles(FilenameFilter?filter)?
?
????????返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。?
?
????????FilenameFilter接口的知识
?
????????接口:java.io.FilenameFilter?:实现此接口的类实例可用于过滤器文件名,
?
????????方法:boolean?accept(File?dir,String?name):测试指定文件是否应该包含在某一文件列表中。?
?
????????????参数:dir?-?被找到的文件所在的目录。
?
????????????????name?-?文件的名称。?
?
????????????返回:当且仅当该名称应该包含在文件列表中时返回?true;否则返回?false。
?
?
?
????(3)String[]?list():返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。?
?
?
?
????(4)static?File[]?listRoots():列出可用的文件系统根。?
?
?
?
?
?
??示例Demo:
?
??class??FileDemo2
?
??{
?
????//?使用?File[]?listFiles()方法
?
?????public?static?void?main(String[]?args)?
?
?????{
?
????????File?dir?=?new?File("c:\");
?
????????File[]?files?=?dir.listFiles();
?
????????for(File?f?:?files)
?
????????{
?
???????????System.out.println(f.getName()+"::"+f.length());
?
????????}??
?
?????}
?
?????//?使用?String[]?listFiles(FilenameFilter?filter)?方法
?
?????public?static?void?listDemo_2()??
?
?????{
?
????????File?dir?=?new?File("d:\\java1223\\day18");
?
????????String[]?arr?=?dir.list(new?FilenameFilter()
?
????????{
?
???????????public?boolean?accept(File?dir,String?name)
?
???????????{
?
????????????//System.out.println("dir:"+dir+"....name::"+name);
?
????????????/*
?
????????????if(name.endsWith(".bmp"))
?
???????????????return?true;
?
????????????else
?
??????????????return?false;
?
????????????*/
?
????????????return?name.endsWith(".bmp");
?
???????????}
?
????????});
?
?
?
????????System.out.println("len:"+arr.length);
?
????????for(String?name?:?arr)
?
????????{
?
???????????System.out.println(name);
?
????????}
?
?????}
?
?????//?使用?String[]?list()方法
?
?????public?static?void?listDemo()???
?
?????{
?
????????File?f?=?new?File("c:\\abc.txt");
?
????????String[]?names?=?f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
?
????????for(String?name?:?names)
?
????????{
?
???????????System.out.println(name);
?
????????}
?
?????}
?
?????//?使用static?File[]?listRoots()方法
?
?????public?static?void?listRootsDemo()???
?
?????{
?
????????File[]?files?=?File.listRoots();
?
????????for(File?f?:?files)
?
????????{
?
???????????System.out.println(f);
?
????????}
?
?????}
?
??}
?
?
?
?
?
?
?
?
17、File对象?——?操作?文件列表/目录
?
??(1)列出目录下所有内容——递归方法(含带层次展现)
?
????需求分析:列出指定目录下文件或者文件夹,包含子目录中的内容,也就是列出指定目录下所有内容。因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。
?
????递归算法:这种函数自身调用自身的表现形式,或者编程手法,称为递归。
?
????递归要注意:a.限定条件。
?
??????????b.要注意递归的次数,尽量避免内存溢出。
?
????示例Demo:
?
????class?FileDemo3?
?
????{
?
???????public?static?void?main(String[]?args)?
?
???????{
?
??????????File?dir?=?new?File("d:\\testdir");
?
??????????showDir(dir,0);
?
?
?
??????????System.out.println(dir.delete());
?
???????}
?
???????//根据文件所在层级书写层标“|--”
?
???????public?static?String?getLevel(int?level)
?
???????{
?
??????????StringBuilder?sb?=?new?StringBuilder();
?
??????????sb.append("|--");
?
??????????for(int?x=0;?x<level;?x++)
?
??????????{
?
?????????????//sb.append("|--");
?
?????????????sb.insert(0,"|??");
?
??????????}
?
??????????return?sb.toString();
?
???????}
?
??????//采用递归算法,列出所有?Java文件列表
?
???????public?static?void?showDir(File?dir,int?level)
?
???????{
?
?
?
??????????System.out.println(getLevel(level)+dir.getName());
?
??????????level++;
?
??????????File[]?files?=?dir.listFiles();
?
??????????for(int?x=0;?x<files.length;?x++)
?
??????????{
?
?????????????if(files[x].isDirectory())
?
??????????????showDir(files[x],level);
?
?????????????else
?
??????????????System.out.println(getLevel(level)+files[x]);
?
??????????}
?
???????}??????
?
????}
?
?
?
??(2)删除带内容的目录
?
????删除原理:在window中,删除目录从里面往外删除的。既然是从里往外删除,就需要用到递归。??
?
????示例Demo:
?
????class??RemoveDir
?
????{
?
???????public?static?void?main(String[]?args)?
?
???????{??
?
??????????File?dir?=?new?File("d:\\testdir");
?
??????????removeDir(dir);
?
???????}
?
???????public?static?void?removeDir(File?dir)
?
???????{
?
??????????File[]?files?=?dir.listFiles();??
?
??????????for(int?x=0;?x<files.length;?x++)
?
??????????{
?
?????????????if(files[x].isDirectory())
?
??????????????removeDir(files[x]);
?
?????????????else
?
??????????????System.out.println(files[x].toString()+":-file-:"+files[x].delete());
?
??????????}
?
??????????System.out.println(dir+"::dir::"+dir.delete());
?
???????}
?
????}?
?
?
?
??(3)创建展现多层级的Java文件列表并输出到文件
?
????需求:将一个指定目录下的java文件的绝对路径,存储到一个文本文件中,建立一个java文件列表文件。
?
????思路:
?
??????a.对指定的目录进行递归。
?
??????b.获取递归过程所以的java文件的路径。
?
??????c.将这些路径存储到集合中。
?
??????d.将集合中的数据写入到一个文件中。
?
????示例Demo:
?
????class??JavaFileList
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException
?
???????{??
?
??????????File?dir?=?new?File("d:\\java1223");
?
??????????List<File>?list?=?new?ArrayList<File>();
?
??????????fileToList(dir,list);
?
??????????//System.out.println(list.size());
?
??????????File?file?=?new?File(dir,"javalist.txt");
?
??????????writeToFile(list,file.toString());
?
???????}
?
???????public?static?void?fileToList(File?dir,List<File>?list)
?
???????{
?
??????????File[]?files?=?dir.listFiles();
?
??????????for(File?file?:?files)
?
??????????{
?
?????????????if(file.isDirectory())
?
??????????????fileToList(file,list);
?
?????????????else
?
?????????????{
?
??????????????if(file.getName().endsWith(".java"))
?
?????????????????list.add(file);
?
?????????????}
?
??????????}
?
???????}
?
???????public?static?void?writeToFile(List<File>?list,String?javaListFile)throws?IOException
?
???????{
?
??????????BufferedWriter?bufw?=??null;
?
??????????try
?
??????????{
?
?????????????bufw?=?new?BufferedWriter(new?FileWriter(javaListFile));???
?
?????????????for(File?f?:?list)
?
?????????????{
?
??????????????String?path?=?f.getAbsolutePath();
?
??????????????bufw.write(path);
?
??????????????bufw.newLine();
?
??????????????bufw.flush();
?
?????????????}
?
??????????}
?
??????????catch?(IOException?e)
?
??????????{
?
???????????throw?e;
?
??????????}
?
??????????finally
?
??????????{
?
?????????????try
?
?????????????{
?
??????????????if(bufw!=null)
?
?????????????????bufw.close();
?
?????????????}
?
?????????????catch?(IOException?e)
?
?????????????{
?
??????????????throw?e;
?
?????????????}
?
??????????}
?
???????}
?
????}
?
?
?
?
?
?
?
?
18、Properties??存取配置文件
?
??Properties是hashtable的子类,也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串,是集合中与IO技术相结合的集合容器。
?
??该对象的特点:可以用于键值对形式的配置文件。
?
??那么在加载数据时,需要数据有固定格式:键=值。
?
?
?
??示例Demo:
?
??class?PropertiesDemo?
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????//method_1();
?
????????loadDemo();
?
?????}
?
?
?
?????//这是?读取?properties?类型配置文件?最标准的?流程,可以直接在开发中应用。
?
?????public?static?void?loadDemo()throws?IOException
?
?????{
?
????????Properties?prop?=?new?Properties();
?
????????FileInputStream?fis?=?new?FileInputStream("info.txt");
?
????????//将流中的数据加载进集合。
?
????????prop.load(fis);
?
????????//取出属性值的操作
?
????????String?value?=?prop.getProperty("lisi");
?
????????//该从配置文件中读取的“lisi”?的?属性值,就可以被我们使用了。
?
?
?
????????//给属性赋值的操作。
?
????????prop.setProperty("wangwu","39");
?
????????//将修改过属性值的集合?重新写回配置文件中:更新
?
????????FileOutputStream?fos?=?new?FileOutputStream("info.txt");
?
????????prop.store(fos,"haha");
?
????????//?System.out.println(prop);
?
????????prop.list(System.out);
?
????????fos.close();
?
????????fis.close();??????
?
????}
?
?
?
?
?
?????//下面演示,自定义方法:将流中的数据存储到集合中。
?
?????//想要将info.txt中键值数据存到集合中进行操作。
?
?????/*
?
??????1,用一个流和info.txt文件关联。
?
??????2,读取一行数据,将该行数据用"="进行切割。
?
??????3,等号左边作为键,右边作为值。存入到Properties集合中即可。
?
?????*/
?
?????public?static?void?method_1()throws?IOException
?
?????{
?
????????BufferedReader?bufr?=?new?BufferedReader(new?FileReader("info.txt"));
?
????????String?line?=?null;
?
????????Properties?prop?=?new?Properties();
?
????????while((line=bufr.readLine())!=null)
?
????????{
?
???????????String[]?arr?=?line.split("=");
?
???????????///System.out.println(arr[0]+"...."+arr[1]);
?
???????????prop.setProperty(arr[0],arr[1]);
?
????????}
?
????????bufr.close();
?
????????System.out.println(prop);
?
?????}
?
????//?设置和获取元素。
?
?????public?static?void?setAndGet()
?
?????{
?
????????Properties?prop?=?new?Properties();
?
????????prop.setProperty("zhangsan","30");
?
????????prop.setProperty("lisi","39");
?
??????//??System.out.println(prop);
?
????????String?value?=?prop.getProperty("lisi");
?
????????//System.out.println(value);???
?
????????prop.setProperty("lisi",89+"");
?
????????Set<String>?names?=?prop.stringPropertyNames();
?
????????for(String?s?:?names)
?
????????{
?
???????????System.out.println(s+":"+prop.getProperty(s));
?
????????}
?
?????}?
?
??}
?
?
?
?
?
?
?
?
19、PrintStream?以及?PrintWriter
?
??打印流:该流提供了打印方法,可以将各种数据类型的数据都原样打印。
?
??PrintStream?-?字节打印流:
?
????构造函数可以接收的参数类型:
?
??????a.file对象。File??---------?PrintStream(File?file)?
?
??????b.字符串路径。String??-----?PrintStream(String?fileName)?
?
??????c.字节输出流。OutputStream??PrintStream(OutputStream?out)?
?
?
?
??PrintWriter?-?字符打印流
?
????构造函数可以接收的参数类型:
?
??????a.file对象。File??-----------?PrintWriter(File?file)?
?
??????b.字符串路径。String??-------?PrintWriter(String?fileName)?
?
??????c.字节输出流。OutputStream?--?PrintWriter(OutputStream?out)?
?
??????d.字符输出流,Writer。??-----?PrintWriter(Writer?out)?
?
??【备注:在构造函数中可以?添加?true/false,?以代表是否需要自动刷新。】
?
??示例Demo:
?
??class??PrintStreamDemo
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????BufferedReader?bufr?=?
?
???????????new?BufferedReader(new?InputStreamReader(System.in));
?
????????PrintWriter?out?=?new?PrintWriter(new?FileWriter("a.txt"),true);
?
????????String?line?=?null;??????????????//自动刷新
?
????????while((line=bufr.readLine())!=null)
?
????????{
?
???????????if("over".equals(line))
?
??????????break;
?
???????????out.println(line.toUpperCase());??//自带平台适应的行分隔符(等同于换行符)
?
???????????//out.flush();
?
????????}
?
????????out.close();
?
????????bufr.close();
?
?????}?
?
??}
?
?
?
?
?
?
?
?
?
?
?
?
20、文件的?切割操作
?
??示例Demo:
?
??@Test
?
???public?static?void?splitFile()throws?IOException
?
???{
?
??????FileInputStream?fis?=??new?FileInputStream("c:\\1.bmp");
?
??????FileOutputStream?fos?=?null;
?
??????byte[]?buf?=?new?byte[1024*1024];??//切割后每份的大小。
?
??????int?len?=?0;
?
??????int?count?=?1;
?
??????while((len=fis.read(buf))!=-1)
?
??????{
?
?????????fos?=?new?FileOutputStream("c:\\splitfiles\"+(count++)+".part");
?
?????????fos.write(buf,0,len);
?
?????????fos.close();
?
??????}??
?
??????fis.close();??
?
???}
?
?
?
?
?
?
?
?
21、文件的合并操作?-----??SequenceInputStream?合并文件
?
??SequenceInputStream:表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。?
?
??构造方法:SequenceInputStream(Enumeration<??extends?InputStream>?e)?
?
????通过记住参数来初始化新创建的?SequenceInputStream,该参数必须是生成运行时类型为?InputStream?对象的?Enumeration?型参数。
?
?
?
??SequenceInputStream?的两种装载方式:
?
??????a.?Vector方式:操作方便,但是效能远低于ArrayList。
?
??????b.?ArrayList方式:操作稍显麻烦,但是ArrayList的性能要比Vector高很多。
?
?
?
??示例Demo:??
?
??//第一种?SequenceInputStream?的装载方式?————??Vector
?
??@Test
?
???public?static?void?merge1()?throws?IOException
?
???{
?
??????Vector<FileInputStream>?v?=?new?Vector<FileInputStream>();??
?
???????v.add(new?FileInputStream("c:\\1.txt"));
?
???????v.add(new?FileInputStream("c:\\2.txt"));
?
???????v.add(new?FileInputStream("c:\\3.txt"));
?
??????Enumeration<FileInputStream>?en?=?v.elements();//仅Vector结合对象能得到Enumeration类型。
?
??????SequenceInputStream?sis?=?new?SequenceInputStream(en);??//将多个文本的输入流?组装到SequenceInputStream中
?
??????FileOutputStream?fos?=?new?FileOutputStream("c:\\4.txt");
?
??????byte[]?buf?=?new?byte[1024];
?
??????int?len?=0;
?
??????while((len=sis.read(buf))!=-1)??//把?SequenceInputStream?当作一个?普通输入流?读取数据。
?
??????{
?
?????????fos.write(buf,0,len);
?
??????}
?
??????fos.close();
?
??????sis.close();
?
???}
?
?
?
??//第二种?SequenceInputStream?的装载方式??————??ArrayList
?
??@Test
?
???public?static?void?merge2()throws?IOException
?
???{
?
??????ArrayList<FileInputStream>?al?=?new?ArrayList<FileInputStream>();
?
??????for(int?x=1;?x<=3;?x++)
?
??????{
?
?????????al.add(new?FileInputStream("c:\\splitfiles\"+x+".part"));
?
??????}
?
??????final?Iterator<FileInputStream>?it?=?al.iterator();
?
?
?
?????//将?it?装载入?Enumeration?里面
?
??????Enumeration<FileInputStream>?en?=?new?Enumeration<FileInputStream>()
?
??????{
?
?????????public?boolean?hasMoreElements()
?
?????????{
?
??????????return?it.hasNext();
?
?????????}
?
?????????public?FileInputStream?nextElement()
?
?????????{
?
??????????return?it.next();
?
?????????}
?
??????};
?
??????//上面的文件合并功能实现方式?若稍显麻烦(但是ArrayList的性能要比Vector高很多),
?
??????//?可以参见“#SquenceInputSteam?合并文件”?中的演示。
?
??????SequenceInputStream?sis?=?new?SequenceInputStream(en);
?
??????FileOutputStream?fos?=?new?FileOutputStream("c:\\splitfiles\\0.bmp");
?
??????byte[]?buf?=?new?byte[1024];
?
??????int?len?=?0;
?
??????while((len=sis.read(buf))!=-1)
?
??????{
?
???????fos.write(buf,0,len);
?
??????}
?
??????fos.close();
?
??????sis.close();
?
???}
?
?
?
?
?
?
?
?
?
?
?
?
22、对象的序列化:ObjectOutputStream?和反序列化:ObjectInputStream????
?
??ObjectOutputStream
?
????作用:可将对象写入流中(对象类需实现Serializable接口);
?
????????也可将?Java?对象的基本数据类型和图形写入?OutputStream。????
?
??ObjectInputStream?对以前使用?ObjectOutputStream?写入的基本数据和对象进行反序列化。?
?
?
?
??示例Demo:
?
??class?ObjectStreamDemo?
?
??{
?
?????public?static?void?main(String[]?args)?throws?Exception
?
?????{
?
????????//writeObj();
?
????????readObj();
?
?????}
?
?????public?static?void?readObj()throws?Exception
?
?????{
?
????????ObjectInputStream?ois?=?new?ObjectInputStream(new?FileInputStream("obj.txt"));
?
????????Person?p?=?(Person)ois.readObject();??//该Person类必须是实现了Serializable?接口
?
????????System.out.println(p);
?
????????ois.close();
?
?????}
?
?????public?static?void?writeObj()throws?IOException
?
?????{
?
????????ObjectOutputStream?oos?=?new?ObjectOutputStream(new?FileOutputStream("obj.txt"));
?
????????oos.writeObject(new?Person("lisi0",399,"kr"));??//将对象保存到硬盘文件"obj.txt"?中。
?
????????oos.close();??????//该Person类必须是实现了Serializable?接口
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
23、RandomAccessFile?随机读写访问文件
?
??RandomAccessFile:该类不是算是IO体系中子类,而是直接继承自Object,但是它是IO包中成员,因为它具备读和写功能。其内部封装了一个数组,而且通过指针对数组的元素进行操作。
?
??我们可以通过getFilePointer()获取指针位置,同时可以通过seek()改变指针的位置,其实完成读写的原理就是内部封装了字节输入流和输出流。
?
??【备注:可实现多线程并发读写同一文件:如迅雷技术。】
?
??构造函数:
?
????RandomAccessFile(File?file,?String?mode)?
?
??????????创建从中读取和向其中写入(可选)的随机访问文件流,该文件由?File?参数指定。?
?
????RandomAccessFile(String?name,?String?mode)?
?
??????????创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称。?
?
??????mode?参数指定用以打开文件的访问模式。允许的值及其含意为:
?
????????值??????含意???????
?
????????"r"?????以只读方式打开。调用结果对象的任何?write?方法都将导致抛出?IOException。??
?
????????"rw"????打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。??
?
?
?
??通过构造函数可以看出,该类只能操作文件,而且操作文件还有模式:只读r,读写rw等。
?
????如果模式为只读?r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
?
????如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖。
?
?
?
??示例Demo:
?
??class?RandomAccessFileDemo?
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????//writeFile_2();
?
????????//readFile();
?
????????//System.out.println(Integer.toBinaryString(258));
?
?????}
?
?????//测试打开一个只读的RandomAccessFile对象
?
?????public?static?void?readFile()throws?IOException
?
?????{
?
????????RandomAccessFile?raf?=?new?RandomAccessFile("ran.txt","r");??
?
????????//调整对象中指针。
?
????????//raf.seek(8*1);????//注:该方法不但能向后跳,还能再跳回来。
?
????????//跳过指定的字节数
?
????????raf.skipBytes(8);????//注:该方法仅能向后跳,不能再跳回来。
?
????????byte[]?buf?=?new?byte[4];
?
????????raf.read(buf);
?
????????String?name?=?new?String(buf);
?
????????int?age?=?raf.readInt();
?
????????System.out.println("name="+name);
?
????????System.out.println("age="+age);
?
????????raf.close();
?
?
?
?????}
?
?????//测试打开一个?可读也可写的RandomAccessFile对象
?
?????public?static?void?writeFile_2()throws?IOException
?
?????{
?
????????RandomAccessFile?raf?=?new?RandomAccessFile("ran.txt","rw");
?
????????raf.seek(8*0);??//读取数据
?
????????raf.write("周期".getBytes());??//写入数据
?
????????raf.writeInt(103);
?
????????raf.close();
?
?????}
?
????//测试写入数据?
?
?????public?static?void?writeFile()throws?IOException
?
?????{
?
????????RandomAccessFile?raf?=?new?RandomAccessFile("ran.txt","rw");
?
????????raf.write("李四".getBytes());????//写入字节数据?
?
????????raf.writeInt(97);????//写入整型数据?
?
????????raf.write("王五".getBytes());
?
????????raf.writeInt(99);
?
????????raf.close();
?
?????}
?
??}
?
?
?
?
?
?
?
?
24、操作基本数据类型?DataInputStream与DataOutputStream
?
??DataInputStream与DataOutputStream?可以用于操作基本数据类型的数据的流对象,减少字节位数?转换的麻烦。
?
?
?
??示例Demo:
?
??class?DataStreamDemo?
?
??{
?
?????public?static?void?main(String[]?args)?throws?IOException
?
?????{
?
????????//writeData();
?
????????//readData();
?
????????//writeUTFDemo();
?
??????//??OutputStreamWriter?osw?=?new?OutputStreamWriter(new?FileOutputStream("gbk.txt"),"gbk");
?
??????//??osw.write("你好");
?
??????//??osw.close();
?
??????//??readUTFDemo();
?
?????}
?
?????public?static?void?readUTFDemo()throws?IOException
?
?????{
?
????????DataInputStream?dis?=?new?DataInputStream(new?FileInputStream("utf.txt"));
?
????????String?s?=?dis.readUTF();??//读入一个已使用?UTF-8?修改版格式编码的字符串。
?
????????System.out.println(s);
?
????????dis.close();
?
?????}
?
?????public?static?void?writeUTFDemo()throws?IOException
?
?????{
?
????????DataOutputStream?dos?=?new?DataOutputStream(new?FileOutputStream("utfdate.txt"));
?
????????dos.writeUTF("你好");//将表示长度信息的两个字节写入输出流,后跟字符串?s?中每个字符的?UTF-8?修改版表示形式。
?
????????dos.close();
?
?????}
?
?????public?static?void?readData()throws?IOException
?
?????{
?
????????DataInputStream?dis?=?new?DataInputStream(new?FileInputStream("data.txt"));
?
????????int?num?=?dis.readInt();??????//?读取?int?类型的数据
?
????????boolean?b?=?dis.readBoolean();??//?读取布尔类型的数据
?
????????double?d?=?dis.readDouble();????//?读取双精度类型的数据
?
????????System.out.println("num="+num);
?
????????System.out.println("b="+b);
?
????????System.out.println("d="+d);
?
????????dis.close();
?
?????}
?
?????public?static?void?writeData()throws?IOException
?
?????{
?
????????DataOutputStream?dos?=?new?DataOutputStream(new?FileOutputStream("data.txt"));
?
????????dos.writeInt(234);??//写入?int?类型的数据
?
????????dos.writeBoolean(true);//写入布尔类型的数据
?
????????dos.writeDouble(9887.543);//?写入双精度类型的数据
?
????????dos.close();
?
????????ObjectOutputStream?oos?=?null;
?
????????oos.writeObject(new?O());??//写入对象数据
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
?
?
25、ByteArrayStream?操作字节数组的流对象。
?
??用于操作字节数组的流对象。
?
????ByteArrayInputStream?:?在构造的时候,需要接收数据源,而且数据源是一个字节数组。
?
????ByteArrayOutputStream:?在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。这就是数据目的地。
?
??因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭。
?
??在流操作规律讲解时:
?
????源设备,
?
??????键盘?System.in,硬盘?FileStream,内存?ArrayStream。
?
????目的设备:
?
??????控制台?System.out,硬盘FileStream,内存?ArrayStream。
?
????用流的读写思想来操作数据。
?
?
?
??示例Demo:
?
??class?ByteArrayStream?
?
??{
?
?????public?static?void?main(String[]?args)?
?
?????{
?
????????//数据源。
?
????????ByteArrayInputStream?bis?=?new?ByteArrayInputStream("ABCDEFD".getBytes());
?
????????//数据目的
?
????????ByteArrayOutputStream?bos?=?new?ByteArrayOutputStream();
?
????????int?by?=?0;
?
????????while((by=bis.read())!=-1)
?
????????{
?
???????????bos.write(by);
?
????????}
?
????????System.out.println(bos.size());
?
????????System.out.println(bos.toString());
?
???????//?bos.writeTo(new?FileOutputStream("a.txt"));
?
?????}
?
??}
?
?
?
?
?
?
?
?
?
?
26、字符的编码和解码
?
??编码:字符串变成字节数组:String-->byte[];??str.getBytes(charsetName);
?
??解码:字节数组变成字符串:byte[]?-->String:?new?String(byte[],charsetName);
?
??(1)编码?和?解码?的练习
?
????示例Demo:
?
????class??EncodeDemo
?
????{
?
???????public?static?void?main(String[]?args)throws?Exception?
?
???????{
?
??????????String?s?=?"哈哈";
?
??????????byte[]?b1?=?s.getBytes("GBK");
?
??????????System.out.println(Arrays.toString(b1));
?
??????????String?s1?=?new?String(b1,"utf-8");
?
??????????System.out.println("s1="+s1);
?
??????????//对s1进行iso8859-1编码。
?
??????????byte[]?b2?=?s1.getBytes("utf-8");
?
??????????System.out.println(Arrays.toString(b2));
?
??????????String?s2?=?new?String(b2,"gbk");
?
??????????System.out.println("s2="+s2);
?
???????}
?
????}
?
?
?
??(2)转换流的字符编码
?
????示例Demo:
?
????class?EncodeStream?
?
????{
?
???????public?static?void?main(String[]?args)?throws?IOException?
?
???????{
?
???????????//writeText();
?
???????????readText();
?
???????}
?
???????public?static?void?readText()throws?IOException?
?
???????{
?
??????????InputStreamReader?isr?=?new?InputStreamReader(new?FileInputStream("utf.txt"),"gbk");
?
??????????char[]?buf?=?new?char[10];
?
??????????int?len?=?isr.read(buf);
?
??????????String?str?=?new?String(buf,0,len);
?
??????????System.out.println(str);
?
??????????isr.close();
?
???????}
?
???????public?static?void?writeText()throws?IOException?
?
???????{
?
??????????OutputStreamWriter?osw?=?new?OutputStreamWriter(new?FileOutputStream("utf.txt"),"UTF-8");
?
??????????osw.write("你好");
?
??????????osw.close();
?
???????}
?
????}
?
?
?
?
?
附图片:?编码1.jpg??和?编码2.jpg
?
?
?
编码1.jpg??
?
?
?
?
?
编码2.jpg?
?
IO流??学习笔记
?
?
?
?
?
?
?
?
?
???
?
?
?
?
?
?
?