欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IO流学习笔记

程序员文章站 2022-07-10 17:43:21
IO流参考:http://c.biancheng.net/java/130/;流的概念在 java 中所有数据都是使用流读写的。流是一组有序的数据序列,将数据从一个地方带到另一个地方输入:是将数据从各种输入设备(包括文件、键盘等)中读取到内存中,输出:是将数据写入到各种输出设备(比如文件、显示器、磁盘等)。流的分类数据流是 Java 进行 I/O 操作的对象,它按照不同的标准可以分为不同的类别。按方向输入流:将<存储设备>中的内容读到<内存>中输出流:将<...

IO流

参考:http://c.biancheng.net/java/130/;

流的概念

在 java 中所有数据都是使用流读写的。流是一组有序的数据序列,将数据从一个地方带到另一个地方

输入:是将数据从各种输入设备(包括文件、键盘等)中读取到内存中,

输出:是将数据写入到各种输出设备(比如文件、显示器、磁盘等)。
IO流学习笔记

流的分类

数据流是 Java 进行 I/O 操作的对象,它按照不同的标准可以分为不同的类别。

按方向

  • 输入流:将<存储设备>中的内容读到<内存>中
  • 输出流:将<内存>中的内容写到<存储设备>中

按单位

  • 字节流:以字节为单位,可以读写所有数据
  • 字符流:以字符为单位,只能读写文本数据

按功能

  • 节点流:具有实际传输数据的读写功能
  • 处理流:在节点流的基础之上增强功能

输入流和输出流本身都是抽象类,不能直接实例化,如果想操作对象,则必须实例化这些类的子类对象.

输入流

Java 流相关的类都封装在 java.io 包中,而且每个数据流都是一个对象。所有输入流类都是 InputStream 抽象类(字节输入流)和 Reader 抽象类(字符输入流)的子类。其中 InputStream 类是字节输入流的抽象类,是所有字节输入流的父类

IO流学习笔记

输出流

在 Java 中所有输出流类都是 OutputStream 抽象类(字节输出流)和 Writer 抽象类(字符输出流)的子类。其中 OutputStream 类是字节输出流的抽象类,是所有字节输出流的父类,

IO流学习笔记

系统流

每个java程序运行时都带有一个系统流,系统流对应的类为 java.lang.System。Sytem 类封装了 Java 程序运行时的 3 个系统流,分别通过 in、out 和 err 变量来引用。这 3 个系统流如下所示:

  • System.in:标准输入流,默认设备是键盘。
  • System.out:标准输出流,默认设备是控制台。
  • System.err:标准错误流,默认设备是控制台。
import java.io.IOException;

public class Demo02 {

        public static void main(String[] args) {
            byte[] byteData = new byte[100]; // 声明一个字节数组
            System.out.println("请输入英文:");
            try {
                System.in.read(byteData);//读取
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.out.println("您输入的内容如下:");
            for (int i = 0; i < byteData.length; i++) {
                System.out.write((char) byteData[i]);//输出,强转为字符类型
            }
    }
}

System.in 是 InputStream 类的一个对象,因此上述代码的 System.in.read() 方法实际是访问 InputStream 类定义的 read() 方法。该方法可以从键盘读取一个或多个字符。对于 System.out 输出流主要用于将指定内容输出到控制台。

System.out 和 System.error 是 PrintStream 类的对象。因为 PrintStream 是一个从 OutputStream 派生的输出流,所以它还执行低级别的 write() 方法。因此,除了 print() 和 println() 方法可以完成控制台输出以外,System.out 还可以调用 write() 方法实现控制台输出。

该方法通过 byteval 参数向文件写入指定的字节。在实际操作中,print() 方法和 println() 方法比 write() 方法更常用。

注意:尽管它们通常用于对控制台进行读取和写入字符,但是这些都是字节流。因为预定义流是没有引入字符流的 Java 原始规范的一部分,所以它们不是字符流而是字节流,但是在 Java 中可以将它们打包到基于字符的流中使用。

字符编码介绍

Java 中常见编码说明如下:

  • ISO8859-1:属于单字节编码,最多只能表示 0~255 的字符范围。
  • GBK/GB2312:中文的国标编码,用来表示汉字,属于双字节编码。GBK 可以表示简体中文和繁体中文,而 GB2312 只能表示简体中文。GBK 兼容 GB2312。
  • Unicode:是一种编码规范,是为解决全球字符通用编码而设计的。UTF-8 和 UTF-16 是这种规范的一种实现,此编码不兼容 ISO8859-1 编码。Java 内部采用此编码。
  • UTF:UTF 编码兼容了 ISO8859-1 编码,同时也可以用来表示所有的语言字符,不过 UTF 编码是不定长编码,每一个字符的长度为 1~6 个字节不等。一般在中文网页中使用此编码,可以节省空间。

本地的默认编码可以使用 System 类查看。Java 中 System 类可以取得与系统有关的信息,所以直接使用此类可以找到系统的默认编码。方法如下所示:

public static Properties getProperty()

使用上述方法可以查看 JVM 的默认编码,代码如下:

public static void main(String[] args) {
    // 获取当前系统编码
    System.out.println("系统默认编码:" + System.getProperty("file.encoding"));
}

字节流的使用

字节输入流

InputStream 类及其子类的对象表示字节输入流,InputStream 类的常用子类如下。

  • ByteArrayInputStream 类:将字节数组转换为字节输入流,从中读取字节。
  • FileInputStream 类:从文件中读取数据。
  • PipedInputStream 类:连接到一个 PipedOutputStream(管道输出流)。
  • SequenceInputStream 类:将多个字节输入流串联成一个字节输入流。
  • ObjectInputStream 类:将对象反序列化。

使用 InputStream 类的方法可以从流中读取一个或一批字节。下面 列出了 InputStream 类的常用方法。

方法名及返回值类型 说明
int read() 从输入流中读取一个 8 位的字节,并把它转换为 0~255 的整数,最后返回整数。 如果返回 -1,则表示已经到了输入流的末尾。为了提高 I/O 操作的效率,建议尽量 使用 read() 方法的另外两种形式
int read(byte[] b) 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。 该方法返回 读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
int read(byte[] b, int off, int len) 从输入流中读取若干字节,并把它们保存到参数 b 指定的字节数组中。其中,off 指 定在字节数组中开始保存数据的起始下标;len 指定读取的字节数。该方法返回实际 读取的字节数。如果返回 -1,则表示已经到了输入流的末尾
void close() 关闭输入流。在读操作完成后,应该关闭输入流,系统将会释放与这个输入流相关 的资源。注意,InputStream 类本身的 close() 方法不执行任何操作,但是它的许多 子类重写了 close() 方法
int available() 返回可以从输入流中读取的字节数
long skip(long n) 从输入流中跳过参数 n 指定数目的字节。该方法返回跳过的字节数
void mark(int readLimit) 在输入流的当前位置开始设置标记,参数 readLimit 则指定了最多被设置标记的字 节数
boolean markSupported() 判断当前输入流是否允许设置标记,是则返回 true,否则返回 false
void reset() 将输入流的指针返回到设置标记的起始处

注意:在使用 mark() 方法和 reset() 方法之前,需要判断该文件系统是否支持这两个方法,以避免对程序造成影响。

字节输出流

OutputStream 类及其子类的对象表示一个字节输出流。OutputStream 类的常用子类如下。

  • ByteArrayOutputStream 类:向内存缓冲区的字节数组中写数据。
  • FileOutputStream 类:向文件中写数据。
  • PipedOutputStream 类:连接到一个 PipedlntputStream(管道输入流)。
  • ObjectOutputStream 类:将对象序列化。

利用 OutputStream 类的方法可以从流中写入一个或一批字节。下面列出了 OutputStream 类的常用方法。

方法名及返回值类型 说明
void write(int b) 向输出流写入一个字节。这里的参数是 int 类型,但是它允许使用表达式, 而不用强制转换成 byte 类型。为了提高 I/O 操作的效率,建议尽量使用 write() 方法的另外两种形式
void write(byte[] b) 把参数 b 指定的字节数组中的所有字节写到输出流中
void write(byte[] b,int off,int len) 把参数 b 指定的字节数组中的若干字节写到输出流中。其中,off 指定字节 数组中的起始下标,len 表示元素个数
void close() 关闭输出流。写操作完成后,应该关闭输出流。系统将会释放与这个输出 流相关的资源。注意,OutputStream 类本身的 close() 方法不执行任何操 作,但是它的许多子类重写了 close() 方法
void flush() 为了提高效率,在向输出流中写入数据时,数据一般会先保存到内存缓冲 区中,只有当缓冲区中的数据达到一定程度时,缓冲区中的数据才会被写 入输出流中。使用 flush() 方法则可以强制将缓冲区中的数据写入输出流, 并清空缓冲区

文件字节流

文件字节输入流

在创建 FileInputStream 类的对象时,如果找不到指定的文件将拋出 FileNotFoundException 异常,该异常必须捕获或声明拋出。

import java.io.FileInputStream;

/**
 * FileInputStream的使用
 * 文件字节输入流,从文件中读取数据
 */

public class Demo03 {

    public static void main(String[] args) throws Exception{
        //1.创建FileInputStream,并指定文件路径
        FileInputStream fis = new FileInputStream("F:\\file\\word.txt");
        //2读取文件
       // fis.read();

        //1.单个字节读取输出
//        int data = 0;
//        //如果 = -1 则说明读完了 跳出循环
//        while((data = fis.read())!= -1){
//            System.out.println((char)data);
//        }

        //2.读出多个字节输出
        byte [] buf = new byte[5]; // 周转的缓冲区
        int len = 0;//读取的长度
        while((len = fis.read(buf))!= -1){
            System.out.println(new String(buf,0,len));
            System.out.println(len);//读取的长度
        }
        fis.close();//关闭输入流
        System.out.println("执行完毕");
    }
}

文件字节输出流

import java.io.FileOutputStream;

/**
 *FileOutputStream的使用
 * 文件字节输出流,向文件中写入数据
 */
public class Demo04 {

    public static void main(String[] args) throws Exception{

        //创建FileOutputStream对象,没文件会自动创建
        //每次执行都会把原为文件内容覆盖
        FileOutputStream fos = new FileOutputStream("F:\\file\\word.txt");

        //不会覆盖原来的内容
       // FileOutputStream fos = new FileOutputStream("F:\\file\\word.txt",true);
        
        fos.write(97); //写入的是unicode码对应的字符
        fos.write('b');
        fos.write('c');

        byte[] buf = {'d','c','s','s','g'};//定义一个字节数组
        fos.write(buf);

        String string = "hello world";
        fos.write(string.getBytes());//string转为一个字节数组

        //强制将缓冲区中的数据写入输出流,
        //并清空缓冲区
        fos.flush();

        fos.close();
        System.out.println("执行完毕");
    }

}

字节流复制文件

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * 复制文件
 */
public class Demo05 {

    public static void main(String[] args) {
        //创建文件字节输入流
        File file = new File("F:\\file\\word.txt");
        FileInputStream fis = null;
        //创建文件字节输出流
        FileOutputStream fos = null;
        try{
            fis = new FileInputStream(file);
            //文件不存在会自动创建
            fos = new FileOutputStream("F:\\file\\word1.txt");

            byte[] buf = new byte[1024];//周转的缓存区
            int len = 0; //读取的字节长度
            //边读边写
            while((len = fis.read(buf)) != -1){
                fos.write(buf,0,len);
            }
            
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                fis.close();//关闭输入流
                fos.close();//关闭输出流
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        System.out.println("执行完毕");
    }
}
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * 图片复制
 */
public class Demo06 {

    public static void main(String[] args) throws Exception{
        FileInputStream fis = new FileInputStream("F:\\file\\01.jpg");
        FileOutputStream fos = new FileOutputStream("F:\\file\\02.jpg");

        byte[] buf = new byte[1024];
        int len = 0;

        while((len = fis.read(buf))!= -1){
            fos.write(buf);
        }

        fis.close();
        fos.close();
        System.out.println("执行完毕");
    }
}

字节缓冲流

  • 缓冲流 BufferInputStream/BufferOutputStream
    • 提高I0效率,减少访问磁盘的次数;
    • 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。

字节输入缓冲流

import java.io.BufferedInputStream;
import java.io.FileInputStream;

/**
 * 使用字节缓冲流
 * BufferInputStream
 */
public class Demo07 {

    public static void main(String[] args) throws Exception{
        //BufferInputStream实例化
        FileInputStream fis = new FileInputStream("F:\\file\\word.txt");
        BufferedInputStream bis = new BufferedInputStream(fis); //提高读的速率
        //读数据
        byte[] buf = new byte[1024];
        int len = 0;
        while((len = fis.read(buf)) != -1){
            System.out.println(new String(buf,0,len));
        }

        bis.close();//会自动把fis关闭
    }
}

字节输出缓冲流

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;

/**
 * 字节输出缓冲流的使用
 * BufferOutputStream
 */
public class Demo08 {

    public static void main(String[] args) throws Exception{
        //BufferedOutputStream实例化
        FileOutputStream fos = new FileOutputStream("F:\\file\\buffer.txt");
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        bos.write("hello world".getBytes());//写入到BufferedOutputStream维护的缓冲区

        //强制将缓冲区中的数据写入输出流,
        //并清空缓冲区
        bos.flush();
        //close()方法里面调用了flush()方法,可以省略flush()不写
        bos.close();
        System.out.println("执行完毕");
    }
}

对象流

  • 对象流: Object0utputStream / 0bjectInputStream

    • 增强了缓冲区功能
    • 增强了读写8种基本数据类型和字符串功能
    • 增强了读写对象的功能:
      • readd0bject() 从流中读取一个对象
      • write0bject (0bject obj) 向流中写入一一个对象

    使用流传输对象的过程称为序列化、反序列化。

    ObjectInputStream 类:将对象反序列化。

    ObjectOutputStream 类:将对象序列化。

序列化(ObjectOutputStream)

注意:序列化的类 需要实现Serializable接口
*       序列化类中的对象属性也需要 实现Serializable接口
*       序列化版本号ID,保证序列化的类和反序列化的类是同一个类
*       使用transient(瞬间的)修饰属性,这个属性不能序列化
*       静态属性不能序列化
*       序列化多个对象,可以借助集合来实现
import java.io.Serializable;

/**
 * 该类想要序列化,需要实现Serializable接口,否则不能序列化
 */
public class Student implements Serializable {
	//serialVersionUID 序列化版本号ID
    private final static long serialVersionUID= 1L;
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 使用ObjectOutputStream实现对象的序列化
 * 注意:序列化的类 需要实现Serializable接口
 *       序列化类中的对象属性也需要 实现Serializable接口
 *       序列化版本号ID,保证序列化的类和反序列化的类是同一个类
 *       使用transient(瞬间的)修饰属性,这个属性不能序列化
 *       静态属性不能序列化
 *       序列化多个对象,可以借助集合来实现
 *
 */
public class Demo09 {

    public static void main(String[] args) throws Exception{
        //实例化ObjectOutputStream
        FileOutputStream fos = new FileOutputStream("F:\\file\\Object.bin");
        ObjectOutputStream oos = new ObjectOutputStream(fos);

        //序列化写入操作
        Student student = new Student("张三",20);
        Student student1 = new Student("李四",21);

        //1.
//        oos.writeObject(student);
//        oos.writeObject(student1);
        //2.使用集合
        List<Student> students = new ArrayList<>();
        students.add(student);
        students.add(student1);
        oos.writeObject(students);

        oos.close();
        System.out.println("执行完毕");
    }
}

文件会乱码

反序列化(ObjectInputStream)

import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;

/**
 * 使用ObjectInputStream实现反序列化(读取重构成对象)
 */
public class Demo10 {
    public static void main(String[] args) throws Exception{
        // 创建对象流
        FileInputStream fis = new FileInputStream("F:\\file\\Object.bin");
        ObjectInputStream ois = new ObjectInputStream(fis);

        //读取文件(反序列化)

        //1.
//        Student student =(Student) ois.readObject();
//        Student student1 = (Student) ois.readObject();
//        System.out.println(student.toString());
//        System.out.println(student1.toString());

        //2.
        List<Student> students =(List<Student>) ois.readObject();
        System.out.println(students.toString());

        //关闭
        ois.close();
        System.out.println("执行完毕");
    }
}

待加…

本文地址:https://blog.csdn.net/qian4517/article/details/109817369

相关标签: java