深入理解io流
侧边栏壁纸
  • 累计撰写 24 篇文章
  • 累计收到 177 条评论

深入理解io流

xiaoyu
2022-11-22 / 0 评论 / 44 阅读 / 正在检测是否收录...

感谢博文——>史上最骚最全最详细的IO流教程,没有之一!一键跳转
注:以此博文为基础进行复习查阅如若有哪方面侵权,请联系小宇(不懂这方面,您的博文也未明确),总之,这篇写的真好

明确

字节(byte):是计算机中 数据处理 的基本单位,习惯上用大写  B  来表示,1B(byte,字节)= 8bit(位)
字符:是指计算机中使用的字母、数字、字和符号

(1)
输入输出是相对内存而言
输入:将硬盘中的数据读到内存中使用
输出:将内存中的数据写到硬盘中保存

源(读、输入流)目的(写、输出流)
字节: InputStream字节: OutputStream
文本、字符:Reader文本、字符:Writer

(3)

表头源设备:对应目的设备:
硬盘文件 File开头文件 File开头
内存数组,字符串数组,字符串
键盘/屏幕System.inSystem.out
网络SocketSocket

流的主要分类

1676705876.png
总结:有Stream即为字节流(注:OutputStreamWriter与InputStreamReader 是字节流通向字符流的桥梁)
所有字符流都含有Writer、Reader

IO流

(一)、
一、根据数据的流向分为:输入流 和 输出流。

①输入流 :把数据从其他设备上读取到内存中的流。
②输出流 :把数据从内存 中写出到其他设备上的流。
二、根据数据的类型分为:字节流 和 字符流。

①字节流 :以字节为单位,读写数据的流。(适合读取视频声音图片等二进制文件)

一切文件数据(文本、图片、视频等)在存储时,都是以二进制数字的形式保存,都一个一个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。

②字符流 :以字符为单位,读写数据的流。(纯文本文件:文字、数字等)

(二)、字节流
一、字节输出流(OutputStream)
此抽象类是表示输出字节流的所有类的超类(父类),子类能改继承其方法。输出流接受输出字节并将这些字节发送到某个接收器。
需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法。

1、FileOutputStream 以我的英格力士水平觉得他是文件输出流,用于将数据写出到文件。
2、FileOutputStream构造方法
不管学啥,只要是对象,就从构造方法开始!

FileOutputStream fos = new FileOutputStream("学io.txt");

就这句代码,类似这样创建对象都做了三件事情:
1、调用系统功能去创建文件【输出流对象会自动创建】(没有该文件才自动创建、有则清空数据)
2、创建fos对象
3、把fos对象指向这个文件

import java.io.*;
public class Fostest {
    public static void main(String[] args) {
        FileOutputStream fos;
        try {
            fos = new FileOutputStream("fos.txt");
            // 字符串转换为字节数组
            byte[] b = "小宇在学io".getBytes();// 默认UTF-8
            fos.write(b, 0, 6);// 写出字节数组数据
            fos.close();
        } catch (IOException e) {
        }
    }
} 
输出结果:
小宇(一个汉字三个字节)

二、字节输入流(InputStream)

此抽象类是表示字节输入流的所有类的超类。 
需要定义 InputStream 子类的应用程序必须总是提供返回下一个输入字节的方法。

1、FileInputStream文件输入流,从文件中读取字节。
2、FileInputStream的构造方法

 FileInputStream fis = new FileInputStream("小宇在学io.txt");

当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出FileNotFoundException。
read方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1

import java.io.*;
class Fisread {
    public static void main(String[] args) throws IOException{
          // 使用文件名称创建流对象
           FileInputStream fis = new FileInputStream("read.txt");//read.txt文件中内容为abcde
          // 读取数据,返回一个字节
        int read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
        read = fis.read();
        System.out.println((char) read);
          // 读取到末尾,返回-1
           read = fis.read();
        System.out.println( read);
        // 关闭资源
        fis.close();
    }
}
//循环结构
import java.io.*;
class Tenio {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileInputStream fis = new FileInputStream("fos.txt");// read.txt文件中内容为1234
        // 读取数据,返回一个字节
        int read;
        while ((read = fis.read()) != -1) {
            System.out.println((char) read);
        }
        // 关闭资源
        fis.close();
    }
}
结果:
a
b
c
d

*开发中一般强烈推荐使用数组读取文件
传输图片等二进制文件

import java.io.*;
class Copy {
    public static void main(String[] args) throws IOException {
        // 1.创建流对象
        // 1.1 指定数据源
        FileInputStream fis = new FileInputStream("D:\\test.jpg");
        // 1.2 指定目的地
        FileOutputStream fos = new FileOutputStream("test_copy.jpg");

        // 2.读写数据
        // 2.1 定义数组
        byte[] b = new byte[1024];
        // 2.2 定义长度
        int len;
        // 2.3 循环读取
        while ((len = fis.read(b))!=-1) {
            // 2.4 写出数据
            fos.write(b, 0 , len);
        }

        // 3.关闭资源
        fos.close();
        fis.close();
    }
}
//传输图片等二进制文件
import java.io.*;
class Tenio {
    public static void main(String[] args) throws IOException {
        //指定数据源
        FileInputStream fis = new FileInputStream("C:\\Users\\dong1\\Pictures\\11.png");
        //指定目的地
        FileOutputStream fos = new FileOutputStream("C:\\Users\\dong1\\Desktop\\赞赏.png");

        byte[] b = new byte[1024];//定义数组
        int len;//定义长度
        while ((len = fis.read(b))!=-1) {//循环读取
            fos.write(b, 0 , len);//写出数据
        }
        //关闭流
        fos.close();
        fis.close();
    }
}

(三)、字符流
因为数据编码的不同,因而有了对字符进行高效操作的流对象,字节流直接读取数据会有乱码的问题(读中文会乱码)

//乱码例
import java.io.*;


public class zifu {

    public static void main(String[] args) throws Exception {
        //FileInputStream为操作文件的字节输入流(原博客这里写的字符输入流,我做了修改)
        FileInputStream inputStream = new FileInputStream("a.txt");//内容为小宇在学io
        int len;
        while ((len=inputStream.read())!=-1){
           System.out.print((char)len);
        }
    }
}
结果:?°??????¨???io  //因为io有对应的编码,所以能正常输出

//修改为数组读取,并用String输出
import java.io.*;


public class zifu {
public static void main(String[] args) throws Exception {
    
            FileInputStream inputStream = new FileInputStream("a.txt");
            byte[] bytes = new byte[1024];
            int len;
            while ((len=inputStream.read(bytes))!=-1){
               System.out.print(new String(bytes,0,len));
            }
        }
    }
    结果:灏忓畤鍦ㄥio("小宇在学io"的utf-8编码)
    原因String构造方法有解码功能,并且默认编码是utf-8,Cmd默认使用的编码为GBK

一、字符输入流(Reader)

用于读取字符流的抽象类。子类必须实现的方法只有 read(char[], int, int) 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 

1、FileReader(用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。)

用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。 

依旧是构造,造就完了

import java.io.*;
public class Frtest throws IOException{
           public static void main(String[] args) {
            // 使用File对象创建流对象
        File file = new File("io.txt");
        try {
            FileReader fr = new FileReader(file);
        } catch (FileNotFoundException e) {

            System.out.println("无法找到文件");
        }
      
        // 使用文件名称创建流对象
        //FileReader fr = new FileReader("b.txt");
    }
}

读取字符:read方法
每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1

import java.io.*;
public class readtest{
    public static void main(String[] args) throws IOException {
        try {
            // 使用文件名称创建流对象
            FileReader fr = new FileReader("io.txt");
            // 定义变量,保存数据
            int b;
            // 循环读取
            while ((b = fr.read()) != -1) {
                System.out.print((char) b);
            }
            // 关闭资源
            fr.close();
        } catch (IOException e) {
            System.out.println("找不到文件");
          }
    }  
}

二、字符输出流(Writer)

写入字符流的抽象类。子类必须实现的方法仅有 write(char[], int, int)、flush() 和 close()。但是,多数子类将重写此处定义的一些方法,以提供更高的效率和/或其他功能。 

1、FileWriter(FileWriter 用于写入字符流。要写入原始字节流,请考虑使用 FileOutputStream。)

写入字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。要自己指定这些值,可以先在 FileOutputStream 上构造一个 OutputStreamWriter。 
import java.io.*;
public class io{
    public static void main(String[] args) throws IOException {
        // 第一种:使用File对象创建流对象——>写文件
        try {
            File file = new File("io.txt");
            //FileWriter fw = new FileWriter(file);//已有该文件,则会清除文件数据
            FileWriter fw = new FileWriter(file,true);//有文件则将数据写入文件末尾处,而不是清楚原有数据,并从开始处写。 
            // 第二种:使用文件名称创建流对象
            // FileWriter fw = new FileWriter("b.txt");
          fw.write('小');
          fw.write("宇在学io");
          fw.close();//关闭资源时,与FileOutputStream不同。如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        } catch (IOException e) {
            System.out.println("创建文件失败");
        }
try {
      // 使用文件名称创建流对象——>读文件
      FileReader fr = new FileReader("io.txt");
      // 定义变量,保存数据
      int b;
      // 循环读取
      while ((b = fr.read()) != -1) {
      System.out.print((char) b);
     }
      // 关闭资源
     fr.close();
      } catch (IOException e) {
      System.out.println("无法找到文件");}
      }
    }
}
输出结果:小


io先告一段落,有时间会继续学,先处理实验

1

评论 (0)

取消