Java IO流

什么是IO流

IO

  • IO(即in和out)也就是输入和输出,指应用程序和外部设备之间的数据传递,常见的外部设备包括文件、管道、网络连接。

Java 中是通过流处理IO 的,那么什么是流?

流(Stream)

  • 流(Stream)是一个抽象的概念,是指一连串的数据(字符或字节),是以先进先出的方式发送信息的通道。

当程序需要读取数据的时候,就会开启一个通向数据源的流,这个数据源可以是文件,内存,或是网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。这时候你就可以想象数据好像在这其中“流”动一样。

流的特点

  • 先进先出:最先写入输出流的数据最先被输入流读取到。
  • 顺序存取:可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile除外)
  • 只读或只写:每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

作用
IO流用来处理设备之间的数据传输,上传文件和下载文件,Java对数据的操作是通过流的方式,Java用于操作流的对象都在IO包中。
分类
IO流操作一般分为两类:字符流 和 字节流

字符流和字节流的区别

字符流

  • 字符流是由字符组成的
  • 主要用在处理二进制数据,它是按字节来处理的但实际中很多的数据是文本。
  • Java里字符由两个字节组成.
  • 1字符=2字节,字符流是采用UTF编码,支持中文的
  • 字节流一般用来处理图像、视频、音频、PPT、Word等类型的文件。

字节流

  • 字节流是由字节组成的
  • 字节流是最基本的,采用ASCII编码
  • 按虚拟机的encode来处理,也就是要进行字符集的转化。
  • 字符流一般用于处理纯文本类型的文件,如TXT文件等,但不能处理图像视频等非文本文件。

字节流可以处理一切文件,而字符流只能处理纯文本文件

IO流的基本使用

在这里插入图片描述

字节流

1. InputStream 和 OutputStream

InputStream 和 OutputStream为各种输入输出字节流的基类,所有字节流都继承这两个基类。

2. FileInputStream 和 FileOutputStream

这两个从字面意思很容易理解,把硬盘文件中的数据,读取到内存中使用,是对文件的字节流操作,也会最常见的IO操作流。

    /*
     * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
     */
    public static void readFileByBytes(String inFile, String outFile) {
        File file = new File(fileName);
        InputStream in = null;
        OutputStream out = null;
        try {
            byte[] tempbytes = new byte[100];
            int byteread = 0;
            in = new FileInputStream(inFile);
            out = new FileOutputStream(outFile);
            //read() 将此输入流中的数据读取到字节数组中
            while ((byteread = in.read(tempbytes)) != -1) {
                out.write(tempbytes, 0, byteread);
            }
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e1) {
                }
                try {
                    out.close();
                } catch (IOException e1) {
                }
            }
        }
    }
3、BufferedInputStream 和 BufferedOutputStream

BufferedInputStream是带缓冲区的输入流,它继承于FilterInputStream。默认缓冲区大小是8M,能够减少访问磁盘的次数,提高文件读取性能。
BufferedOutputStream是带缓冲区的输出流,它继承于FilterOutputStream,能够提高文件的写入效率。
它们提供的“缓冲功能”本质上是通过一个内部缓冲区数组实现的。例如,在新建某输入流对应的BufferedInputStream后,当我们通过read()读取输入流的数据时,BufferedInputStream会将该输入流的数据分批的填入到缓冲区中。每当缓冲区中的数据被读完之后,输入流会再次填充数据缓冲区;如此反复,直到我们读完输入流数据。

    public static void readAndWrite(String[] args) {    
        try {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("f:/a.mp3"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("f:/b.mp3"));
            byte[] b=new byte[1024];
            int len=0;
            while(-1!= (len = bis.read(b, 0, b.length))) {
                bos.write(b, 0, len);
            }
 
        } catch (FileNotFoundException e) {
            System.out.println("文件异常");
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if (null! = bos){
                bos.close();
            }
            if (null! = bis){
                bis.close();
            }
        }
    }

字符流

1. InputStreamReader 和 OutputStreamWriter

InputStreamReader 和 OutputStreamWriter为各种输入输出字符流的基类,所有字符流都继承这两个基类。实际上,这两个类内部各自持有一个inputStream 和 outputStream对象,相当于是对inputStream 和 outputStream进行了包装,将输入字节流转换成字符流,便于读写操作。

    /**
     * 以字符为单位读取文件,常用于读文本,数字等类型的文件
     */
    public static void readFileByChars(String fileName) {
        File file = new File(fileName);
        Reader reader = null;
        try {
            System.out.println("以字符为单位读取文件内容,一次读一个字节:");
            //1. 一次读一个字符
            reader = new InputStreamReader(new FileInputStream(file));//可以是任意的InputStream类,不一定必须是FileInputStream
            int tempchar;
            while ((tempchar = reader.read()) != -1) {
                if (((char) tempchar) != '\r') {
                    System.out.print((char) tempchar);
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        try {
            System.out.println("以字符为单位读取文件内容,一次读多个字节:");
            //2. 一次读多个字符
            char[] tempchars = new char[30];
            int charread = 0;
            reader = new InputStreamReader(new FileInputStream(fileName));
            while ((charread = reader.read(tempchars)) != -1) {
                for (int i = 0; i < charread; i++) {
                    if (tempchars[i] != '\r') {
                        System.out.print(tempchars[i]);
                    }
                }
            }
 
        } catch (Exception e1) {
            e1.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
    }
2. FileReader 和 FileWriter

FileReader 和 FileWriter分别继承自 inputStreamReader 和 outputStreamWriter。它是对读取文件操作系统的封装,所有的读写都是直接操作文件系统。因此如果是频繁读写操作,不建议使用FileReader 和 FileWriter,性能将会非常低,这时你需要使用BufferedReader。

(1)FileWriter类
构造方法:
FileWriter fw = new FileWriter(String fileName);//创建字符输出流类对象和已存在的文件相关联。文件不存在的话,并创建。
FileWriter fw = new FileWriter(String fileName,boolean append);//创建字符输出流类对象和已存在的文件相关联,并设置该该流对文件的操作是否为续写。
主要方法:

write(char[] buffer, int offset, int count) //将字符数组写入,offset为数组的起始地址,count为需要写入的字符数
void write(String str) //写入字符串。当执行完此方法后,字符数据还并没有写入到目的文件中去。此时字符数据会保存在缓冲区中。
viod flush() //刷新该流中的缓冲。将缓冲区中的字符数据保存到目的文件中去。
viod close() //关闭此流。在关闭前会先刷新此流的缓冲区。在关闭后,再写入或者刷新的话,会抛IOException异常。

(2)FileReader类
构造方法:
FileReader fr = new FileReader(String fileName); //使用带有指定文件的String参数的构造方法。创建该输入流对象。并关联源文件。
主要方法:
int read(); // 读取单个字符。返回作为整数读取的字符,如果已达到流末尾,则返回 -1。
int read(char []cbuf); //将字符读入数组。返回读取的字符数。如果已经到达尾部,则返回-1。
void close(); //关闭此流对象。释放与之关联的所有资源。

    public static void readAndWrite() {
        FileReader fr = null;
        FileWriter fw = null;
        try {
            fr = new FileReader("C:\\my.txt");
            fw = new FileWriter("D:\\you.txt");
            //1.读一个字符,写一个字符方法
            int ch = 0;  
            while ((ch = fr.read()) != -1) {  
                fw.write(ch);  
            } 
            
            //2.读一个数组大小,写一个数组大小方法。
            char []buf = new char[1024];
            int len = 0;
            while((len = fr.read(buf)) != -1){
                fw.write(buf, 0, len);              
            }
            
            //3.直接写一个字符串
            fw.write("hello world!");
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            if (fr != null)
                try {
                    fr.close();
                } catch (Exception e2) {
                    throw new RuntimeException("关闭失败!");
                }
            if (fw != null){
                try {
                    fw.close();
                } catch (IOException e) {
                    throw new RuntimeException("关闭失败!");
                }
            }
        }
    }
3. BufferedReader 和 BufferedWriter

(1)BufferedReader和BufferedWriter类各拥有8192字符的缓冲区。当BufferedReader在读取文本文件时,会先尽量从文件中读入字符数据并置入缓冲区,而之后若使用read()方法,会先从缓冲区中进行读取。如果缓冲区数据不足,才会再从文件中读取,使用BufferedWriter时,写入的数据并不会先输出到目的地,而是先存储至缓冲区中。如果缓冲区中的数据满了,才会一次对目的地进行写出。
(2)从标准输入流System.in中直接读取使用者输入时,使用者每输入一个字符,System.in就读取一个字符。为了能一次读取一行使用者的输入,使用了BufferedReader来对使用者输入的字符进行缓冲。readLine()方法会在读取到使用者的换行字符时,再一次将整行字符串传入

    /**
     * 以行为单位读取文件,常用于读面向行的格式化文件
     */
    public static void readWithBufferedReader(String fileName) {
        File file = new File(fileName);
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            String tempString = null;
            int line = 1;
            // 一次读入一行,直到读入null为文件结束
            while ((tempString = reader.readLine()) != null) {
                System.out.println("line " + line + ": " + tempString);
                line++;
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e1) {
                }
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值