java.IO字节流和字符流详解

本文深入讲解Java IO流的分类及应用,包括输入流、输出流、字节流、字符流的概念,以及InputStream、OutputStream、Reader、Writer等核心类的使用方法。通过实例演示文件的读写操作。

IO流的分类
在学习字节流和字符流之前因该先学习IO流的分类,效果会更好

有多种分类方式:

一种方式是按照流的方向进行分类: 以内存作为参照物,
往内存中去,叫做输入(Input)。或者叫做读(Read)。
从内存中出来,叫做输出(Output)。或者叫做写(Write)。

	另一种方式是按照读取数据方式不同进行分类:

有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等…

			假设文件file1.txt,采用字节流的话是这样读的:
				a中国bc张三fe
				第一次读:一个字节,正好读到'a'
				第二次读:一个字节,正好读到'中'字符的一半。
				第三次读:一个字节,正好读到'中'字符的另外一半。

		有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取
		普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯
		文本文件,连word文件都无法读取。

			假设文件file1.txt,采用字符流的话是这样读的:
				a中国bc张三fe
				第一次读:'a'字符('a'字符在windows系统中占用1个字节。)
				第二次读:'中'字符('中'字符在windows系统中占用2个字节。)

流的分类 : 输入流、输出流 字节流、字符流

java的输入流主要以InputStream和Reader作为基类,而输出流主要以OutputStream和writer作为基类。(他们都是抽象基类,无法创建)

java IO流这块有四大家族:
四大家族的首领:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流

	java.io.Reader		字符输入流
	java.io.Writer		字符输出流

	四大家族的首领都是抽象类。(abstract class)

	所有的流都实现了:
		java.io.Closeable接口,都是可关闭的,都有close()方法。
		流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭,
		不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。

	所有的输出流都实现了:
		java.io.Flushable接口,都是可刷新的,都有flush()方法。
		养成一个好习惯,输出流在最终输出之后,一定要记得flush()
		刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据
		强行输出完(清空管道!)刷新的作用就是清空管道。

		注意:如果没有flush()可能会导致丢失数据。


注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。

字节流和字符流
字节流的操作单元是——字节
字符流的操作单元是——字符

InputStream和Reader
InputStream和Reader是所有的输入流的抽象基类,它们本身并不能用来创建实例执行输入,但是他们都有实现类,用于读取文件的输入流:FileInputStream和FileReader.

InputStream接口中的相关方法:

在这里插入图片描述

Reader接口中的相关方法:
在这里插入图片描述

相应方法的详解:

在这里插入图片描述

分析程序读取文件的原理:

程序通过调用read()方法每次读取一个字节或者字符,但是这样效率太低,也可以通过read(char[]
cbuf)或者read(byte[]
b)的方法来一次读取多个字节或者字符。当使用数组来读取文件的时候可以理解为要读取的文件是一个大缸中的水,而数组是一个瓢一次最多只能读取
数组.lengt的字节或者字符,所以需要通过循环连续取水,直到最后,当文件全部去除的时候read()方法会返回-1,即表明输入流结束,这个可以用来判断文件是否全部取出的标志。

public class FileInputStreamTest {
    public static void main(String[] args) throws FileNotFoundException {
        //创建字节输入流
        final FileInputStream file=new FileInputStream("C:\\java File\\undefined\\src\\网课\\IO\\FileInputStreamTest.java");
        try (file){
            //创建一个数组,可以读取1024个字节,
            byte[] by=new byte[1024];
            //用于保存实际读取的字节数
            int hasRead=0;
            //使用循环来重复读取字节的过程
            while((hasRead=file.read(by))!=-1){
                //将数组中读取到的字节转换成字符串输出
                System.out.println(new String(by,0,hasRead ));

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注解:因为异常继承了AutoClousable接口或者是Closeable接口,所以可以使用java9新增强的资源自动回收机制。

创建一个新的String对象将数组中的字节转换成默认色字符集:
在这里插入图片描述

public class FileReaderTest  {
     public static void main(String[] args) throws IOException {
        //创建字符输入流
         FileReader file = new FileReader("C:\\java File\\undefined\\src\\网课\\IO\\FileReaderTest.java");

         try(file) {
           //创建一个字符集的数组
            char[] ch=new char[32];
            //用来保存read()方法的放回值
            int hasNext=0;
            while((hasNext=file.read(ch))!=-1){
                //一次转化一个数组的长度的字符
                System.out.println(new String(ch,0,hasNext));

            }
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
}

OuterputStream和Writer

OutputStream和wirter是所有的输入流的抽象基类,它们本身并不能用来创建实例执行输入,但是他们都有实现类,用于读取文件的输入流:FileOutputStream和FileWriter.

eg:实现文件的输入和输出

public class FileOutputStreamTest {


    public static void main(String[] args) throws FileNotFoundException {
        //创建字节输入流
        FileInputStream fileinput=new FileInputStream("C:\\java File\\undefined\\src\\网课\\IO\\FileOutputStreamTest.java");
       //创建字节输出流
        FileOutputStream fileoutput= new FileOutputStream("F:\\MySQL\\test.java");
        try(fileinput;fileoutput){
            byte[] by=new byte[1024*1024];
            int hasNext=0;
            while((hasNext=fileinput.read(by))!=-1){
                //一边读取一边写入
                fileoutput.write(by,0,hasNext);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行程序可以看到在相应的文件夹下面多了一个文件,

注意:

使用java的IO流执行的时候,不要忘记关闭输出流,关闭输出流可以保证流的物理资源被回收,还可以将输出流缓冲其中的数据flush()到物理节点里,(因为程序会在执行Close()方法之前自动的执行输出流中的flush()方法)。

public class text05 {
    public static void main(String[] args) {
        FileOutputStream fos=null;
        try {
            fos=new FileOutputStream("F:\\text.TXT");
            byte[] by=new byte[]{35,24,5,44,45,51,5};
            //如果当前写盘的路径不存在,系统会自动新建

            //这种方式会将源文件先清空在重新写入;
            fos.write(by);
            //写完之后一定要刷新文件
            fos.flush();

            //以追加的方式写入文件
            fos=new FileOutputStream("F:\\text.TXT",true);
            fos.write(by);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally{

        }

    }
}

如果希望直接输出字符则选用文件字符输出流效果更好;

eg:
public class FireWritertest {
    public static void main(String[] args) throws IOException {
        FileWriter filewriter =new FileWriter("F:\\MySQL\\FireWriter.java",true);
        try(filewriter){
            filewriter.write("日出而作,日入而息。");
            filewriter.write(" 凿井而饮,耕田而食。");
            filewriter.write("帝力于我何有哉!");
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值