Java基础日记———IO流(上)

来源:互联网 发布:网络信用卡 编辑:程序博客网 时间:2024/06/03 13:06

一.概述
1.IO流用来处理设备之间的数据传输 。
2.Java对数据的操作是通过流的方式。
3.Java用于操作流的对象都在IO包中。
4.流按操作数据分为两种:字节流与字符流。
编码表进程:ASCII–>GB2312(中)–>GBK(中)–>Unicode(各个国家的进行重新编排,两个字节表示)–>UTF-8
–>仅为时间关系,不含其他。各个表的编码方式不同。
字符流就是为了适应编码表的多样化,可以指定处理文字是按照的编码表。
5.流按流向分为:输入流,输出流。
IO流常用基类:
字节流抽象基类:InputStream,OutputStream
字符流抽象基类:Reader,Wirter
由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
二.IO体系
1.字符流
(1)抽象类write:创建并写入文件。以操作文本文件来演示:FileWriter
①writer写文件
代码示例:

 FileWriter fw = new FileWriter("demo.txt");//创建一个FileWriter对象,并且对象一被初始化必须明确要操作的文件。    fw.write("asdasdasd");//调用write方法。    fw.flush();//刷新缓冲区,将数据存入“目的地”    fw.close();//关闭流资源(必需操作)。

注意点:
FileWriter初始化文件后将会创建到指定的目录下,如果该目录下存在该文件,那么原文件将会被覆盖。
flush和close的区别:flush只是刷新缓冲区,流可以继续使用;但是,close操作在刷新缓冲区后,将会关闭流资源。
②续写文件:
FileWriter(String fileName, boolean append):根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
代码示例:

  FileWriter fw = new FileWriter("demo.txt",true); 
③异常处理:    第一种直接抛出异常:throws IOException;    第二种使用try/catch:
    FileWriter fw = null; //在这里声明是因为这样finally中才不报错。    try  {              fw = new FileWriter("demo.txt");             fw.write("abcdefg");         } catch (IOException e) {               System.out.println("catch:"+e.toString());         } finally {               try {                       if(fw!=null) //为了健壮性,判断fw是否为空                      fw.close();    //必须操作,可以放在finally中              } catch (IOException e) {                     System.out.println(e.toString());              }            }
(2)抽象类Reader:读文件①读文件读取方式一

代码示例:

    FileReader fr = new FileReader("demo.txt"); //创建对象        int c= 0;        while((c = fr.read())!=-1){           System.out.print((char)c);     }     fr.close();

注意点:
创建一个文件读取流对象,需要和指定名称的文件相关联。而且保证文件存在,否则报错。
read():一次读一个字符。而且会自动往下读。
read的返回值:作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1 。
读取方式二:通过字符数组进行读取。

    FileReader fr = new FileReader("demo.txt");       char[] buf = new char[1024];        int num = 0;       while((num=fr.read(buf))!=-1) {             System.out.println(new String(buf,0,num));      }      fr.close();
注意点:      定义一个字符数组。用于存储读到的字符。      该read(char[])返回的是读到字符个数即定义时char的个数,读到最后会返回-1。

小例子
·复制文件主要代码示例:

      FileReader fr2 = new FileReader("demo.txt");       FileWriter fw = new FileWriter("F:\\demo3.txt");       char[] ch = new char[2048];       while(fr2.read(ch)!=-1){             fw.write(ch);       }       fr2.close();       fw.close(); 

(3)字符流缓冲区
目的:缓冲区是为了提高流的读取效率,所以没有空参数的构造函数。而且创建缓冲区前必须要先有流对象。
原理:缓冲区对象里封装了数组,先把数据存储起来编程一个对象,在进行读写。
①BufferWreiter
代码示例:

FileWriter fw = new FileWriter("buf.txt");  //创建一个字符写入流对象        BufferedWriter bufw = new BufferedWriter(fw); //将流对象传递给缓冲区构造函数即可        bufw.write("asdas\r\ndasd"); //写入操作        bufw.flush();//写入都要刷新        bufw.close();//关闭的是缓冲区的流对象,所以不用fw.close();
特有方法:    newLine():写入一个行分隔符。    方便跨平台使用:在windows中换行是\r\n,而Linux中是\r。

②BufferReader

  FileReader fr = new FileReader("buf.txt");  //创建一个读取流对象      BufferedReader bubr = new BufferedReader(fr);    String s = null;    while((s=bubr.readLine())!=null){        System.out.println(s);    }    bubr.close();
特有方法:    readLine():读取一行。    readLine读取的返回值是String类型,当返回null是为文件的结尾。    readLine只返回回车符之前的内容,并不包含每行的结尾换行符。③装饰设计模式:    当想要对已有的对象进行功能增强时,    可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。    那么自定义的该类称为装饰类。    装饰类通常会通过构造方法接收被装饰的对象。     并基于被装饰的对象的功能,提供更强的功能。装饰类设计模式与继承的区别:    MyReader//专门用于读取数据的类。     |--MyTextReader          |--MyBufferTextReader     |--MyMediaReader          |--MyBufferMediaReader     |--MyDataReader          |--MyBufferDataReader    class MyBufferReader    {        MyBufferReader(MyTextReader text)         {}         MyBufferReader(MyMediaReader media)         {}    }    上面这个类扩展性很差。    找到其参数的共同类型。通过多态的形式。可以提高扩展性。    class MyBufferReader extends MyReader    {         private MyReader r;         MyBufferReader(MyReader r)         {}    }    MyReader//专门用于读取数据的类。         |--MyTextReader         |--MyMediaReader         |--MyDataReader         |--MyBufferReader    以前是通过继承将每一个子类都具备缓冲功能。    那么继承体系会复杂,并不利于扩展。    现在优化思想。单独描述一下缓冲内容。    将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。    这样继承体系就变得很简单。优化了体系结构。    装饰模式比继承要灵活。避免了继承体系臃肿。    而且降低了类于类之间的关系。    装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。    所以装饰类和被装饰类通常是都属于一个体系中的。

包装类示例:
LineNumberReader(Reader in):使用默认输入缓冲区的大小创建新的行编号 reader。

2.字节流    字符流也是字节流,只有多了一个字符的编码表。    与字节流类似,相同部分只代码示例;不同部分会重点介绍。(1)OutputStream:字节输出流

代码示例:

 FileOutputStream fos = new FileOutputStream("fos.txt");    fos.write("abcde".getBytes()); //不用刷新                       fos.close();
(2)InputStream:字节输入流

代码示例:

     FileInputStream fis = new FileInputStream("fos.txt");     int ch = 0;     while((ch=fis.read())!=-1)     {           System.out.println((char)ch);      }      fis.close();
   上面的例子是一个一个读字节,比较麻烦。   可以对其进行修改:定义一个换成数组,一个数组一个数组的往外读取(也就是缓冲区):    byte[] buf = new byte[1024];    int len = 0;    while((len=fis.read(buf))!=-1)    {       System.out.println(new String(buf,0,len));     }特有方法:    available():返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。通俗来讲也就是返回文件的字节数,包括回车符等。(3)字节流缓冲区

代码示例:

     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) //返回值是int类型而字符流缓冲区读一行时返回的是String类型     {           bufos.write(by);      }      bufos.close();      bufis.close();
3.读取键盘录入     (1)通过刚才的键盘录入一行数据并打印其大写,发现其实就是读一行数据的原理。也就是readLine方法。    readLine方法是字符流BufferedReader类中的方法。而键盘录入的read方法是字节流InputStream的方法。    那么可以将字节流转换为字符流进行操作,同时方便对字符流操作可以使用缓冲区。    字节流与字符流之间的桥梁:Reader的子类:    InputStreamReader(InputStream in):创建一个使用默认字符集的 InputStreamReader。       OutputStreamWriter(OutputStream out):创建使用默认字符编码的 OutputStreamWriter          获取键盘录入对象。    InputStream in = System.in;    将字节流对象转成字符流对象,使用转换流。InputStreamReader    InputStreamReader isr = new InputStreamReader(in);    为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader    BufferedReader bufr = new BufferedReader(isr);  可以合为一句,即成为键盘录入最常见的写法:BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));    输出与之类似就是:BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

代码示例:

     BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));      BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));      String line = null;      while((line=bf.readLine())!=null){           bw.write(line.toUpperCase());           bw.newLine();           bw.flush();          }          bf.close();          bw.close();     }
(2).最简单,最强大的,就是用Scanner类
  public static void main(String [] args) {  Scanner sc = new Scanner(System.in);  System.out.println(“请输入你的姓名:”);  String name = sc.nextLine();  System.out.println(“请输入你的年龄:”);  int age = sc.nextInt();  System.out.println(“请输入你的工资:”);  float salary = sc.nextFloat();  System.out.println(“你的信息如下:”);  System.out.println(“姓名:”+name+“\n”+“年龄:”+age+“\n”+“工资:”+salary);  }
4.流操作的基本规律:     最痛苦的就是流对象有很多,不知道该用哪一个。    通过三个明确来完成。(1)明确源和目的。     源:输入流。InputStream  Reader     目的:输出流。OutputStream  Writer。(2)操作的数据是否是纯文本。     是:字符流。     不是:字节流。(3)当体系明确后,在明确要使用哪个具体的对象。     通过设备来进行区分:     源设备:内存,硬盘。键盘     目的设备:内存,硬盘,控制台。举例:(1)将一个文本文件中数据存储到另一个文件中。复制文件。     源:因为是源,所以使用读取流。InputStream Reader     是不是操作文本文件。     是!这时就可以选择Reader     这样体系就明确了。     接下来明确要使用该体系中的哪个对象。     明确设备:硬盘。上一个文件。     Reader体系中可以操作文件的对象是 FileReader     是否需要提高效率:是!加入Reader体系中缓冲区 BufferedReader.     FileReader fr = new FileReader("a.txt");     BufferedReader bufr = new BufferedReader(fr);     目的:OutputStream Writer     是否是纯文本     是!Writer     设备:硬盘,一个文件。     Writer体系中可以操作文件的对象FileWriter     是否需要提高效率:是!     加入Writer体系中缓冲区 BufferedWriter     FileWriter fw = new FileWriter("b.txt");     BufferedWriter bufw = new BufferedWriter(fw);(2)需求:将键盘录入的数据保存到一个文件中。     这个需求中有源和目的都存在。     那么分别分析     源:InputStream Reader     是不是纯文本?是!Reader      设备:键盘。对应的对象是System.in.     不是选择Reader吗?System.in对应的不是字节流吗?     为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。     所以既然明确了Reader,那么就将System.in转换成Reader。     用了Reader体系中转换流,InputStreamReader     InputStreamReader isr = newInputStreamReader(System.in);     需要提高效率吗?需要!BufferedReader     BufferedReader bufr = new BufferedReader(isr);     目的:OutputStream  Writer     是否是存文本?是!Writer。     设备:硬盘。一个文件。使用 FileWriter。     FileWriter fw = new FileWriter("c.txt");     需要提高效率吗?需要。     BufferedWriter bufw = new BufferedWriter(fw);
0 0