Java教程

Java字节流

本文主要是介绍Java字节流,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

流的概念

流的概念:内存与存储设备之间数据传输的通道,数据借助流传输

流的分类

  • 按方向:以内存为参照
    • 输入流:将 存储设备 中的内容读入到 内存
    • 输出流:将 内存 中的内容写入到 存储设备
  • 按单位:
    • 字节流:以字节为单位,读写所有数据
    • 字符流:以字符为单位,读写文本数据
  • 按功能:
    • 节点流(底层流):具有实际传输数据的读写功能
    • 过滤流:在节点流的基础上增强功能,如缓冲流

字节流抽象类

  • 字节流的父类(抽象类):
    • InputStream:字节输入流
      • read()
      • close():节约资源
    • OutputStream:字节输出流
      • write()
      • close():节约资源

文件字节流

  • FileInputStream:

    • read(byte[] b):从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1
//1 创建 FileInputStream,并指定路径
FileInputStream fis = new FileInputStream("F:\\a.txt");

//2 读文件
//读一个字节
int data = 0;
while ((data = fis.read()) != -1) {
    System.out.print((char) data);
}

//3.关闭
fis.close();

使用byte[]读取多个字节

FileInputStream fis = new FileInputStream("F:\\a.txt");

byte[] b = new byte[3];

int count = fis.read(b);//read()范围值为读取字节的个数
System.out.println(new String(b));
System.out.println(count);

int count2 = fis.read(b);
System.out.println(new String(b));
System.out.println(count2);

fis.close();

读取结果:为 fjkljk,默认读取的方法在读取结束时不会覆盖未读取的内容,需要对其进行限制:

int count5 = fis.read(b);
System.out.println(new String(b,0,count5));//l
System.out.println(count5);//1

使用循环读取:

FileInputStream fis = new FileInputStream("F:\\a.txt");

byte[] b = new byte[3];
int count = 0;
while((count = fis.read(b))!= -1){
    System.out.println(new String(b,0,count));
}

fis.close();
  • FileOutputStream:
    • write(byte[] b):一次写多个字节,将b数组中所有字节,写入输出流
    • 覆盖:默认写入时对原文件进行覆盖,如果不想进行覆盖,在读取文件时设置为 true
FileOutputStream fileOutputStream = new FileOutputStream("F:\\b.txt",true);
  1. 单个字节写入
//1 创建文件输出流对象
FileOutputStream fileOutputStream = new FileOutputStream("F:\\b.txt");
//2. 写入文件
fileOutputStream.write(97);
fileOutputStream.write('c');
fileOutputStream.write('s');
//3. 关闭
fileOutputStream.close();
System.out.println("执行完毕");
  1. 字符串写入
//1 创建文件输出流对象
FileOutputStream fileOutputStream = new FileOutputStream("F:\\b.txt");
//2. 写入文件
String s = "Hello,world";
fileOutputStream.write(s.getBytes());//执行写入操作的时候覆盖源文件
//3. 关闭
fileOutputStream.close();
System.out.println("执行完毕");

复制文件

字节流可以复制任何文件

//1. 创建流
//文件字节输入流
FileInputStream fileInputStream = new FileInputStream("F:\\wall.jpg");
//文件字节输出流
FileOutputStream fileOutputStream = new FileOutputStream("F:\\1.jpg");
//2. 边读边写
byte[] b = new byte[1024];
int count = 0;
while ((count=fileInputStream.read(b))!=-1){
    fileOutputStream.write(b,0,count);
}
//3. 关闭
fileInputStream.close();
fileOutputStream.close();
System.out.println("复制完毕");

字节缓冲流

  • 缓冲流:
    • BufferedInputStream
    • BufferedOutputStream
  • 作用:
    • 提高IO效率,减少访问磁盘的次数
    • 数据存储在缓冲区中,flush是将缓冲区的内容写入文件中,也可以直接close

缓冲流读取文件

//1. 创建BufferedInputStream
//把字节流传入缓冲流
FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
//2. 读取
//读取到缓冲区,然后再读取到文件中,缓冲区大小维8192
int data = 0;
while((data=bufferedInputStream.read())!=-1){
    System.out.print((char)data);
}
//3.关闭缓冲区
bufferedInputStream.close();

创建缓冲区(与前文的字符串读取相同,byte[]起到缓冲区作用)

//1. 创建BufferedInputStream
//把字节流传入缓冲流
FileInputStream fileInputStream = new FileInputStream("F:\\buffer.txt");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
//2. 读取

//自己创建缓冲区
byte[] b = new byte[1024];
int count = 0;
while((count = fileInputStream.read(b))!=-1){
    System.out.println(new String(b,0,count));
}
//3.关闭缓冲区
bufferedInputStream.close();

缓冲流写入文件

  • 在使用缓冲区写入文件时,需要进行 flush刷新才能将缓冲区的内容写入硬盘中
  • 当缓冲区写满时,会自动调用 flush进行写入
  • close缓冲流时,会调用 flush进行把缓冲区的内容写入硬盘中
  • 主动进行 flush操作可以提高效率
//1.创建字节输出缓冲流
FileOutputStream fileOutputStream = new FileOutputStream("F:\\buffer.txt");
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

//2.写入文件
for (int i = 0; i < 9; i++) {
    //仅写入缓冲区中,没有写入硬盘中,缓冲区满了会自动调用flush
    bufferedOutputStream.write("hello,world!\r\n".getBytes());
    //刷新到硬盘中,提高效率
    bufferedOutputStream.flush();
}

//3.close(内部调用flush)
//即使不进行刷新,关闭缓冲区时也会写入到硬盘中
bufferedOutputStream.close();

对象流

  • 对象流:
    • ObjectOutputStream
    • ObjectInputStream
  • 增强了缓冲区功能
  • 增强了读写8种基本数据类型和字符串功能
  • 增强了读写对象的功能
    • readObject():从流中读取一个对象(反序列化
    • writeObject(Object obj):向流中写入一个对象(序列化

序列化

序列化是将数据类型和类进行写入,要序列化类必须实现 Serializable接口

  • 类的定义:
public class Student implements Serializable{}
  • 类的序列化
//1.创建对象流
FileOutputStream fileOutputStream = new FileOutputStream("F:\\stu.bin");
ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
//2.序列化(写入操作)
Student stu1 = new Student("小王",29);
objectOutputStream.writeObject(stu1);//需要进行序列化,需要使类实现序列化的接口
//3.关闭
objectOutputStream.close();
System.out.println("序列化完毕");

反序列化

反序列化:读取文件,再重构成对象

一个对象仅能反序列化一次

//1. 创建对象流
FileInputStream fileInputStream = new FileInputStream("F:\\stu.bin");
ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
//2. 读取文件(反序列化)
Student stu = (Student)objectInputStream.readObject();
//如果读取两次会出现异常,每个对象反序列化仅能进行一次
// Student stu2 = (Student)objectInputStream.readObject();
System.out.println(stu.toString());
//3. 关闭
objectInputStream.close();

注意事项

序列化:

  • 序列化类必须要实现Serializable接口
  • 序列化类中的对象属性,即引用类型字段也要实现Seralizable接口
  • 序列化版本号ID,保证序列化的类和反序列化的类是同一个类 private static final long serialVersionUID = xxxL;
  • 使用 transient(瞬间的)修饰属性,使属性不被序列化
  • 静态属性不能序列化
  • 序列化多个对象,可以借助集合实现

序列化:

//序列化多个对象
Student stu1 = new Student("小王",29);
Student stu2 = new Student("林",12);
ArrayList<Student> list = new ArrayList<>();
list.add(stu1);
list.add(stu2);
objectOutputStream.writeObject(list);//需要进行序列化,需要使类实现序列化的接口

反序列化:

//反序列化
ArrayList<Student> list = (ArrayList<Student>) objectInputStream.readObject();
System.out.println(list.toString());
这篇关于Java字节流的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!