学习笔记:IO流

学习内容: IO流

1、初识Java IO

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

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

2、IO流的分类

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

2.2、按照读取数据方式不同进行分类:
字节流:按照字节的方式读取数据,一次读取一个字节(byte),等同于一次读取8个二进制位。这种流是万能的,什么类型的文件都可以读取。
字符流:按照字符的方式读取数据,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流只能读取纯文本文件。
在这里插入图片描述2.3、Java IO流的“四大家族”
“四大家族”的首领(都是抽象类):
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流

所有的流都实现了java.io.Closeable接口,都是可关闭的,都有close()方法。流毕竟是一个管道,用完之后一定要关闭,不然会耗费(占用)很多资源。

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

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

3、Java.io报下需要掌握的流

文件专属:
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.FileWriter

转换流(将字节流转换成字符流):
java.io.InputStreamReader
java.io.OutputStreamWriter

缓冲流专属:
java.io.BufferedInputStream
java.io.BufferedOutputStream
java.io.BufferedReader
java.io.BufferedWriter

数据流专属:
java.io.DataInputStream
java.io.DataOutputStream

标准输出流:
java.io.PrintWriter
java.io.PrintStream

对象专属流:
java.io.ObjectInputStream
java.io.ObjectOutputStream

3.1、FileInputStream

1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。
2、字节的方式,完成输入的炒作,完成读的操作(硬盘—>内存)
3、创建文件字节输入流对象:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis=null;
        //创建文件字节输入流对象
        try {
            //文件路径:D:\Tets(IDEA会自动把\编写成\\,因为java中\表示转义)
            //以下都是采用了绝对路径的方式
            //FileInputStream fis=new FileInputStream("D:\\Test.txt");
			//相对路径是从当前所在的位置为起点开始找!
			//IDEA默认的当前路径是Project的根。
            //在这里的流得放在try外面,要不然在在后面finally里面关的时候找不到
            //”D:\\Test.txt“也可以写成”D:/Test.txt“
            fis=new FileInputStream("D:\\Test.txt");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            //在finally语句中确保流一定关闭
            if (fis == null) {//避免空指针异常
                //关闭流的前提是:流不是空
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

(Test.txt里面放的数据是abcdef)
4、方法:

  1. public int read() 从该输入流读取下一个数据字节,如果达到流的末尾,返回-1。
    (以3中代码为例)
FileInputStream fis=null;
        try {
            fis=new FileInputStream("D:\\Test.txt");
            //public int read()从该输入流读取下一个数据字节,如果达到流的末尾,返回-1
            //开始读
//            int readDate=fis.read();//这个方法的返回值是:读取到的”字节“本身。
//            System.out.println(readDate);//97
//            readDate=fis.read();
//            System.out.println(readDate);//98
//            readDate=fis.read();
//            System.out.println(readDate);//99
//            readDate=fis.read();
//			  System.out.println(readDate);//100
//			  readDate=fis.read();
//			  System.out.println(readDate);//101
//			  readDate=fis.read();
//   		  System.out.println(readDate);//102
//			  readDate=fis.read();
//            System.out.println(readDate);//-1
            //用while循环读取
//            while(true){
//           	int readData=fis.read();
//          	if(readData==-1){
//					break;
//				}
//				System.out.println(readData);
//            }
			//while循环改进
            int readData=0;
            while((readData= fis.read())!=-1){
                System.out.println(readData);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //这里面的语句同上述代码
        }

缺点:一次读取一个字节(byte),这样内存和硬盘交互太频繁,基本上时间/资源都耗费在交互上面了。

  1. int read(byte[] b) 一次最多读取b.length个字节的数据,存到一个byte数组中。
    (以3中代码为例)
FileInputStream fis=null;
try {
    fis=new FileInputStream("D:\\Test.txt");
    //int read(byte[] b) 一次最多读取b.length个字节的数据,存到一个byte数组中。
    byte[] bytes=new byte[4];//准备一个4个长度的byte数组,一次最多读取4个字节
    int readCount=fis.read(bytes);//这个方法的返回值是:读取到的字节数量(不是字节本身)
    System.out.println(readCount);//4
    //将字节数组全部转换成字符串
    //System.out.println(new String(bytes));//abcd
    //不应该全部都转换,应该是读取了多少个字节就转换多少个。
    System.out.println(new String(bytes,0,readCount));//abcd

    readCount= fis.read(bytes);//第二次只能读取到2个字节
    System.out.println(readCount);//2
    //将字节数组全部转换成字符串
    //System.out.println(new String(bytes));//efcd
    //不应该全部都转换,应该是读取了多少个字节就转换多少个。
    System.out.println(new String(bytes,0,readCount));//ef

    readCount= fis.read(bytes);//1个字节都没有读到
    System.out.println(readCount);//-1
} 
//后面的catch和finally语句同上述代码

最终改良版:

FileInputStream fis=null;
try {
     fis=new FileInputStream("D:\\Test.txt");
     byte[] bytes=new byte[4];
     int readCount=0;
     while ((readCount=fis.read(bytes))!=-1){
       System.out.println(new String(bytes,0,readCount));
	}
}
//后面的catch和finally语句同上述代码
  1. int available() 返回流当中剩余的没有读到的字节数量
    (以3中代码为例)
FileInputStream fis=null;
try {
   fis=new FileInputStream("D:\\Test.txt");
   //读1个字节
   int readByte=fis.read();
   //还剩下可以读的字节数量
   System.out.println("剩下多少个字节没有读:"+fis.available());//5
}
//后面的catch和finally语句同上述代码
  1. long skip(long n) 跳过几个字节不读
    (以3中代码为例)
FileInputStream fis=null;
try {
   fis=new FileInputStream("D:\\Test.txt");
   fis.skip(3);//跳过3个
   System.out.println(fis.read());//100  跳过了97 98 99
}
//后面的catch和finally语句同上述代码

3.2、FileOutputStream

1、文件字节输出流,负责写。
2、从内存到硬盘。
3、创建文件字节输出流对象:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileOutputStream fos=null;
        try{
        	//此处的文件若是不存在,就会新建一个
            fos=new FileOutputStream("myfile");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

4、方法

  1. void write(byte[] b) 将byte数组全部写出(这种方式会将原文件清空,然后重新写入
    (以3中代码为例)
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileOutputStream fos=null;
        try{
            fos=new FileOutputStream("myfile");
            //开始写
            byte[] bytes={97,98,99,100};
            //将byte数组全部写出
            fos.write(bytes);//写出abcd

            //写完之后,最后一定要刷新
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

  1. void write(byte[] b, int off, int len) 将byte数组一部分写出(这种方式会将原文件清空,然后重新写入
    (以3中代码为例)
FileOutputStream fos=null;
        try{
            fos=new FileOutputStream("myfile");
            byte[] bytes={97,98,99,100};
            //将byte数组一部分写出
            fos.write(bytes,0,2);//写出ab
            fos.flush();
        }

在这里插入图片描述
若是不想将原文件清空再输入,而是直接在文件后面加。则需要在创建文件字节输出流对象的时候调用另一个构造方法。
FileOutputStream(name,append)
name—> 文件名
append—>如果为true,则将字节写入文件末尾处,而不是写入文件开始处。

fos=new FileOutputStream("myfile",true);

3.3、使用FileInputStream+FileOutputStream实现文件的拷贝

1、拷贝过程应该是一边读、一边写。
2、使用以上的字节流拷贝文件的时候,文件类型随意,万能的。什么样的文件都能拷贝。
例:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class FileInputStreamTest01 {
    public static void main(String[] args) {
        FileInputStream fis=null;
        FileOutputStream fos=null;

        try {
            //创建一个输入流对象
            fis=new FileInputStream("D:\\Test.txt");
            //创建一个输出流对象
            fos=new FileOutputStream("D:\\上机\\Test.txt");

            //刷新,输出流最后要刷新
            fos.flush();

            //最核心:一边读,一边写
            byte[] bytes=new byte[1024*1024];//1MB(一次最多拷贝1MB)
            int readCount=0;
            while ((readCount=fis.read(bytes))!=-1){
                fos.write(bytes,0,readCount);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //分开try,不要一起try
            //一起try的时候,其中一个出现异常,可能会影响到另一个流的关闭
            if(fos!=null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fis!=null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.4、FileReader

文件字符输入流只能读取普通文本。读取文本内容时,比较方便快捷。
(基本上和FileInputStream一样,照葫芦画瓢,只是用数组读取的时候变成了char数组)
例:
在这里插入图片描述

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderTest {
    public static void main(String[] args) {
        FileReader reader=null;
        try {
            //创建文件字符输入流
            reader=new FileReader("myfile");
            //开始读
            //一次读取一个字符参照FileInputStream里面的一次读取一个字符
            //这里是一次读取多个字符
            char[] chars=new char[4];
            int readCount=0;
            while ((readCount=reader.read(chars))!=-1){
                System.out.println(new String(chars,0,readCount));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

3.4、FileWriter

文件字符输出流,写,只能输出普通文本。(能用记事本编辑的)
(和FileOutputStream类似,照葫芦画瓢)
例:

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest {
    public static void main(String[] args) {
        FileWriter out=null;
        try {
            //和FilterOutputStream一样,
            //调用的这个构造方法在写入的时候,会先把文件内容清空再写入
            //out=new FileWriter("myfile");
            out=new FileWriter("myfile",true);

            //开始写
            char[] chars={'奥','特','曼','打','小','怪','兽'};
            out.write("\n");
            out.write(chars);
            out.write(chars,3,4);
            out.write("\n");
            out.write("我是迪迦");

            //刷新
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

在这里插入图片描述

3.5、使用FileReader+FileWriter实现文件拷贝(只能拷贝“普通文本”文件)

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileWriterTest {
    public static void main(String[] args) {
        FileReader in=null;
        FileWriter out=null;
        try {
            in = new FileReader("D:\\Test.txt");
            out = new FileWriter("D:\\上机\\Test.txt", true);

            //一边读一边写
            char[] chars = new char[1024 * 512];//1MB
            int readCount = 0;
            while ((readCount = in.read(chars)) != -1) {
                out.write(chars, 0, readCount);
            }

            //刷新
            out.flush();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

3.6、BufferedReader(BufferedInputStream和这个一样,照葫芦画瓢)

带头缓冲区的字符输入流。使用这个流的时候不需要自定义char数组,自带缓冲。
1、构造方法:BufferedReader(Reader in)
它这里面要求传入一个Reader,但是Reader是一个抽象类,不能new对象。所以我们用FileReader(Reader的子类)来new对象传进去。

2、当一个流的构造方法中需要一个流的时候,这个被传进来的流叫做:节点流。
外部负责包装的这个流,叫做:包装流,还有一个名字叫做:处理流。

例子:

import java.io.BufferedReader;
import java.io.FileReader;

public class BufferedReaderTest {
    public static void main(String[] args) throws Exception{
        //这里因为嫌麻烦,就直接把异常全部throws(上抛了)
        //不出现异常JVM就不会停止运行,
        // 但是大家写代码的时候不要在mian方法里面上抛异常,具体原因请参考:“学习笔记:异常”

        FileReader reader=new FileReader("myfile");
        BufferedReader br=new BufferedReader(reader);

        //readLine()方法读取一个文本行,但是不带换行符。
//        String line1=br.readLine();
//        System.out.println(line1);

        //改进
        String s=null;
        while ((s=br.readLine())!=null){
            System.out.println(s);
        }


        //关闭流
        //这里只用关闭最外层的流就行,里面的节点流会自动关闭
        //因为在源码中,BufferedReader这个流关闭的时候,里面的流也会关,源码如下
//        public void close() throws IOException {
//            synchronized (lock) {
//                if (in == null)
//                    return;
//                try {
//                    in.close();//这里会关闭传进来的节点流
//                } finally {
//                    in = null;
//                    cb = null;
//                }
//            }
//        }
            br.close();
    }
}

在这里插入图片描述

3.7、BufferedWriter(BufferedOutputStream和这个一样,照葫芦画瓢)

带有缓冲的字符输出流

import java.io.*;

public class BufferedWriterTets {
    public static void main(String[] args) throws Exception{
        BufferedWriter out=new BufferedWriter(new FileWriter("copy"));
        out.write("hello,world!");
        out.write("\n");
        out.write("迪迦奥特曼");
        out.flush();
        out.close();
    }
}

在这里插入图片描述

3.8、InputStreamReader(OutputStreamWriter和这个一样,照葫芦画瓢就行)

//节点流
FileInputStream in =new FileInputStream("myfile");

//通过转换流转换(InputStreamReader将字节流转换成字符流)
InputStreamReader reader=new InputStreamReader(in);

//这个构造方法只能传一个字符流。不能传字节流
BufferedReader br=new BufferedReader(reader);

3.9、DataOutputStream

数据专属的流。这个流可以将数据连同数据的类型一并写入文件。
注意:这个文件不是普通文本文档(这个文件用记事本打不开)
例:

import java.io.DataOutputStream;
import java.io.FileOutputStream;

public class Test06 {
    public static void main(String[] args) throws Exception{
        DataOutputStream dos=new DataOutputStream(new FileOutputStream("data"));
        //写数据
        byte b=100;
        short s=200;
        int i=300;
        long l=400L;
        float f=3.0F;
        double d=3.14;
        boolean sex=false;
        char c='a';

        dos.writeByte(b);
        dos.writeShort(s);
        dos.writeInt(i);
        dos.writeLong(l);
        dos.writeFloat(f);
        dos.writeDouble(d);
        dos.writeBoolean(sex);
        dos.writeChar(c);

        //刷新
        dos.flush();
        //关闭最外层
        dos.close();
    }
}

3.10、DataInputStream

数据字节输入流。DataOutputStream写的文件只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。
读的顺序需要和写的顺序一致。才可以正常取出数据。

import java.io.DataInputStream;
import java.io.FileInputStream;

public class Test07 {
    public static void main(String[] args)throws Exception {
        DataInputStream dis=new DataInputStream(new FileInputStream("data"));
        //开始读
        byte b=dis.readByte();
        short s=dis.readShort();
        int i=dis.readInt();
        long l=dis.readLong();
        float f=dis.readFloat();
        double d=dis.readDouble();
        boolean sex=dis.readBoolean();
        char c=dis.readChar();

        System.out.println(b);
        System.out.println(s);
        System.out.println(i);
        System.out.println(l);
        System.out.println(f);
        System.out.println(d);
        System.out.println(b);
        System.out.println(c);

        dis.close();
    }
}

在这里插入图片描述

3.11、PrintStream

标准的字节输出流。默认输出到控制台。

import java.io.FileOutputStream;
import java.io.PrintStream;

public class Test07 {
    public static void main(String[] args)throws Exception {
        //联合起来写
        System.out.println("hello,world!");

        //分开写
        PrintStream ps=System.out;
        ps.println("hello,zhangsan");

        //标准输出流不需要手动close()关闭
        /*这些是之前System类使用过的方法和属性
        System.gc();
        System.currentTimeMillis();
        PrintStream ps2=System.out;
        System.exit(0);
        System.arraycopy();
        */

        //可以改变标准输出流的输出方向
        //标准输出流不再指向控制台,指向“log”文件。
        PrintStream printStream=new PrintStream(new FileOutputStream("log"));
        //修改输出方向,将输出方向修改到"Log"文件
        System.setOut(printStream);
        //再输出
        System.out.println("我是迪迦奥特曼");
    }
}

在这里插入图片描述
在这里插入图片描述

3.12、PrintWriter

PrintWriter

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值