Java学习笔记 -IO流1

概述

1. 按照字节的方式读取:

  • 等同于一次读取8个二进制位;
  • 是万能的,什么类型都能读取,包括文本、声音、图片。。
  • 例如:a重点
  • 第一次读取a 一个字节;第二次读取“重”的前半部分 一个字节

2. 按照字符去读取数据,一次读取一个字符,为了方便读取普通的文本文件

  • 不能读取除了普通文本之外的任何类型,连Word文件也无法读取
  • 例如:a重点
  • 第一次读取a 一个字节;第二次读取“重” 两个字节

3. Java IO流四大家族

(1)四大首领:
  • java.io.InputSteam 字节输入流

  • java.io.OutputStream 字节输出流

  • java.io.Reader 字符输入流

  • java.io.Writer 字符输出流

(2)相关知识:
  • 以"Stream"结尾都是字节流,以"Reader/Writer"结尾都是字符流
  • 四大家族的首领都是抽象类 (abstract class)
  • 所有流都实现了java.io.closeable接口,都是可以关闭的,都有close()方法
  • 所有的输出流都实现了java.io.Flushable接口,输出流在最终输出之后,一定要flush()
    表示刷新一下,这个刷新将管道中剩余的未输出的数据强行输出完,如果没有flush()可能导致数据丢失

4. 16个常用的类

(1)文件专属:
  • FileInputStream
  • FileOutputStream
  • FileReader
  • FileWriter
(2)转换流:(将字节流转换未字符流)
  • InputStreamReader
  • OutputStreamWriter
(3)缓冲流:
  • BufferedReader
  • BufferedWriter
  • BufferedInputStream
  • BufferedOutputStream
(4)数据流:
  • DataInputStream
  • DataOutputStream
(5)标准输出流:
  • PrintWriter
  • PrintStream
(6)对象专属流:
  • ObjectInputStream
  • ObjectOutputStream

文件专属流

  • 本段通过几个示例程序表述知识点
  • 文件字节流和字符流的用法类似,所以只讲字节流
  • 有一点区别:字节流使用byte[]数组缓存,字符流使用char[]数组缓存
  • 文件字节流读取含中文的普通文本可能会乱码,读取含中文的普通文本最好使用文件字符流

示例1 -FileInputStream:

(1)知识点:

  • 文件路径:绝对路径 & 相对路径
  • 方法:int read() 返回读取字符的编码,如果读取到了文件结尾就返回-1

(2)程序:

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

public class FileInputSteamTest01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            /*
            (1)绝对路径的两种表达:     "\"因为表示转义
            FileInputStream fis = new FileInputStream("D:\biancheng\java\file\chapter19\111.txt");
            fis = new FileInputStream("D:/biancheng/java/file/chapter19/111.txt");
            (2)相对路径:
            IDEA默认的当前目录是工程初始模块的根目录下
             */
            fis = new FileInputStream("src/1/111.txt");

            //如果都到末尾没有数据,会返回-1
            int readData = 0;
            while((readData = fis.read()) != -1){
                System.out.println(readData);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

示例2 -FileInputStream:

(1)知识点:

  • 使用示例1的方法,会造成和硬盘的交互次数过多,应该提高每一次交互所读取的字节数
  • 方法:int read(byte[] b) 一次最多读取b.length个字节,返回读取的字节数,如果读取到了文件结尾就返回-1
  • 常用方法:int available() 返回剩下未读取的字节数量
  • 常用方法:long skip(long n) 跳过n个字节不读,返回实际跳过的字节数目

(2)程序:

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

        try {
            fis = new FileInputStream("src/1/111.txt");
            
            int retValue = 0;
            //这个方式不适合读大文件,因为bytes数组不能太大
            byte[] bytes = new byte[fis.available()];  //实例化一个和文件字节数相同的byte数组
            fis.skip(3);   //跳过3个字符不读取
            fis.read(bytes);
            System.out.println(new String(bytes));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

示例3 -FileOutputStream:

(1)知识点:

  • 构造方法:fos = new FileOutputStream(String name,boolean append)
    append:是否以追加模式写入,默认是false
    其他构造方法查阅参考手册

  • 方法:write(byte b)
    write(byte b, int off, int len)

  • 方法:flush(): 在最后一次输出之后,一定要调用flush(),就好像把水管里还剩余的水全部输送出去

(2)程序:

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

public class FileOutputStreamTest01 {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //以追加模式写入,默认是false
            fos = new FileOutputStream("myfile",true);
            byte[] bytes = {96,97,98,99};
            fos.write(bytes);

            //写入bytes数组的部分内容
            fos.write(bytes, 0, 2);

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

示例4 -复制文件

  • 重点掌握这种写法

程序:

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

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

        try {
            fis = new FileInputStream("D:\迅雷下载\星露谷\README.md");
            fos = new FileOutputStream("D:\myPicture.png");
            //一次读取最多读取1M
            byte[] bytes = new byte[1024 * 1024];
            int retValue = 0;
            while ((retValue = fis.read(bytes)) != -1){
                //一定要指定offset和长度,否则如果读取byte数组不满时,会写入一部分上一次读取的字符
                fos.write(bytes,0,retValue);
            }

            fos.flush();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //分别进行try catch,防止一个出现异常,另一个无法关闭
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
原文地址:https://www.cnblogs.com/zy200128/p/13021181.html