Java基础---IO编程(字节流与字符流)

Java基础—IO编程(字节流与字符流)



字节流与字符流

字节流与字符流简介

  流是什么呢?听到流我们第一个想到的是什么,水流?数据流?都不是。这里我们对流的定义主要是数据的处理方式,以及目标内容的处理机制,流分为输入流和输出流两种,在java.io包中针对输入输出流分为两种类型:

   · 字节操作流:OutputStream(字节输出流)、InputStream(字节输入流);
   · 字符操作流:Writer(字符输出流)、Reader(字符输入流)。

另外,输入流和输出流的定义如下:

   · 输入流: 程序可以从中读取数据的流。
   · 输出流: 程序能向其中写入数据的流。

字节输出流OutputStream

OutputStream流是实现字节输出的操作类,定义如下:

public abstract class OutputStream extends Object implements Closeable,Flushable

  OutputStream是在JDK1.0的时候提供的,而后在JDK1.5的时候设计了两个新的接口:Closeable和Flushable,而且在JDK1.7的时候Closeable又成了AutoCloseable接口的子类。

Closeable和Flushable接口的定义如下:

//Closeable 接口定义
public interface Closeable extends AutoCloseable{
	public void close() throws IOException;
}

//Flushable 接口定义
public interface Flushable{
	public void flush() throws IOException;
}

  OutputStream类提供的是一个流的输出操作,所以在OutputStream类中提供有三个输出方法。

序号方法名称类型描述
1public abstract void write(int b)throws IOException方法输出单个字节数据
2public void write(byte[] b)throws IOException方法输出全部字节数组的数据
3public void write(byte[] b,int off,int len)方法输出部分字节数组的数据

  OutputStream类中的write()方法是针对字节数据进行处理的,但是OutputStream类是一个抽象类,需要通过子类的实例化对象才可以访问类中的方法,此时我们要进行文件处理选用java.io.FileOutputStream子类实现。

对于抽象类的子类来说,我们需要关注的点有两个:

   · 1.子类中完成对父类抽象方法的覆写;
   · 2.子类构造实例化对象向上转型;

  此时由于是系统给出的子类,只需要关注构造方法即可。

序号方法名称类型描述
1public FileOutputStream(File file)throws FileNotFoundException构造方法设置文件的输出流,每次对原始数据进行覆盖
2public FileOutputStream(File file,boolean append)throws FileNotFoundException构造方法如果将append的内容设置为true,表示进行内容增加

使用构造方法实现磁盘数据的输出:

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

//使用OutputStream实现磁盘数据的输出
public class Test01{
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator+"zhang"+File.separator+"da"+File.separator+"pao.txt");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        OutputStream output = new FileOutputStream(file);
        output.write("zhangdapao".getBytes());
        output.close();
    }
}

  此时使用构造方法就完成了对文件内容的覆盖操作。如果想对内容进行追加内容,可以使用另一个构造方法完成。如下所示:

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

//使用OutputStream实现磁盘数据的输出
public class Test01{
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator+"zhang"+File.separator+"da"+File.separator+"pao.txt");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        OutputStream output = new FileOutputStream(file);
        output.write("zhangdapao".getBytes());
        output.close();
    }
}

字节输入流InputStream

InputStream流是实现字节输出的操作类,定义如下:

public abstract class InputStream extends Object implements Closeable

  通过观察定义可以发现,进行InputStream和OutputStream类有所区别,InputStream没有实现Flushable接口,因为在读的过程是不需要使用到系统的缓冲区的,缓冲区是为了防止过多的写入,在InputStream类中提供有如下的读取操作方法:

序号方法名称类型描述
1public abstract int read()throws IOException方法读取单个字节数据,没有数据返回“-1”
2public int read(byte[] b)throws IOException方法将内容读取到字节数组中,返回读取个数,没有数据返回“-1”
3public int read(byte[] b,int off,int len方法读取部分内容到字节数组中,返回读取个数,没有数据返回“-1”
4public byte[] readAllBytes()方法返回全部的字节数据
5public int available()方法获取可用的长度

  InputStream类是一个抽象类,可以利用FileInputStream子类为其进行实例化,实现文件流的操作,构造方法定义为:

 public FileInputStream(File file)throws FileNotFoundException;

使用InputStream实现文件数据的读取,示例如下:

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;


//使用InputStream实现文件数据的读取
public class Test01{
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator+"zhang"+File.separator+"da"+File.separator+"pao.txt");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        //定义一个字节数组,用来保存数据
        byte data [] = new byte[1024];
        InputStream input = new FileInputStream(file);
        //获取读取的字节个数
        int len = input.read(data);
        //打印字节数组中的数据
        System.out.println(new String(data));
        input.close();
    }
}


执行结果:D:\java\jdk-11\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2018.3.2\lib\idea_rt.jar=56626:D:\IDEA\IntelliJ IDEA 2018.3.2\bin" -Dfile.encoding=UTF-8 -classpath D:\JavaTest\out\production\Test01 zhang.da.pao.Test01
zhangdapao111

Process finished with exit code 0


  从JDK1.9之后InputStream追加了一个新的方法“readAllBytes()”,这种方法特点在于可以直接返回所有字节,不需要考虑数组大小。但仅适用于小文件,不然程序会崩溃。

字符输出流:Writer

  上文所述的OutputStream类是可以实现输出操作,但是输出的时候使用的是字节类型,但多数情况下使用的最多的还是字符串类型,为了简化输出操作,JDK1.1开始提供了字符输出流,Writer类的定义为:

Public abstract class Writer extends Object implements Appendable,Closeable,Flushable

  从定义我们可以看出相比较OutputStream类,Writer类多实现了一个Appendable接口,里面只有一个append()方法;让我们来观察一下Appendable接口里面的内容;

public interface Appendable{
	public Appendable append(CharSequence csq)throws IOException;
	public Appendable append(CharSequence csq,int start, int end)throws IOException;
	public Appendable append(Char c)throws IOException;
}

  使用Writer类进行输出的时候,最大的特点在于可以直接进行字符串的数据处理,Writer类是一个抽象类,可以利用FileWriter子类为其进行实例化,实现文件流的操作,构造方法定义为:

序号方法名称类型描述
1public void write(String str)throws IOException方法在文件上写入字符串数据

使用FileWriter进行文件操作:


import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

//使用FileWriter进行程序的数据输出,文件的写入操作
public class Test01{
   public static void main(String[] args) throws Exception {
       File file =new File("d:"+File.separator+"zhang"+File.separator+"da"+File.separator+"pao.txt");
       if(!file.getParentFile().exists()){
           file.getParentFile().mkdirs();
       }
       Writer writer = new FileWriter(file);
       //写入字符串数据
       writer.write("zhangdapao006");
       //追加写入
       writer.append("zhangdapao007");
       writer.close();
   }
}

在这里插入图片描述
  使用Writer最大的有时就在于可以直接进行字符串的输出处理。

字符输入流:Reader

Reader是实现字符数据的输入流类,定义如下:

public abstract class Reader extends Object implements Readable,Closeable

  与InputStream类有所区别的是,Readable类中没有提供读取全部数据的方法,避免造成内存溢出,但实现方法与前面讲的三个类一样,都是使用子类对象实例化来实现,如下例所示:

//使用Reader读取数据
public class Test01{
    public static void main(String[] args) throws Exception {
        File file =new File("d:"+File.separator+"zhang"+File.separator+"da"+File.separator+"pao.txt");
        if(!file.getParentFile().exists()){
            file.getParentFile().mkdirs();
        }
        //定义一个字节数组,用来保存数据
        char data [] = new char[1024];
        Reader reader = new FileReader(file);
        //获取读取的字节个数
        int len = reader.read(data);
        //打印字节数组中的数据
        System.out.println(new String(data));
        reader.close();
    }
}

执行结果:D:\java\jdk-11\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2018.3.2\lib\idea_rt.jar=55635:D:\IDEA\IntelliJ IDEA 2018.3.2\bin" -Dfile.encoding=UTF-8 -classpath D:\JavaTest\out\production\Test01 zhang.da.pao.Test01
zhangdapao006zhangdapao007                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

Process finished with exit code 0

字节流与字符流区别

  在实际开发中该选用哪一种输入输出流呢?先来看看两者的区别:

  字节操作属于基础的二进制操作形式,在网络、文件等操作几乎都是以字节数据为主,但是字节数据不方便进行中文的处理,所以对于中文处理应使用字符流。

  还有比较特殊的一点是:在进行网络传输或者磁盘数据存储的时候,所存放的内容都属于字节数据。

  close()方法可以自动清空缓冲区的内容,另外清空缓存区还可以使用flush方法实现。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值