【黑马程序员】java中---------------IO流

来源:互联网 发布:js的id命名规范 编辑:程序博客网 时间:2024/05/29 04:51

---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------





一、IO流

1、IO流是用来处理设备之间的数据传输

2、java对数据的操作是通过流的方式

3、java用于操作流的对象都在IO包中

4、流按操作数据分为两种:字节流与字符流

5、流按流向分为:输出流与输入流


A、字符流体系

基类:Reader-----InputStreamReader字节转字符的读取流-------FileReader字符读取流

|----BufferedReader字符缓冲区---------LineNumberReader基于缓冲区的行号读取流

|-----CharArrayReader字符输入流的字符缓冲区

|-----FilterReader用于读取已过滤的字符流的抽象类--------PashbackReader

|-----PipedReader字符管道读取流

|-----StringReader字符串读取流

基类:Writer

|----FileWriter字符文件输出流

|--BufferedWriter字符缓冲输出
|----OutStreamWriter字符转换输出
|----PipedWriter 字符管道输出
|----PrintWriter 字符文本打印输出
|----StringWriter字符串输出
|----CharArrayWriter字符数组输出

B、字节流体系

基类:InputStream

|----FileInputStream字节文件读取流

|----ObjectInputStream反序列化读取流

|----FilterInputStream过滤流

|----BufferedInputStream字节缓冲读取流

|----DataInputStream基本数据字节读取流

|----PipedInputStream字节管道读取流

|----SequenceInputStream合并字节流。没有与之相对应的输出流

|----ByteArrayInputStream字节数组读取流

基类:OutputStream

|----FileOutputStream字节文件输出

|----ObjectOutputStream序列化输出

|----FilterOutputStream过滤流

|----BufferedOutputStream字节缓冲输出

|----DataOutputStream基本数据字节输出

|----PrintStream字节打印流

|----PipedOutputStream字节管道输出

|----ByteArrayOutputStream字节数组输出


二、缓冲技术
1、字节流当中:BufferedInputStream读取流缓冲技术,它的内部封装了byte[]字节数组
  BufferedOutputStream输出流缓冲技术,要注意的是:flush()刷新
2、字符流中:

BufferedReader读取流缓冲技术,内部封装了数组

特有方法:readLine()方法,一次读一行


BufferWriter输出流缓冲技术,

特有方法:newLine()换行方法

flush()刷新方法

三、转换流

1、字节向字符流的转换:InputStreamReader类:InputStreamReader(InputStream in)

其次还可以指定字符编码的功能:InputStreamReader(InputStream in,String charsetName) 创建使用指定字符集的 InputStreamReader。

2、字符转换成字节流:OuputStreamWriter类:OutputStreamWriter(OutputStream out)

其次还可以指定字符编码的功能:OutputStreamWriter(OutputStream out,String charsetName)  创建使用指定字符集的 OutputStreamWriter。

四、输出流对象的续写功能
1、FileOutputStream类中,构造函数FileOutputStream(String name, boolean append)
       第一个参数:接收字符串文件名
第二个参数:接收一个布尔型值,为真,就在文件末尾处继续写入数据,
2、FileWriter类中,构造函数FileWriter(String fileName, boolean append)
第一个参数:接收字符串文件名
第二个参数:接收一个布尔型值,为真,就在文件末尾处继续写入数据,

五、只有BufferedReader类中,readLine()一次读一行的方法
子类LineNumberReader类中,getLineNumber()获取行号方法和setLineNumber()设置行号方法

a、为了了解他的原理:来自定义MyBufferedReader类,模拟readLine()方法
/*装饰设计模式:装饰的类和被装饰的类通常同属一个体系中,同属一个父类或者接口定义:当想对已有的对象进行功能增强时,可以定义类,将已有的对象传入,基于已有的功能,  并提供加强功能,那么自定义类称为装饰类模拟ReadLine()方法,一次读一行abstract  int read(char[] cbuf, int off, int len)           将字符读入数组的某一部分。 abstract  void close()           关闭该流并释放与之关联的所有资源。 */import java.io.*;//用到装饰设计模式,继承Reader基类class  myBufferedReader extends Reader{private Reader r;myBufferedReader(Reader r){this.r=r;}//自定义一个myReaderLine()方法public String myReadLine()throws IOException{//定义一临时容器.StringBuilderStringBuilder sb=new StringBuilder();int ch=0;//调用父类的read()方法while((ch=r.read())!=-1){if(ch=='\r')continue;if(ch=='\n')return sb.toString();elsesb.append((char)ch);}if(sb.length()!=0)//如果已读数据没有\r\n需要判断,return sb.toString();return null;}public void myClose()throws IOException{r.close();}//复写父类的两个抽象方法public int read(char[] cbuf, int off, int len)throws IOException{return r.read(cbuf, off,len);}public void close()throws IOException{r.close();}}class myReaderLineDemo_1{public static void main(String[] args)throws IOException{FileReader fr=new FileReader("buff.txt");myBufferedReader myBuf=new myBufferedReader(fr);String line=null;while((line=myBuf.myReadLine())!=null){System.out.println(line);}myBuf.myClose();}}

b、自己定义一个MyLineNumberReader类,模拟getLineNumber(),setLineNumber()方法
/*装饰设计模式:MyLineNumber继承myBufferedReader类增强功能,myLineNumber()方法Reader类----|---BufferedReader类|------LineNumberReader类   方法:getlineNumber();  setLineNumber()|------自定义增强类;myBufferReader类   方法:myReadLine();|-------------自定义增强类:MyLineNumberReader类  复写方法:myReadLine();特有:setLineNumber();特有:getLineNumber();*/import java.io.*;class MyLineNumberReader extends myBufferedReader{private int lineNumber;//构造函数传父类,多态MyLineNumberReader(Reader r){//引用父类的构造函数super(r);}public String myReadLine()throws IOException{lineNumber++;//引用父类的myReaderLine()方法return super.myReadLine();}public int getLineNumber(){return lineNumber;}public void setLineNumber(int lineNumber){this.lineNumber=lineNumber;}}class MyLineNumberReaderDemo_2{public static void main(String[] args)throws IOException{FileReader fr=new FileReader("FileWriterDemo2.java");MyLineNumberReader mlnr=new MyLineNumberReader(fr);String line=null;while((line=mlnr.myReadLine())!=null){System.out.println(mlnr.getLineNumber()+":"+line);}mlnr.myClose();}}

六、装饰设计模式
1、定义:当想对已经有的对象进行功能增强时,就可以定义一个类,将已有的对象传入
基于已有的功能,并提供加强的功能,那么这个自定义的类称为装饰类
通常装饰类会通过构造函数接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能

2、其实,LineNumberReaders类和BufferedReader类 都是装饰类,
装饰类与被装饰的类通常属于一个体系中,同属于一个父类或者接口

3、  比方说我们现在有一个专门读取数据的类MyReader它的继承体系如下:

MyReader

|--MyTextReader 用于操作文本文件的类

       |--MyBufferTextReader用来缓冲操作文本文件的类

|--MyMediaReader 用于操作媒体文件的类

       |--MyBufferMediaReader用来缓冲操作媒体文件的类

|--MyDataReader 用于操作数据的类

       |--MyBufferDataReader用来缓冲操作数据文件的类

如果运用装饰设计模式:这个继承体系更简单,

MyReader

|--MyTextReader 用于操作文本文件的类

|--MyMediaReader 用于操作媒体文件的类

|--MyDataReader 用于操作数据的类

|--MyBufferReader用来缓冲操作数据文件的类,只剩下这一个类了。


七、读取键盘录入
1、
/*读取键盘录入:父类:OutputStream |--FilterOutputStream|-->PrintStream<----返回    Sysrem.out:对应的的标准的输出设备,控制台InputStream <--返回    System.in:对应的是标准的输入设备:键盘需求:通过键盘录入数据1,当录入以后数据后,就将该数据进行打印2,如果录入的数据是over,那么就停止录入*/import java.io.*;class ReadIn{public static void main(String[] args)throws IOException{InputStream in=System.in;//readIn(in);readIn( in);}/*第一种读取键盘录入的方式思路:1.接收一个键盘录入返回的InputStream字节流对象,  2.建立一个StringBuileder容器(相当于缓冲区),调用字节流中read()方法,  将每次读取一个字节,存放进容器中  3,。再将容器中的数据转化成大写打印,每次打印完需要清空容器  */public static void readIn(InputStream in)throws IOException{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());}elsesb.append((char)ch);}}/*第二种方式:转换流的应用:思路:1.将键盘录入返回的字节流InputStream对象  2.通过转换流:InputStreamReader类,将其转换成字符流,  3.再通过建立BufferedReader类对象,字符缓冲技术,接收字符流  4.使用:缓冲区中readLine()方法,一次读一行的方法*/public static void ReadLineDemo(InputStream in)throws IOException{//将字节流转换成字符流,InputStreamReader类,InputStreamReader isr=new InputStreamReader(in);//为了提高效率,将字符流 进行缓冲区技术高效操作,用缓冲区BufferedReader类BufferedReader bufr=new BufferedReader(isr);String line=null;while((line=bufr.readLine())!=null){if("over".equals(line))break;String s=line.toUpperCase();System.out.println(s);}bufr.close();}}
标准的键盘录入和标准的输出设备:
/*字节流转换字符流在InputStream中,键盘录入的方法是read()而在Reader类中 1,BufferedReader子类中才有readLIine()方法2,子类InputStreamReader是字节流通向字符流的桥梁,*/import java.io.*;class zhuanHuanLiu{public static void main(String[] args)throws IOException{//获取键盘录入InputStream in=System.in;//将字节流对象转换成字符流对象,InputStreamReader类InputStreamReader isr=new InputStreamReader(in);//为了提高效率,将字符流 进行缓冲技术操作。使用BufferedReaderBufferedReader bufr=new BufferedReader(isr);/*String line=null;while((line=bufr.readLine())!=null){if("over".equals(line))//自定义结束标记break;System.out.println(line);System.out.println(line.toUpperCase());}*///获取输出设备OutputStream out=System.out;//字符流通向字节流对象:OutputStreamWriter类OutputStreamWriter osw=new OutputStreamWriter(out);//提高效率,将字符流进行缓冲区高效操作,BufferedWeriterBufferedWriter bufw=new BufferedWriter(osw);String line=null;while((line=bufr.readLine())!=null){if("over".equals(line))break;bufw.write(line);bufw.newLine();bufw.write(line.toUpperCase());bufw.newLine();//BufferedWriter类中的换行方法bufw.flush();//刷新}bufr.close();}}

改变读取源和改变输出目的的两个方法:
/*改变源和目的的两个方法:static void setIn(InputStream in)           重新分配“标准”输入流。 static void setOut(PrintStream out)           重新分配“标准”输出流。   PrintStream(String fileName)           创建具有指定文件名称且不带自动行刷新的新打印流。*/import java.io.*;class SystemIn{public static void main(String[] args )throws Exception{//设置源System.setIn(new FileInputStream("流规律.txt"));//设置目的System.setOut(new PrintStream("流规律_1.txt"));BufferedReader br=new BufferedReader(new InputStreamReader(System.in));BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));String line=null;while((line=br.readLine())!=null){if("over".equals(line))break;//bw.write(line.toUpperCase());bw.write(line);bw.newLine();bw.flush();}br.close();}}

异常日志信息:
异常日志信息*/import java.io.*;import java.util.*;import java.text.*;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返回的是输出流对象,初始化须有文件,文件须抛异常PrintStream ps=new PrintStream("日志信息.txt");ps.println(s);//相当于ps.write(s.getBytes());System.setOut(ps);}catch(Exception ex){throw new RuntimeException("日志信息建立失败");//捕获异常并处理}e.printStackTrace(System.out);//捕获并,处理角标越界异常}}}
HashMap集合 的子类Properties集合与IO相结合的技术用于配置文件的创建和读取
1、集合中load()方法,从输入流中读取键值对信息
2、Set ---stringProopertyNames(),获取Properties集合中的所有键的set集合
3、Properties集合中的:list(PrintStream   out)方法
store(outputStream   out,   String      comments)

/*properties 是HashMap的子类1.也就是说他具备map集合的特点,而且它里面存储的键值对都是字符串2.是集合中和IO技术相结合的集合容器该对象的特点:可以用于键值对形式的配置文件 String getProperty(String key)           用指定的键在此属性列表中搜索属性。  String getProperty(String key, String defaultValue)           用指定的键在属性列表中搜索属性。  Object setProperty(String key, String value)     Set<String> stringPropertyNames() 获取map集合中,键的set集合  void load(InputStream inStream)           从输入流中读取属性列表(键和元素对)。  void load(Reader reader)           按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。  void list(PrintWriter out)           将属性列表输出到指定的输出流。 void store(OutputStream out, String comments)    */import java. io.*;import java.util.*;class PropertiesDemo{public static void main(String[]  args)throws IOException{//getKey();//mothed_1();mothed_2();}public static void mothed_2()throws IOException{FileInputStream fis=new FileInputStream("配置文件.txt");Properties pro=new Properties();pro.load(fis);//System.out.println(pro);pro.setProperty("shengao","185");//发现只能修改内存的数据,文本中没变//pro.list(System.out);//通过此方法解决,将修改的数据写到文本中FileOutputStream fos=new FileOutputStream("配置文件_1.txt");pro.store(fos,"store()方法");pro.list(System.out);fos.close();fis.close();}//通过文本缓冲区读取,中的readLine(),在遍历的时候,进行字符串切割,返回字符串数组//再通过往Properties集合设置键值对public static void mothed_1()throws IOException{BufferedReader bufr=new BufferedReader(new FileReader("配置文件.txt"));Properties pro=new Properties();String line=null;while((line=bufr.readLine())!=null){String[] s=line.split("=");pro.setProperty(s[0],s[1]);}bufr.close();System.out.println(pro);}public static void getKey(){Properties pro=new Properties();pro.setProperty("zhangs","18");pro.setProperty("lisi","38");pro.setProperty("wangwu","28");System.out.println(pro);String s=pro.getProperty("lisi");System.out.println(s);Set<String> name=pro.stringPropertyNames();for(String names:name){System.out.println( names+"---"+pro.getProperty(names));}}}


联习代码:控制程序的运行次数
/*练习:用配置文件记录住程序的运行次数,使用次数已到,那么就给出提示键值对:map集合+ IO技术--------->用到Properties类*/import java.io.*;import java.util.*;class PropertiesDemo2{public static void main(String[] args)throws IOException{store();}public static void store()throws IOException{File file=new File("配置文件_2.ini");if(!file.exists())file.createNewFile();FileInputStream fis=new FileInputStream(file);Properties pro=new Properties();pro.load(fis);int count=0;String value=pro.getProperty("time");if(value!=null){ count=Integer.parseInt(value);if(count>=5){System.out.println("使用次数已到,请交钱");return ;}}count++;pro.setProperty("time",count+"");FileOutputStream fos=new FileOutputStream(file);pro.store(fos,"peizi");fis.close();fos.close();}}





---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------











原创粉丝点击