Java学习总结-IO流的概念理解

一、Java io流 的概念

流存在的意义:

1. 数据的传输量很大

2. 内存有限

3. 带宽有限

而Stream可以1点1点地逐步传输所有数据, 这就是Stream存在的根本意义。想想我们是怎样下载1个大文件的, 下载软件(例如x雷)并不会占用你内存很大的空间, 而只是在内存划分1个缓冲区, 一点一点地下载到自己的内存(缓冲区满了再写到硬盘), 这也是流的1个例子。

1、java的io是实现输入和输出的基础,可以方便的实现数据的输入和输出操作。在java中把不同的输入/输出源(键盘,文件,网络连接等)抽象表述为“流”(stream)。通过流的形式允许java程序使用相同的方式来访问不同的输入/输出源。stram是从起源(source)到接收的(sink)的有序数据。

2、Stream是java的1个类, 这个类专门用于程序和外部设备的输入输出(IO). 基本上所有流都在 java.io这个包中.

实际上Stream就是数据在程序和外部设备的单向管道, 流的各种方法相当于管道上的各种按钮.  

所谓的外部设备可以包括硬盘文件, 网络设备, 另个程序等. 也就是当前程序之外的数据设备

Java将所有传统的流类型都放在Java.io包下,用于实现输入和输出功能。

二、io 流的分类

按照流的不同的分类方式,可以把流分为不同的类型,流常见的分类有3种:

1、按照流的流向分:输入流和输出流

  • 输入流: 只能从中读取数据,而不能向其写入数据。
  • 输出流:只能向其写入数据,而不能向其读取数据。

此处的输入,输出涉及一个方向的问题,对于如图15.1所示的数据流向,数据从内存到硬盘,通常称为输出流——也就是说,这里的输入,输出都是从程序运行所在的内存的角度来划分的。

注:java的输入流主要是InputStream和Reader作为基类,而输出流则是主要由outputStream和Writer作为基类。它们都是一些抽象基类,无法直接创建实例。

2、按照操作单元划分,可以划分为字节流和字符流。

    字节流和字符流的用法几乎完成全一样,区别在于字节流和字符流所操作的数据单元不同,字节流操作的单元是数据单元是8位的字节,字符流操作的是数据单元为16位的字符。

字节流主要是由InputStream和outPutStream作为基类,而字符流则主要有Reader和Writer作为基类。

3、按照流的角色划分为节点流和处理流。

    可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,称为节点流。节点流也被称为低级流。图15.3显示了节点流的示意图。 
    从图15.3中可以看出,当使用节点流进行输入和输出时,程序直接连接到实际的数据源,和实际的输入/输出节点连接。 
处理流则用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能。处理流也被称为高级流。

节点流:

节点流的类型:

 1)File 文件流。对文件进行读、写操作 :FileReader、FileWriter、FileInputStream、FileOutputStream。、
(2)Memory 
1)从/向内存数组读写数据: CharArrayReader与 CharArrayWriter、ByteArrayInputStream与ByteArrayOutputStream。 
2)从/向内存字符串读写数据 StringReader、StringWriter、StringBufferInputStream。
(3)Pipe管道流。 实现管道的输入和输出(进程间通信): PipedReader与PipedWriter、PipedInputStream与PipedOutputStream

节点流执行图示:

 

 处理流:

处理流的类型:

 (1)Buffering缓冲流:在读入或写出时,对数据进行缓存,以减少I/O的次数:BufferedReader与BufferedWriter、BufferedInputStream与BufferedOutputStream。 
- (2)Filtering 滤流:在数据进行读或写时进行过滤:FilterReader与FilterWriter、FilterInputStream与FilterOutputStream。 
- (3)Converting between Bytes and Characters 转换流:按照一定的编码/解码标准将字节流转换为字符流,或进行反向转换(Stream到Reader):InputStreamReader、OutputStreamWriter。 
- (4)Object Serialization 对象流 :ObjectInputStream、ObjectOutputStream。 
- (5)DataConversion数据流: 按基本数据类型读、写(处理的数据是Java的基本类型(如布尔型,字节,整数和浮点数)):DataInputStream、DataOutputStream 。 
- (6)Counting计数流: 在读入数据时对行记数 :LineNumberReader、LineNumberInputStream。 
- (7)Peeking Ahead预读流: 通过缓存机制,进行预读 :PushbackReader、PushbackInputStream。 
- (8)Printing打印流: 包含方便的打印方法 :PrintWriter、PrintStream。
 

处理流的执行图示:

 

缓冲流(buffering)是处理流的一种,对I/O进行缓冲是一种常见的性能优化,缓冲流为I/O流增加了内存缓冲区,增加缓冲区的两个目的: 
(1)允许Java的I/O一次不只操作一个字符,这样提高䇖整个系统的性能; 
(2)由于有缓冲区,使得在流上执行skip、mark和reset方法都成为可能。

【2】缓冲流:它是要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能, 
提高了读写的效率,同时增加了一些新的方法。例如:BufferedReader中的readLine方法, 
BufferedWriter中的newLine方法。

j2sdk提供了4种缓冲流,重用的构造方法如下:

//字符输入流
BufferedReader(Reader in)//创建一个32字节的缓冲区
BufferedReader(Reader in, int size)//size为自定义缓存区的大小

//字符输出流
BufferedWriter(Writer out)
BufferedWriter(Writer out, int size)

//字节输入流
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int size)

//字节输出流
BufferedOutputStream(OutputStream in)
BufferedOutputStream(OutputStream in, int size)

备注:

  (1)缓冲输入流BufferedInputSTream除了支持read和skip方法意外,还支持其父类的mark和reset方法; 
  (2)BufferedReader提供了一种新的ReadLine方法用于读取一行字符串(以\r或\n分隔); 
  (3)BufferedWriter提供了一种新的newLine方法用于写入一个行分隔符; 
 (4)对于输出的缓冲流,BufferedWriter和BufferedOutputStream,写出的数据会先在内存中缓存, 
使用flush方法将会使内存的数据立刻写出。

 

分类2:

1、java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java Io流的40多个类都是从如下4个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

2、java输入/输出流体系中常用的流的分类表

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipedInputStreamPipedOutputStreamPipedReaderPipedWriter
访问字符串  StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流  InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream  
抽象基类FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流 PrintStream PrintWriter
推回输入流PushbackInputStream PushbackReader 
特殊流DataInputStreamDataOutputStream  

注:表中粗体字所标出的类代表节点流,必须直接与指定的物理节点关联:斜体字标出的类代表抽象基类,无法直接创建实例。

 

 

CODE:

/**2019.6.14
 * cpu将数据传入设备叫输出流-写入数据write,设备将数据传到cpu输入流-读数据
 *java.io 包
 * 定规范就是为了让别人写出想要的方法
 * InputStream int read()
 * OutputStream void write(,int);
 * File:对文件进行的操作:FileInputStream 是从文件里面读东西的 ,调用read
 * FileOutStream :从文件里面输出信息 ,调用write()方法
 */
package flow;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.*;
import java.util.Date;
import test.Student;
public class TestIo {
    /*测试文件输出流*/
    @Test
    public void test1() throws Exception {
        //与众多的设备打交道的流叫基础流(低级流)文件流是低级流
        FileOutputStream fout = new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\a.txt");
        int a = 20;//00000000 00000000 00000000 00010100 一个字节代表8位
        byte[] b = {0,0,0,20};
        fout.write(b[0]);
        fout.write(b[1]);
        fout.write(b[2]);
        fout.write(b[3]);
        fout.close();
        //0号字符,20号字符显示不出来
        FileInputStream fin = new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\a.txt");
        byte[] c = new byte[4];
        c[0] = (byte) fin.read();
        c[1] = (byte) fin.read();
        c[2] = (byte) fin.read();
        c[3] = (byte) fin.read();
        System.out.println(b[3]);
        fin.close();
    }

    @Test
    public void test2() throws Exception {
        FileOutputStream fout = new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\b.txt");
        String mesg = "Hello!Laurence。";
        // 00000000 1010111 Java采用Unicod码
        byte[] ss = mesg.getBytes();
        for (byte s : ss) {//for循环遍历的另一种形式
            fout.write(s);//对象流
        }
        fout.close();
    }

//读
    @Test
    public void test3() throws Exception {
        FileInputStream fin = new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\b.txt");
        byte[] b = new byte[fin.available()];//测量文件占用的字节长度
        int t;
        byte i = 0;
        while ((t = fin.read()) != -1) {
            b[i] = (byte) t;
            i++;
        }
        String c = new String(b);
        System.out.println(c);
        fin.close();//释放流的资源
    }


    /*
     高级流一般不读写文件
     */
    @Test
    public void test4() throws Exception {
        OutputStream fout = new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\b.txt");
        //OutputStream :写
        ObjectOutputStream objout = new ObjectOutputStream(fout);//实际上是fout在写字节
        // ObjectOutputStream :类型转换:将其他类型转换为字节类型
        //write()是写字节的方法
        objout.writeInt(222);//对象流完成其他类型到字节类型的转换
        objout.writeDouble(22.0);
        objout.writeBoolean(true );
        objout.writeChar('l');
        objout.writeChars("liujiaheng is a good man!");
        objout.flush();//刷新
        objout.close();
        fout.close();//释放流的资源
     }




     //装饰模式:两个流类合作完成一个功能
    @Test
    public void test5() throws Exception {
        InputStream fin = new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\b.txt");
        ObjectInputStream objout = new ObjectInputStream(fin);//实际上是fout在写字节
        int r=objout.readInt();//对象流完成其他类型到字节类型的转换
        System.out.println(r);
        double t1=objout.readDouble();
        System.out.println(t1);
        boolean t2=objout.readBoolean();
        System.out.println(t2);
        char e=objout.readChar();
        System.out.println(e);
//        String t3=objout.readUTF();//此方法读不出字符串
        System.out.println(t3);
        objout.close();
        fin.close();//释放流的资源
     }

@Test
    public void test6() throws Exception {
          OutputStream fout = new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
         //OutputStream :写
          ObjectOutputStream objout =new ObjectOutputStream(fout);
          Date d=new Date();
          objout.writeObject(d);
          Student s=new Student(2000,"Laurence");
          objout.writeObject(s);
          objout.flush();
          objout.close();
    }


@Test
    public void test7() throws Exception {
        InputStream fin = new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
        //OutputStream :实现写的操作

        ObjectInputStream obin = new ObjectInputStream(fin);//实际上是fout在写字节
        // ObjectOutputStream :类型转换
        //write()是写字节的方法;
          Date d=(Date)obin.readObject();
          Student s=(Student)obin.readObject();
          System.out.println(d);
          System.out.println(s.getName());
          System.out.println(s.getId());
          obin.close();
    }
         //高级流实现读写操作
    public void test8() throws Exception {
        OutputStream fout = new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
        //OutputStream :实现写的操作
        //下面也是高级流
        BufferedOutputStream bout = new BufferedOutputStream(fout);
        ObjectOutputStream obin = new ObjectOutputStream(bout);//实际上是fout在写字节
        fout.write(22);
        bout.write(222);
        bout.flush();//此时将数据写入文件里了
        ObjectOutputStream objout = new ObjectOutputStream(
                new BufferedOutputStream(
                        new FileOutputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\d.txt")
                )
        );
        Date d=new Date();
        objout.writeObject(d);
        Student s=new Student(2000,"Laurence");
        objout.writeObject(s);
        objout.flush();
        objout.close();

    }



        public void test9() throws Exception {
            InputStream fin = new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
            //OutputStream :实现写的操作

            ObjectInputStream obin = new ObjectInputStream(

                    new BufferedInputStream(
                         new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt")
                    )
            );//实际上是fout在写字节
            // ObjectOutputStream :类型转换
            //write()是写字节的方法;
            Date d=(Date)obin.readObject();
            Student s=(Student)obin.readObject();
            System.out.println(d);
            System.out.println(s.getName());
            System.out.println(s.getId());
            obin.close();
        }
    }

 

package flow;
import org.junit.Test;
import java.io.*;
import  java.util.*;

public class testIo2 {

    @Test
    public void test1() throws Exception{
        FileInputStream fin=new FileInputStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
          int a;
          while ((a=fin.read())!=-1){
              System.out.println((char)a);
          }
        fin.close();//因为字节流是一个字节一个字节读的,但是一个字符是占用两个字节。所以读出来的数据是乱码的
        //Reader、 Writer字符流
    }


    @Test
    public  void test2() throws Exception{
        FileWriter  w=new FileWriter("D:\\新建文件夹\\练习\\javacode\\src\\test\\c.txt");
        w.write('A');
        w.write("刘家亨真棒!");
        w.close();

    }


    //字符流
    @Test
    public  void test3() throws Exception{
        BufferedWriter  w=new BufferedWriter(
                new FileWriter("D:\\新建文件夹\\练习\\javacode\\src\\test\\e.txt")
            );
        w.write("sucessful\n");
        w.flush();//
        w.close();
    }


    @Test
    public  void test4() throws Exception{
        FileReader  w=new FileReader("D:\\新建文件夹\\练习\\javacode\\src\\test\\e.txt");
        int a;
        while((a=w.read())!=-1){
            System.out.print((char)a);
        }
        w.close();
    }


    @Test
    public  void test5() throws Exception{
        BufferedReader  w=new BufferedReader(new FileReader("D:\\新建文件夹\\练习\\javacode\\src\\test\\e.txt")
         );
         String mesg = w.readLine();
         System.out.println(mesg);
         w.close();
    }


    //输入流 //输入流不需要flush//输入流包装字符流
    @Test
    public void tes6() throws Exception {
        InputStreamReader ir=new InputStreamReader(System.in) ;
        BufferedReader br=new BufferedReader(ir);
        String mesg=br.readLine();
        System.out.println(mesg);
    }

    @Test
    public void  test7() throws Exception{
        OutputStreamWriter w=new OutputStreamWriter(System.out);
         BufferedWriter bw=new BufferedWriter(w);
         bw.write("中国你好!");
         bw.flush();
         bw.close();

    }




    @Test//PrintStream主要用于包装其他字符流,还可以用来写字符串
    public void  test8() throws Exception{
      PrintStream c=new PrintStream("D:\\新建文件夹\\练习\\javacode\\src\\test\\rr.txt");
      c.print("hello"+"my name is Laurence");//
      c.flush();//刷新后才能写进去
    }

    //既可以包装字符流,又可以包装字节流,还可以给文件直接写字符,它可以和其他的流搭配着用
    @Test
    public void test9()throws Exception {
    PrintWriter pw = new PrintWriter("D:\\新建文件夹\\练习\\javacode\\src\\test\\rr.txt");
    pw.println("hello"+"bjdhsvcjhdbvcjhdsc");//给文件中写入这样一段字符
    pw.flush();
    pw.close();

    }


    @Test//文件对象   用来标识文件的,判断文件或目录是否存在
    public void test10() throws Exception{
        File f=new  File("D:\\liujiaheng\\pp");
        if(f.exists()){//判断文件目录是否存在
            System.out.println("存在");
        }else{
            System.out.println("不存在");
            System.out.println( f.mkdirs());//如果不存在就创建一个目录树
        }
    }

    @Test
    public void tes11() throws Exception {
        File f = new File( "D:\\新建文件夹\\练习\\aa.txt" );
        if(f.exists()){//判断文件是否存在
            System.out.println("存在");
        }else{
            System.out.println("不存在");
            f.createNewFile();//必须在已将创建的目录下才可以创建一个空文件
        }
    }


    @Test
    public void tes12() throws Exception {
        File f = new File("D:\\新建文件夹\\练习\\javacode\\src\\test");//这是一个目录
        File e=new File("D:\\新建文件夹\\练习\\javacode\\src\\test\\rr.txt");
        System.out.println(f.isDirectory());//判断目录是否存在
        System.out.println(f.isFile());//判断是否为文件返回值为true或false
        System.out.println(e.isDirectory());
        System.out.println(e.isFile());
    }


    @Test
    public void tes13() throws Exception {
        File f = new File("D:\\新建文件夹");
       //目录名两端加一个[]代表它是一个目录。
        if(f.isDirectory()){
            System.out.println("[" + f.getName() + "]");
        }else{
            System.out.println(f.getName());
        }
        File[] fs = f.listFiles();
        if(fs != null && fs.length > 0){
            listFile(fs,1);
        }
    }

    private void writeBlank(int level){
        for(int i = 0 ; i < level ; i++)
            System.out.print("  ");//一级打两个空格
    }

    private void listFile(File[] fs,int level){//file数组,level表示是第几层
        for(File f : fs){//循环
            writeBlank(level);//打空格
            if(f.isDirectory()){//判断这个文件是不是目录
                System.out.println("[" + f.getName() + "]");
                File[] ff = f.listFiles();
                if(ff != null && ff.length > 0){//判断目录是否为空
                    listFile(ff,++level);//不为空就迭代
                }
            }else{
                System.out.println(f.getName());//不是目录打印出名字
            }
        }
    }

}

流的重要特性:

1、流是Java 的1个类,但类不是流。

2、数据并不会在流里自动流动,因此需要我们调用流的方法,一次传输一定量的数据。

3、一个流对象只有一个传输方向,也就是说流是单向的, 数据要么从程序到设备(OutputStream), 要么从设备到程序(InputStream)。

 

 

 

 

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值