JavaSE值字节流与字符流

流操作简介

File类不支持文件内容处理,如果要处理文件内容,必须要通过流的操作模式来完成。流分为输入流和输出流。
在java.io包中,流分为两种:字节流与字符流

  1. 字节流(byte):InputStream、OutputStream
  2. 字符流(char):Reader、Writer

字节流与字符流操作的本质区别只有一个:字节流是原生的操作,而字符流是经过处理后的操作。
一般使用字节流(无论是网络传输还是磁盘数据保存均以字节为单位)。而所有磁盘中的数据必须先读取到内存后才能进行操作,而内存中会帮助我们把字节变为字符。所以一般只有处理中文文本时才会用到字符流。
不管使用的是字节流还是字符流,其基本的操作流程几乎是一样的,以文件操作为例。

  1. 根据文件路径创建File类对象 ;
  2. 根据字节流或字符流的子类实例化父类对象 ;
  3. 进行数据的读取或写入操作
  4. 关闭流(close())。

对于IO操作属于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)最后必须要进行关闭。

字节输出流(OutputStream)

OutputStream类的定义结构:

public abstract class OutputStream implements Closeable, Flushable

OutputStream类实现了Closeable,Flushable两个接口,这两个接口中的方法:

1. Closeable: public void close() throws IOException;
2. Flushable: public void flush() throws IOException;

在OutputStream类中还定义有其他方法:

1. 将给定的字节数组内容全部输出:public void write(byte b[]) throws IOException
2. 将部分字节数组内容输出:public void write(byte b[], int off, int len) throws IOException
3. 输出单个字节:public abstract void write(int b) throws IOException;

由于OutputStream是一个抽象类,所以要想为父类实例化,就必须要使用子类(如果要进行文件的操作,可以使用FileOutputStream),这个类的构造方法如下:

  1. 接收File类(覆盖):public FileOutputStream(File file) throws FileNotFoundException
  2. 接收File类(追加):public FileOutputStream(File file, boolean append)
    范例:实现文件的内容输出
import java.io.*;
import java.io.File;
import java.util.Date;

public class Test {
    public static void main(String[] args) {
            File file = new File("C:Users" + File.separator + "Administrator"
                    + File.separator + "Desktop"+File.separator+"Test.txt");
        OutputStream out= null;
        try {
          //  out = new FileOutputStream(file);//文本覆盖
            out = new FileOutputStream(file,true);//文本追加
            String msg="hello HL";
            try {
                //out.write(msg.getBytes());//文本全部输出
                out.write(msg.getBytes(),1,3);//文本部分输出(可能会出现乱码问题)
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

当使用FileOutputStream进行文本内容输出时,只要文件的父路径存在,FileOutputStream会自动创建文件。

AutoCloseable自动关闭支持

从JDk1.7开始追加了一个AutoCloseable接口,这个接口的主要目的是自动进行关闭处理,但是这种处理一般不好用,因为使用它必须结合try…catch
范例:观察AutoCloseable接口使用

class Msg implements AutoCloseable{
    void print(){
        System.out.println("就随便输出一下....");
    }

    @Override
    public void close() throws Exception {
        System.out.println("auto close....");
    }
}

public class Test {
    public static void main(String[] args) {
          try (Msg msg=new Msg()){
              msg.print();
          }catch (Exception e){

          }
    }
}

在这里插入图片描述

因为语法结构比较混乱,所以还是推荐大家使用close方法手工关闭资源~

字节输入流(InputStream)

InputStream类的定义如下:

public abstract class InputStream implements Closeable

在InputStream类中提供有如下方法:
1.输入

 public int read(byte b[]) throws IOException
 返回值:
  1.如果开辟的字节数组大小大于读取的数据大小,则返回的就是读取个数
  2.如果要读取的数据大于数组的内容,那么这个时候返回的就是数组长度
  3.如果没有数据了还在读,则返回-1(即数据已经读取完毕)

2.读取单个字节

public abstract int read() throws IOException//每次读取一个字节的内容,直到没有数据了返回-1:

同OutputStream的使用一样,InputStream是一个抽象类,如果要对其实例化,同样也需要使用子类。如果要对文件进行处理,则使用FileInputStream类。

范例:实现文件信息的读取

import java.io.*;
import java.io.File;
import java.util.Date;

public class Test {
    public static void main(String[] args)throws IOException {
        File file = new File("C:Users" + File.separator + "Administrator"
                + File.separator + "Desktop"+File.separator+"Test.txt");
            InputStream input=new FileInputStream(file);
            byte[] b=new byte[1024];
            int ret=input.read(b);
        System.out.println(ret);
            System.out.println(new String(b,0,ret));//要是字符数组没有被写满,一定要限制输出字符串的区间
            input.close();
    }
}

运行结果:
在这里插入图片描述

字符输出流(Writer)

个类的定义如下:

public abstract class Writer implements Appendable, Closeable, Flushable

字符输出流(与字节输出流相比,字符输出流多了一个可以直接传String类型的方法)

public void write(String str) throws IOException

如果要操作文件使用FileWriter子类
范例:通过Writer实现输出

import java.io.*;
import java.io.File;
import java.util.Date;

public class Test {
    public static void main(String[] args)throws IOException {
        File file = new File("C:Users" + File.separator + "Administrator"
                + File.separator + "Desktop"+File.separator+"Test.txt");
        Writer writer=new FileWriter(file);
        writer.write("hello");
        writer.close();
    }
}

字符输入流(Reader)

在Reader类中没有方法可以直接读取字符串类型,这个时候只能通过字符数组进行读取操作
如果要操作文件使用FileReader子类
范例:通过文件读取数据

import java.io.*;
import java.io.File;
import java.util.Date;

public class Test {
    public static void main(String[] args)throws IOException {
        File file = new File("C:Users" + File.separator + "Administrator"
                + File.separator + "Desktop"+File.separator+"Test.txt");
        Reader reader=new FileReader(file);
        char[] ch=new char[1024];
        int ret=reader.read(ch);
        System.out.println(ret);
        System.out.println(new String(ch,0,ret));
        reader.close();
    }
}

在这里插入图片描述

字节流&字符流的区别

通过上的学习我们可以发现,使用字节流和字符流从代码形式上区别不大。但是如果从实际开发来讲,字
节流一定是优先考虑的,只有在处理中文时才会考虑字符流。因为所有的字符都需要通过内存缓冲来进行处理。
所有字符流的操作,无论是写入还是输出,数据都先保存在缓存中。我们可以验证一下,就是写一个字符输出流,但是不关闭字符流,运行,你会发现文件里什么也没有被写入,难道是代码错了?不。是你的运行结果此时还在缓冲区里呆着呢,不妨试一下关闭字节流后运行一下,再观察文件中的内容,你要输出到文件中的内容一定就在里面。然后重复上面的操作,在字节流中跑一下,你就立马明白字节流和字符流的区别啦~
除了关闭字符流,也可以使用字符流缓冲区刷新flush()
范例:字符流刷新操作

import java.io.*;
import java.io.File;
import java.util.Date;

public class Test {
    public static void main(String[] args)throws IOException {
        File file = new File("C:Users" + File.separator + "Administrator"
                + File.separator + "Desktop"+File.separator+"Test.txt");
    Writer out=new FileWriter(file);
      String msg="hhh";
      out.write(msg);
      out.flush();
    }
}
发布了87 篇原创文章 · 获赞 73 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/HL_HLHL/article/details/84840287