Day03 I/O 流(详解)

I/O流 (即InputStream和OutPutStream) 指得时输入流和输出流

一   流的概念

流是指计算机各部件之间的数据流动。

在java中,把不同类型的输入输出源(键盘、屏  幕、文件、网络等)抽象为流,而其中输入或输出的数据成为数据流。

二  流的分类

按照数据的传输方向,流可分为输入流与输出流;从内容的划分上来看,分为字节流和字符流;

2.1输入流:

输入流指的是:将数据从外设或外存(键盘、鼠标、文件等)传递到应用程序中的流称为输入流。

从本质上来讲,输入流用来读取数据(也就是说程序接收数据时可以认为读取数据。)

2.2输出流

输出流指的是:将数据从应用程序传递到外设或外存(如:屏幕、打印机、文件等)的流称为输出流。

输出流用来写入数据。(也就是说从程序中发送数据时可以认为是写入数据)。

对于输入流只能从其读取数据,而不能写入数据,同样输出流只能向其写入数据而不能从中读取数据。

通常:java应用程序使用输入流读取数据,输出流写入数据。

2.3字节流与字符流:

根据输入输出的数据类型的不同,输入输出流类型分为两种:1.一种是字节流;2.一种是字符流

字符流:(字符流分为字符输入流(Reader)和字符输出流(Writer)。)

字符流用来处理字符数据,字符流的操作对象通常是文本文件。

字符流是针对字符数据的特点进行优化的,因而提供了一些面向字符的有用的特性。java中的字符使用的是16位的unicode编码,每个字符占有两个字节。

字节流:(字节流分为字节输入流(InputStream)和字节输出流(OutPutStream))

字节流用来处理字节数据,这种流通常被用来读写诸如图片、音频之类的二进制数据,也就是二进制文件,但也可以用来处理文本。但不提倡这样做,因为字节流操作文本文件,如果文件中有汉字,可能会出现乱码,这是因为字节流不能直接操作unicode字符所致。因此java语言不提倡使用字节流来读写文本,而建议使用字符流操作文本文件。

很多情况下,数据源或目标中含有非字符的数据,例如java编译器产生的字节码文件中含有java虚拟机的指令。这些信息不能被解释成字符,所以必须使用字节流来输入、输出。

三 使用InputStream (字节输入流)和OutputStream (字节输出流)流 类

InputStream和OutputStream 是抽象类,所以一般而言,并不会直接使用这些类,因为不能表名它们对应哪种输入输出设备,而通常是根据这些类所派生的子类来处理文件。InputStream和OutputStream类是java语言中用来处理二进制文件的数据。

基本的字节输入输出流类

3.1.InputStream(字节输入流)

InputStream流类中包含一套所有字节输入都需要的方法,可以完成最基本的输入流读取数据的功能。

流中的方法都声明抛出异常,所以程序中调用流方法时,必须处理异常,否则编译不能通过。

由于InputStream是抽象类,所以程序创建的输入流对象一般是InputStream某个子类的对象。

3.2.OutputStream(字节输出流)

OutputStream类中包含一套所有字节输出都需要的方法,可以完成最基本的向输出流写入数据的功能。

由于OutputStream是抽象类,所以程序中创建的输出流一般是OutputStream某个子类的对象。

3.3字节输入输出流的应用

由于InputStream字节输入流与OutputStream字节输出流都是是抽象类,所以在具体应用时使用的都是它们所派生的子类,不同的子类,用于不同情况数据的输入输出操作。下面简要介绍这些子类。

3.3.1FileInputStream(文件字节输入流):它是InputStream类的直接子类

创建FileInputStream对象的几种构造方法:

1.  第一种     FileInputStream(String name):表示以指定的文件名作为数据源建立文件输入流对象

例如:FileInputStream input=new FileInputStream("world.txt"):这种写法表示world.txt文件是在当前项的根目录下,在Eclipsez中,直接点击项目名创建的文件都是这种写法。这个文件位于项目的根目录中。当然,也可以指定电脑的磁盘中文件作为数据源,比如:FileInputStream input=new FileInputStream("D:/file/world.txt")或是这种写法:("D:\\file\\world.txt").

 

2.  第二种    FileInputStream(File file):已指定名字的文件对象为数据源建立文件输入流:例如

File file=new File("world.txt");

FileInputStream input=new FileInputStream(file);

3. 第三种     FileInputStream(FileDescriptor fdobdj)根据文件描述符对象为输入端建立一个文件输入流

例如:FileInputStream input=new FileInputStream(FileDescriptor.in);利用这种方式可以实现键盘输入操作。用到的不多,不做详解。

需要注意:在生成FileInputStream对象时,如果指定的文件不存在,则会抛出FileNotFoundException异常。

3.3.2FileOutputStream(文件字节输出流类):它是OutputStream类的直接子类。

创建该对象的4种构造方法:

1 FileOutputStream(String name):已指定名字的文件为接收端建立文件输出流对象;

FileOutputStream out=new FileOutputStream("world.txt");

2.FileOutputStream(File file); 以指定名字的文件对象为接收端建立文件输出流;

例如:File file=new File("world.txt");

          FileOutputStream out=new FileOutStream(file);

3.  FileOutputStream(FileDescriptor fdobj);根据文件描述符对象建立一个文件输出流;

FileOutputStream out=new FileOutStream(FileDescriptor.out);

利用它可以实现屏幕输出操作,将要写入的内容打印到控制台(屏幕),用的不多,不在介绍。

4.  FileOutputStream(String name,boolean append);以指定名字的文件接收端建立文件输出流,并指定写入方式,如果append为true时,则内容会被追加到文件的末尾,文件中的原来的内容不会被清除。默认情况下,使用文件输出流写入数据时,文件的数据会被清零。

注:生成FileOutputStream对象时,如果指定的文件不存在,则会创建一个新的文件。

四   字符输入流(Reader)与字符输出流(Writer )的使用

Reader与writer是用来处理字符流的,也就是文本文件,与文件节流输入输出的功能一样,文件字符输入输出流类Reader与Writer只是建立一条通往文本文件的通道,而要实现对字符数据的读写操作,还需要相应的读方法和写方法来完成。

由于Reader与Writer是抽象类,所以不能直接使用这两个类,而是使用它们的子类来创建对象,再利用对象处理读写操作。

4.1字符输入输出流的应用

由于Reader与Write是抽象类,所以不能直接使用这两个类,而是使用它们的子类来创建对象,再利用对象处理读写操作。下面介绍这些子类。

4.1.2使用FileReader(文件字符输入流)类读取文件

文件字符输入流类FileReader是继承自InputStreamReader类,而InputStreamReader类,而InputStreamReader类又继承自Reader类,因此,Reader类与InputStreamReader类所提供的方法均可供FileRreader类所创建的对象使用。

 

构造方法摘要

FileReader(File file)
          在给定从中读取数据的 File 的情况下创建一个新 FileReader。

例如:File file=new File("D:/world.txt");

FileReader reader=new FileReader(file);

FileReader(FileDescriptor fd)
          在给定从中读取数据的 FileDescriptor 的情况下创建一个新 FileReader。

例如:

FileReader reader=new FileReader(FileDescriptor.in);

FileReader(String fileName)
          在给定从中读取数据的文件名的情况下创建一个新 FileReader。

例如:

FileReader reader =new FileReader("D:/world.txt");

4.1.3使用FileWriter(文件字符输出流)类读取文件

文件字符输出流类FileWriter是继承自OutputStreamWriter类,而OutputStreamWriter类是继承自Writer类,因此,Writer类与OutputStreamWriter类所提供的方法均可以供FileWriter类的对象所使用。

创建FileWriter对象的几种构造方法。

 

 

FileWriter(File file)
          根据给定的 File 对象构造一个 FileWriter 对象。

File file=new File("D:world.txt");

FileWriter writer=newFileWriter(file);

FileWriter(File file, boolean append)
          根据给定的 File 对象构造一个 FileWriter 对象。

File file=new File("D:world.txt");

FileWriter writer=newFileWriter(file,true);设置成true,表示将内容追加到文件末尾中去,而不会进行覆盖。默认情况写,向文件写入字符数据时,原文件中的内容会被覆盖清零。

FileWriter(FileDescriptor fd)
          构造与某个文件描述符相关联的 FileWriter 对象。

例如:

FileWriter writer=newFileWriter(FileDescriptor.out);会将写入的数据打印到屏幕(控制台)。用到的不多

FileWriter(String fileName)
          根据给定的文件名构造一个 FileWriter 对象。

File file=new File("D:world.txt");

FileWriter writer=newFileWriter(“D:world.txt”);

FileWriter(String fileName, boolean append)
          根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。

 

FileWriter writer=newFileWriter("D:world.txt",true);设置成true,表示将内容追加到文件末尾中去,而不会进行覆盖。默认情况写,向文件写入字符数据时,原文件中的内容会被覆盖清零。

五.带缓冲的输入输出流(缓冲字节流)

缓冲是I/O的一种优化,缓冲流为I/O流增加了缓冲区,有了缓冲区,使得在流上执行skipp()、mark()、和reset()方法称为了可能。 (使用缓冲字节流的主要特点是,它可以大大提高程序的执行效率)

5.1 缓冲字节输入流的使用(BufferedInputStream)

缓冲字节输入流(BufferedInputStream)的使用与其他字节输入流的使用方法一样,但是,它需要建立在其他的字节流之上,也就是说,我们有一个已经存在的其他类型的字节输入流时,我们可以使用缓冲字节输入流将它包装起来,这样可以大大提高程序的执行效率。(简而言之,使用缓冲字节输入流时,必须将一个其他类型的字节输入流对象作为缓冲字节输入流对象的参数)比如:File file=new File("world.txxt");

FileInputStream in=new FileputStream(file);

BufferedInputStream buff=new BufferedInputStream(in);

缓冲字节输入流的特点:执行效率高,大大提高了程序的执行效率。

5.1.1缓冲字节输入流与普通的字节输入流执行效率测试

:使用普通的字节输入流来读取文件内容所需要的时间。

public class BufferedStreamTest {

    public static void main(String[] args) {

        //创建文件对象
        File file=new File("C:\\Users\\zsj\\Desktop\\MYSQL5.1 CHM版中文帮助文档.chm");
        
        byte b[]=new byte[4583424];
        FileInputStream input=null;
        long start=System.currentTimeMillis();
        try {
            input=new FileInputStream(file);
            while(input.read(b)!=-1) {
                
            }
            long end=System.currentTimeMillis();
            System.out.println("文件读取完成,用时\n"+(end-start)+"毫秒");
        } catch (FileNotFoundException e) {
        
            e.printStackTrace();
        } catch (IOException e) {
            
            e.printStackTrace();
        }
        
    }

}
 

5.1.2使用缓冲字节输入流来读取文件内容所需要的时间

public class BufferedStreamTest2 {

    public static void main(String[] args) {

        //创建文件对象
        File file=new File("C:\\Users\\zsj\\Desktop\\MYSQL5.1 CHM版中文帮助文档.chm");
        
        byte b[]=new byte[4583424];
        FileInputStream input=null;
        //获取当前系统时间,开始读文件时的时间,
        long start=System.currentTimeMillis();
        try {
            //创建字节输入流对象
            input=new FileInputStream(file);
            //创建缓冲字节输入流对象
            BufferedInputStream buff=new BufferedInputStream(input);
            while(buff.read(b)!=-1) {//buff.read(b),将读取到的数据保存到字节数组中去。果因为已经到达文件末尾而没有更多的数据,则返回 -1。 

                
            }
            //获取当前系统时间,读完文件时的时间
            long end=System.currentTimeMillis();
            System.out.println("文件读取完成,用时\n"+(end-start)+"毫秒");
        
        } catch (FileNotFoundException e) {
        
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
    }

}
 

5.2缓冲字节输出流的使用(BufferedOutputStream)

使用缓冲字节输出流时,它也需要一个已经存在的其他类型的字节输出流对象作为缓冲字节输出流对象的参数。(将其他类型的字节输出流对象包装成缓冲字节输出流。)

例如:

File file=new File("world.txt");

FileOutputStream  out=new FileOutputStream(file);

BufferedOutputStream buff=new BufferedOutputStream(out);

这个对象提供一个flush()方法,它的作用是强制将缓冲区数据写入文件中,即使缓冲区的数据环没有填满,也要将缓冲区的数据写入文件中去。使用缓冲字节输出流时,应多使用flush()操作。

缓冲字节输出流提高了写入数据的效率,它提供的一个flush()刷新的操作,可以让我们避免等待,只要缓冲区有数据就会写入文件中去。

六.缓冲字符流

与缓冲字节流相对应,Java中也有缓冲字符流。

缓冲字符流它有一个最大的特点,就是可以以行为单位,进行输入/输出。

我们之前介绍的都是以字节或字符为单位。在缓冲字符输入流(BufferedReader)中有一个方法叫readLine(),它可以一次读取一行的文本内容。在缓冲字符输出流(BufferedWriter)中,它有一个newLine()方法,它可以在写入数据的时候创建一个新行。

6.1缓冲字符输入流(BufferedReader类)

缓冲字符输入流类BufferedReader继承自Reader类,BufferedReader类是用来读取缓冲区里的数据。使用BufferedReader类来读取缓冲区中的数据之前,必须先创建FileReader类对象,在以该对象来创建BufferedReader类的对象,然后才可以利用此对象来读取缓冲区里的数据。

/*缓冲字符输入流的测试*/
public class BufferedCharStreamTest {

    public static void main(String[] args) {

        File file=new File("world5.txt");
        FileReader reader=null;
        BufferedReader buff_reader=null;
        try {
            //创建文件字符输入流对象
            reader=new FileReader(file);
            //创建缓冲字符输入流对象
            buff_reader=new BufferedReader(reader);
            String temp=null;
            int context=1;
            while((temp=buff_reader.readLine())!=null) {//readLine()方法:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 
                System.out.println("第"+context+"行"+temp);
                context++; 
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            
            
            if(buff_reader!=null) {//关闭流
                try {
                    buff_reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if(reader!=null) {//关闭流
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        
        }
    }

}
 

 

6.2缓冲字符输出流(BufferedWriter类)

缓冲字符输出流类BufferedWriter继承自Writer类,BufferedWriter类是用来将数据写入到缓冲区里。使用BufferedWriter类将数据写入缓冲区的过程与使用BufferedReader类从缓冲区读出数据的过程类似。首先必须先创建FileWriter类对象,在以该对象为参数来创建BufferedWriter类的对象,然后就可以利用此对象来讲数据写入缓冲区,所不同的是,缓冲区内的数据最后必须使用flush()方法将缓冲区清空,也就是将缓冲区的数据全部写入到文件内。

public class BufferedCharStreamTest2 {

    public static void main(String[] args) {

        File file=new File("world5.txt");
        FileWriter writer=null;
        BufferedWriter buff_writer=null;
        
        try {//创建文件字符输出流对象 
            writer=new FileWriter(file,true);
            //创建缓冲字符输出流对象
            buff_writer=new BufferedWriter(writer);
            String str1="如果再回到从前";
            String str2="所有一切重演";
            //     buff_writer .newLine()方法: 写入一个行分隔符。
            buff_writer .newLine();
            //将字符串写入文件中去
            buff_writer.write(str1);
            buff_writer .newLine();
            buff_writer.write(str2);

//必须使用flush()方法,刷新该流的缓冲。 否则可能数据可能并没有被写入文件中去
            buff_writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(buff_writer!=null) {//关闭流
                try {
                    buff_writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(writer!=null) {//关闭流
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            
        }
        

    }

}
七.数据流

数据流可以从流中读取或写入java的基本数据类型,也就是说,在流中可以读取int值、double值等。在java中使用DataInputStream来表示数据输入流,使用DataOutputStream来表示数据输出流。

7.1数据输入流(DataInputStream)与数据输出流(DataOutputStream)

DataInputStream流它是FilterInputStream(过滤字节输入流)的一个子类。

DataOutputStream它是FilterOutputStream(过滤字节输出流)的一个子类。

我们可以使用DataInputStream流来读取文件中的基本 Java 数据类型

应用程序可以使用数据输出流写入基本数据类型,使用数据输入流读取写入的java基本数据数据。

我们可以使用数据输出流把Java中的基本数据类型写入文件当中去,但是,我们写入文件中的基本数据类型,打开这个文件之后是乱码的,因为它写入的是字节码,我们要想解析这个字节码,需要使用数据输入流来将这个文件的字节码读出来。然后,通过数据输入流中的一些方法,将这些字节码解析成我们对应的数据类型。

案例如下:

/*数据输入流与数据输出流的使用*/
public class DataStreamTest {

    public static void main(String[] args) {
        
        File file=new File("world2.txt");
        
        FileOutputStream out=null;
        DataOutputStream data_out=null;
        try {
            out=new FileOutputStream(file);
            data_out=new DataOutputStream(out);
            //writeUTF()这个方法是将一个字符串类型的数据写入文件中去。 
            data_out.writeUTF("生命只有在不畏惧艰险时才充满张力,只有在战胜自我时才有意义。");
            //writeInt(int in):将一个int类型的值数据写入文件
            data_out.writeInt(123);
            //writeBoolean(boolean b):将布尔型数据写入文件中
            data_out.writeBoolean(true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(data_out!=null) {//关闭数据流
                try {
                    data_out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            
            }
            if(out!=null) {//关闭文件字节输入流
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            
            }
        //我们使用数据输出流向文件中写入数据后,打开文件,内容是乱码的,我们需要通过数据输入流来查看文件中的数据类型相应的值
            FileInputStream input=null;
            DataInputStream data_input=null;
            try {
                input =new FileInputStream(file);
                data_input=new DataInputStream(input);
                //读取字符串类型的数据
                System.out.println(data_input.readUTF());
                //读取int类型的数据
                System.out.println(data_input.readInt());
                //读取boolean类型的数据
                System.out.println(data_input.readBoolean());
                //需要注意的是,读取文件中的数据 类型时,一定定要按照写入数据类型的顺序来,否则运行报异常。
                
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(data_input!=null) {//关闭流
                    try {
                        data_input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(input!=null) {//关闭流
                    try {
                        input.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            
                    
        }
    }

}
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值