java中的缓冲流,转换流和序列化流

缓冲流

缓冲流提供了带缓冲区的输入输出功能,目的是提高处理数据的效率,尤其是在进行大量数据的读写时。

BufferedInputStream和BufferedOutputStream

两者同为字节流,BufferedInputStream InputStream 的子类,它通过提供一个缓冲区(内存中的数组)来提高读取数据的效率。它会从底层的输入流中读取数据,并将其缓存在内存中。当需要读取数据时,首先从缓冲区读取,而不是每次都从底层输入流中读取。这样可以减少底层流的读取次数,提高性能。
BufferedOutputStreamOutputStream的子类,它同样使用缓冲区来提高写入数据的效率。它会将数据写入一个缓冲区,当缓冲区满时才将数据写入底层输出流。这减少了每次写入时对底层流的操作次数,从而提高了性能。

构造函数

BufferedInputStream 提供两种构造函数:

  1. public BufferedInputStream(InputStream in)
    • 参数InputStream in是底层输入流
  2. public BufferedInputStream(InputStream in, int size)
    • 参数InputStream in是底层输入流
    • 参数 int size是缓冲区大小,默认为8192

示例:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/1.txt"));

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/1.txt"), 1024);

BufferedOutputStream的构造函数与之类似

  1. public BufferedOutputStream(OutputStream out)
  2. public BufferedOutputStream(OutputStream out, int size)

常用方法

BufferedInputStream 提供了一些方法,主要用于提高读取数据的效率。

  1. read()
    该方法读取下一个字节的数据,并返回该字节。如果到达流的末尾,则返回 -1
int byteRead = bufferedInputStream.read();
  1. read(byte[] b)
    该方法将数据读取到指定的字节数组中,返回实际读取的字节数。如果到达流的末尾,返回 -1
int bytesRead = bufferedInputStream.read(byteArray);
  1. read(byte[] b, int off, int len)
    该方法将数据读取到指定的字节数组 b 的某个位置,最多读取 len 个字节。如果到达流的末尾,返回 -1
int bytesRead = bufferedInputStream.read(byteArray, offset, length);
  1. skip(long n)
    该方法跳过指定数量的字节 n,返回实际跳过的字节数。此方法会在读取流时跳过 n 字节的数据。
long bytesSkipped = bufferedInputStream.skip(n);
  1. available()
    该方法返回流中当前可供读取的字节数,返回值可能不准确。
int availableBytes = bufferedInputStream.available();
  1. mark(int readlimit)
    该方法标记当前流的位置,并将该位置作为后续 reset() 方法调用的起点。readlimit 指定在流被标记后可以读取的最大字节数。如果超过了该限制,流的标记位置将失效。
bufferedInputStream.mark(readLimit);
  1. reset()
    该方法将流的位置重置为先前通过 mark() 方法标记的位置。如果未调用 mark() 方法,调用 reset() 会抛出 IOException
bufferedInputStream.reset();
  1. close()
    该方法关闭流,释放流的相关资源。
bufferedInputStream.close();

以下是 BufferedOutputStream 类的几个常用方法:

  1. write(int b)
    该方法将一个字节的数据写入到流中。
bufferedOutputStream.write(byteData);
  1. write(byte[] b)
    该方法将整个字节数组的数据写入到流中。它会将数组 b 中的所有字节写入到输出流。
bufferedOutputStream.write(byteArray);
  1. write(byte[] b, int off, int len)
    该方法将字节数组 b 从索引 off 位置开始,最多写入 len 个字节到流中。可以指定写入的部分字节数,而不是整个数组。
bufferedOutputStream.write(byteArray, offset, length);
  1. flush()
    该方法将缓冲区中的所有数据强制写入到底层的输出流中。在调用 flush() 之后,缓冲区中的数据会被立即写入目标输出流。通常在写入完成后,应该调用该方法来确保所有数据都被写入。
bufferedOutputStream.flush();
  1. close()
    该方法关闭输出流,并将缓冲区中的任何剩余数据写入到底层流中。关闭流时,还会释放流所占用的资源。
bufferedOutputStream.close();

BufferedReader和BufferedWriter

两者都是字符流

构造函数

BufferedReader 提供两种构造函数:

  1. public BufferedReader(Reader in, int sz)
    • 参数Reader in是输入字符流
    • 参数 int sz是缓冲区的大小(默认8192个字符)
  2. public BufferedReader(Reader in)
    • 参数Reader in是输入字符流

示例:

BufferedReader br = new BufferedReader(new FileReader("src/1.txt"));

BufferedReader br = new BufferedReader(new FileReader("src/1.txt"), 1024);

BufferedWriter的构造函数与之相似:

  1. public BufferedWriter(Writer out)
  2. public BufferedWriter(Writer out, int sz)

常用方法

BufferedReader 的常用方法:

  1. read()
    该方法读取单个字符(以整数形式返回),如果到达流的末尾,返回 -1
int charRead = bufferedReader.read();
  1. read(char[] cbuf)
    该方法读取字符数据,并将读取到的字符存储到字符数组 cbuf 中,返回实际读取的字符数。如果到达流的末尾,返回 -1
int charsRead = bufferedReader.read(cbuf);
  1. readLine()
    该方法读取一行字符,直到遇到行结束符(\n\r\n)为止。如果到达流的末尾,返回 null。该方法在 Java 1.7 之后已经被标记为弃用,建议使用 read() 和相关方法替代。
String line = bufferedReader.readLine();
  1. skip(long n)
    该方法跳过 n 个字符的输入。如果 n 大于流中剩余的字符数,实际跳过的字符数可能会少于 n。返回跳过的字符数。
long charsSkipped = bufferedReader.skip(n);
  1. ready()
    该方法检查是否可以进行读操作。如果可以读取字符,返回 true;否则,返回 false
boolean isReady = bufferedReader.ready();
  1. close()
    该方法关闭流,释放与该流相关的资源。关闭流时,缓冲区中的所有数据都会被自动刷新并写入
bufferedReader.close();

BufferedWriter的常用方法:

  1. write(int c)
    该方法写入单个字符数据。如果要写入的字符是一个字节,则可以使用此方法。
bufferedWriter.write(65); // 写入字符 'A'
  1. write(char[] cbuf)
    该方法将整个字符数组的数据写入到流中。它会将数组 cbuf 中的所有字符写入到输出流。
bufferedWriter.write(cbuf); // 写入字符数组
  1. write(char[] cbuf, int off, int len)
    该方法将字符数组 cbuf 从索引 off 位置开始,最多写入 len 个字符到输出流中。可以指定写入的部分字符数,而不是整个数组。
bufferedWriter.write(cbuf, offset, length); // 写部分字符数组
  1. newLine()
    该方法写入一个平台相关的行分隔符(如 Windows 使用 \r\n,Unix 使用 \n)。它通常用于表示一行的结束。
bufferedWriter.newLine(); // 写入行分隔符
  1. flush()
    该方法将缓冲区中的所有数据强制写入到底层的输出流中。在调用 flush() 之后,缓冲区中的数据会被立即写入目标输出流。通常在写入完成后,应该调用该方法来确保所有数据都被写入。
bufferedWriter.flush();
  1. close()
    该方法关闭输出流,并将缓冲区中的任何剩余数据写入到底层流中。关闭流时,还会释放流所占用的资源。
bufferedWriter.close();

工作原理

FileInputStream 中,每次调用 read() 方法时,都会直接从文件中读取一个字节。这意味着每调用一次 read(),就需要一次磁盘 I/O 操作。对于每次读取一个字节来说,这会造成很多不必要的磁盘访问,从而降低了读取效率。BufferedInputStream 通过内部缓冲区来优化文件读取。它会一次性从磁盘读取多个字节的数据,存入内存中的缓冲区(默认大小为8192个字节)。之后的read() 调用将直接从这个缓冲区返回数据,而不需要每次都访问磁盘。这样,在缓冲区填满后,之后的 read() 调用只是从内存中读取数据,极大减少了磁盘 I/O 操作。

转换流

转换流的作用是将字节流和字符流进行转换。这两个类通常用于在处理非字符流(如文件、网络等)时,实现字符编码和解码功能

InputStreamReader

构造函数

1. public InputStreamReader(InputStream in)
2. public InputStreamReader(InputStream in, String charsetName)
3. public InputStreamReader(InputStream in, Charset cs)
4. public InputStreamReader(InputStream in, CharsetDecoder dec)
构造函数中需要指定包装的字节流,后三种构造方法实际上都是在指定编码方式

常用方法

常用方法与基本的字节流类似,只是会把读取到的数据通过指定字符编码将字节转换为字符。以下是 InputStreamReader 的常用方法:

int charRead = inputStreamReader.read();
int charsRead = inputStreamReader.read(cbuf);
int charsRead = inputStreamReader.read(cbuf, offset, length);
long skippedChars = inputStreamReader.skip(n);
boolean isReady = inputStreamReader.ready();
inputStreamReader.mark(readAheadLimit);
inputStreamReader.reset();
inputStreamReader.close();

OutputStreamWriter

构造方法

  1. public OutputStreamWriter(OutputStream out)
  2. public OutputStreamWriter(OutputStream out, String charsetName)
  3. public OutputStreamWriter(OutputStream out, Charset cs)
  4. public OutputStreamWriter(OutputStream out, CharsetEncoder enc)
    构造函数中需要指定包装的字节流,后三种构造方法实际上都是在指定编码方式

常用方法

OutputStreamWriter 是 Java 中的一个字符流类,用于将字符流(如 Writer)转换为字节流(如 OutputStream)。它用于将字符数据写入到字节流中,并且支持字符编码的转换。下面是 OutputStreamWriter 常用的方法:

outputStreamWriter.write(65);  // 写入字符 'A'

char[] chars = "Hello, OutputStreamWriter!".toCharArray();
outputStreamWriter.write(chars);

outputStreamWriter.write(chars, 0, 5);  // 写入数组的前5个字符

outputStreamWriter.flush();  // 强制写入缓冲区的内容

outputStreamWriter.close();  // 关闭流,释放资源

String encoding = outputStreamWriter.getEncoding();

使用示例

读取一个GBK文件,将其写入一个UTF-8的文件

    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("src/gbk.txt"), "GBK");
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("src/utf8.txt"), StandardCharsets.UTF_8);
        char[] buf = new char[1024];
        int len;
        while ((len = isr.read(buf)) != -1) {
            osw.write(buf, 0, len);
        }
        isr.close();
        osw.close();
    }

序列化流

ObjectInputStream

构造方法

  1. public ObjectInputStream(InputStream in)
    包裹指定的输入字节流

常用方法

ObjectInputStream 可以将从输入流中读取的字节反序列化为 Java 对象。常见的应用场景包括读取从 ObjectOutputStream 写入的数据,进行对象的反序列化。
以下是 ObjectInputStream 的常用方法:

  1. readObject()
    该方法用于从输入流中读取一个对象,并将其反序列化为 Java 对象。返回类型是 Object,因此需要进行强制类型转换。
Object obj = objectInputStream.readObject();
  • 返回值:返回一个被反序列化的对象。
  • 异常:如果反序列化的类没有实现 Serializable 接口,或者发生了 I/O 错误,则会抛出异常(ClassNotFoundExceptionIOException)。
  1. readInt()
    该方法从输入流中读取一个整数值。它将字节转换为一个 int 类型。
int intValue = objectInputStream.readInt();
  1. readLong()
    该方法从输入流中读取一个长整型值。
long longValue = objectInputStream.readLong();
  1. readUTF()
    该方法从输入流中读取一个 UTF-8 编码的字符串,返回该字符串。
String str = objectInputStream.readUTF();
  1. readByte()
    该方法从输入流中读取一个字节。
byte byteValue = objectInputStream.readByte();
  1. readBoolean()
    该方法从输入流中读取一个布尔值。
boolean booleanValue = objectInputStream.readBoolean();
  1. readChar()
    该方法从输入流中读取一个字符。
char charValue = objectInputStream.readChar();
  1. close()
    该方法关闭流并释放资源。当关闭流时,ObjectInputStream 将关闭其底层流(如文件流、网络流等)。
objectInputStream.close();

ObjectOutputStream

构造方法

  1. public ObjectOutputStream(OutputStream out)
    包裹指定的输出字节流

常用方法

ObjectOutputStream 是 Java 中用于将对象写入输出流的类,它负责将对象进行序列化并写入流中,以便可以将其保存到文件、网络、数据库等地方。以下是 ObjectOutputStream 的常用方法:

  1. writeObject(Object obj)
    该方法将一个对象序列化并写入流中。如果对象没有实现 Serializable 接口,会抛出 java.io.NotSerializableException 异常。
objectOutputStream.writeObject(myObject);  // 序列化并写入对象
  • 参数obj — 要写入的对象。
  • 返回值:无。
  • 异常:抛出 IOExceptionNotSerializableException
  1. write(int v)
    该方法将一个字节(int 类型的值)写入输出流。该方法将整数值(0–255)转换为一个字节,并写入流。
objectOutputStream.write(65);  // 写入单个字节,'A' 的 ASCII 值
  1. writeByte(int v)
    该方法将一个字节写入输出流,v 必须是 byte 范围内的整数(即 -128127)。
objectOutputStream.writeByte(100);  // 写入一个字节值 100
  1. writeBoolean(boolean v)
    该方法将一个布尔值写入输出流。
objectOutputStream.writeBoolean(true);  // 写入布尔值 true
  1. writeChar(int v)
    该方法将一个字符(char)写入输出流。
objectOutputStream.writeChar('A');  // 写入字符 'A'
  1. writeFloat(float v)
    该方法将一个浮点值(float)写入输出流。
objectOutputStream.writeFloat(3.14f);  // 写入浮点数 3.14
  1. writeDouble(double v)
    该方法将一个双精度浮点值(double)写入输出流。
objectOutputStream.writeDouble(3.141592);  // 写入双精度浮点数 3.141592
  1. writeUTF(String str)
    该方法将一个字符串写入输出流,并将其转换为 UTF-8 编码的字节流。
objectOutputStream.writeUTF("Hello, world!");  // 写入字符串
  1. flush()
    该方法将缓冲区中的所有数据强制写入到底层输出流中。一般来说,当流被关闭之前,可以调用此方法来确保所有数据被写入。
objectOutputStream.flush();  // 强制写入缓冲区数据
  1. close()
    该方法关闭输出流,并释放资源。当调用 close() 时,ObjectOutputStream 会将任何剩余的字节数据写入流中并关闭流。
objectOutputStream.close();  // 关闭流并释放资源

使用示例

  • 序列化的类需要实现Serializable接口
  • 实现接口后类中会包含一个serialVersionUID
  • 类变化时serialVersionUID同样变化,如果没有找到相同的serialVersionUID反序列化会失败
  • 可以手动指明serialVersionUID

    private static final long serialVersionUID = 1L;

  • 不想序列化的值可以通过transient关键字
// 序列化的实体类
public class A implements Serializable {
    @Serial
    private static final long serialVersionUID = -4476946105183235212L;
    public String name = "aaa";
    public int age = 0;
    public A() {
    }
    public A(String name, int age) {
        this.name = name;
        this.age = age;
    }
}
// 将A类型的对象a写入文件
public static void main(String[] args) {
    A a = new A();
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src/a.txt"));
    oos.writeObject(a);
    oos.close();
}
// 从文件中读取A类型的对象a
public static void main(String[] args) throws IOException, ClassNotFoundException {
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src/a.txt"));
    A a = (A)ois.readObject();
    System.out.println(a);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值