Java学习记录15

IO流

IO,即in和out,也就是输入和输出,指的是程序和外部设备之间的数据传递。常见的外部设备有文件、网络连接、管道等。

Java中通过流处理IO,流(Stream),是指一连串的数据(字节或字符),以先进先出的方式发送信息的通道。

当程序需要读取数据的时候,就会开启一个通向数据源的流,数据源可以是文件、内存、网络连接。类似的,当程序需要写入数据的时候,就会开启一个通向目的地的流。

IO流的核心为四个抽象类:InputStream、OutputStream、Reader、Writer。

InputStream类

  • int read():读取文件
  • int read(byte b[], int off, int len):从第off位置开始读,读取len长度的字节,然后放入数组b中。
  • long skip(long n):跳过指定个数的字节。
  • int available():返回可读的字节数。
  • void close():关闭流,释放资源。

OutputStream类

  • void write(int b): 写入一个字节。
  • void write(byte b[], int off, int len):将数组b中的从off位置开始,长度为len 的字节写入。
  • void flush():强制刷新,将缓冲区的数据写入。
  • void close():关闭流。

Reader类

  • int read():读取单个字符。
  • int read(char cbuf[], int off, int len):从第off位置开始读,读取len长度的字符,然后放入b数组中。
  • long skip(long n): 跳过指定个数的字符。
  • int ready():是否可以读了。
  • void close():关闭流,释放资源。

Writer类

void write(int c):写入一个字符

void write(char cbuf[], int off, int len):将数组从cbuf中的off位置开始,长度为冷的字符写入。

void flush():强制刷新,将缓冲区的数据写入。

void close():关闭流。

字节流和字符流的区别:

字节流一般用来处理图像、视频、音频等类型的文件。字符流一般用来处理纯文本类型的文件,不能处理图像、视频等非文本文件。

字节流本身没有缓冲流,而字符流本身就带有缓冲区,即缓冲流对字节流效率提升高,而对字符流效率提升相对低。

IO流分类

IO流按照操作对象来划分,可以分为:文件、数组、管道、基本数据类型、缓冲、打印、对象序列化/反序列化,以及转换等。

 文件

 文件流就是直接操作文件的流,可以分为字节流(FileInputStream 和 FileOutputStraem) 和 字节流(FileReader 和 FileWriter)

FileInputStream的例子:

//创建一个文件输入流
FileInputStream fis = new FileInputStream("demo/b.txt");
//声明一个字节数组,用来存取读到的数据
byte[] b = new byte[1024];
//声明一个int类型的变量,用于记录读取的个数
int len;
//当数组中的数据没有读完
while((len = fis.read(b)) != -1) {
/将读取到的字节转换为字符打印
    System.out.println(new String(b, 0, len));
}
//关闭文件输入流,释放资源
fis.close();

FileOutputStream的例子:

FileInputStream fis = new FileInputStream("demo/b.txt");
//创建一个文件输出流
FileOutputStream fos = new FileOutputStream("demo/c.txt");
int len;
byte[] buf = new byte[1024];
while ((len = fis.read(buf)) != -1) {
   //向文件中写入数据,如果是非字节数据需要转成字节
    fos.write(buf, 0, len);
}
//关闭输出流
fos.close();
fis.close();

FileReader的例子:

//创建一个FileReader对象,用来读取demo/b.txt中的数据
FileReader fr = new FileReader("demo/b.txt");
//创建一个字符数组用来存储读取的输入
char[] chars = new char[100];
//定义读取到的字符长度
int len = 0;
//循环读取文件中的数据
while ((len = fr.read(chars)) != -1) {
//把读取到字符转为字符串输出
    System.out.print(new String(chars, 0, len));
}

//关闭输入流对象,释放资源
fr.close();

FileWriter的例子:

FileReader fr = new FileReader("demo/b.txt");
//创建一个FileWriter对象,用来读取demo/b.txt中的数据
FileWriter fw = new FileWriter("demo/c.txt");
char[] chars = new char[100];
int len = 0;
while ((len = fr.read(chars)) != -1) {
//向文件中写入数据,写入的是chars数组中的所有字符
    fw.write(chars, 0, len);
}
//关闭FileWriter流,释放资源。
fw.close();
fr.close();

FileOutputStream 和 FileWriter 构造函数的第二个参数(布尔值)可以指定是否追加数据到文件末尾。

数组(内存)

通常来说,针对文件的读写操作,使用文件流加上缓冲流就足够了,但为了提升效率,频繁读写文件并不太好,就出现了数组流,也被称为内存流。

ByteArrayInputStream 的例子:

// 创建一个 ByteArrayInputStream 对象,用于从字节数组中读取数据
InputStream is = new BufferedInputStream(new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)));
// 定义一个字节数组用于存储读取到的数据
byte[] bytes = new byte[1024];
// 定义一个变量用于存储每次读取到的字节数
int len = 0;
// 循环读取字节数组中的数据,并输出到控制台
while ((len = is.read(bytes)) != -1) {
            // 将读取到的字节转换为对应的字符串,并输出到控制台
    System.out.println(new String(bytes, 0, len));
}
// 关闭输入流,释放资源
is.close();

ByteArrayOutputStream 的例子:

 // 创建一个 ByteArrayOutputStream 对象,用于写入数据到内存缓冲区中
 ByteArrayOutputStream bos = new ByteArrayOutputStream();
// 定义一个字节数组用于存储要写入内存缓冲区中的数据
byte[] info = "Hello".getBytes();
// 向内存缓冲区中写入数据,这里写入的是 info 数组中的所有字节
bos.write(info, 0, info.length);
// 将内存缓冲区中的数据转换为字节数组
 byte[] dest = bos.toByteArray();
// 关闭 ByteArrayOutputStream 对象,释放资源
bos.close();

数组流可以用于在内存中读写数据,比如将数据存储在字节数组中进行压缩、加密、序列化等操作。         它的优点是不需要创建临时文件,可以提高程序的效率。缺点是,它只能存储有限的数据量,如果存储的数据量过大,会导致内存溢出。

缓冲

CPU速度相比内存快100倍,比磁盘块百万倍。那么程序和内存交互会很快,和硬盘交互相对就较慢,这样就会导致性能问题。

为了减少程序和硬盘之间的交互,提高程序的效率,java引入了缓冲流。

缓冲流在内存中设置了一个缓冲区,只有缓冲区存储了足够多的数据后,才会和内存或者硬盘进行交互。

BufferedInputStream的例子:

// 创建一个 BufferedInputStream 对象,用于从文件中读取数据
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("demo/a.txt"));

// 创建一个字节数组,作为缓存区
byte[] buffer = new byte[1024];

// 用来判断读取的个数
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
    // 对缓存区中的数据进行处理
    System.out.println(new String(buffer, 0, bytesRead));
}

// 关闭 BufferedInputStream,释放资源
bis.close();

BufferedOutputStream的例子:

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("demo/b.txt"));
// 创建一个 BufferedOutputStream 对象,用于将数据写入到文件中
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("demo/c.txt"));
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
    bos.write(buffer, 0, bytesRead);
}
// 刷新缓存区,将缓存区中的数据写入到文件中
bos.flush();
bos.close();
bis.close();

通过flush()方法将缓存区中的数据写入到文件中。在写入数据时,由于使用了BufferedOutputStream,数据会被先写到缓存区中,只有在缓存区被填满或者调用了flush方法时才会将缓存区中的数据写到文件中。

BufferedReader的例子:

// 创建一个 BufferedReader 对象,用于从文件中读取数据
BufferedReader br = new BufferedReader(new FileReader("demo/b.txt"));
// 读取文件中的数据,并将其存储到字符串中
String line;
while ((line = br.readLine()) != null) {
   // 对读取到的数据进行处理
   System.out.println(line);
}
// 关闭 BufferedReader,释放资源
br.close();

BufferWriter的例子:

BufferedReader br = new BufferedReader(new FileReader("demo/b.txt"));
// 创建一个 BufferedWriter 对象,用于将数据写入到文件中
BufferedWriter bw = new BufferedWriter(new FileWriter("demo/c.txt"));
String line;
while ((line = br.readLine()) != null) {
    bw.write(line + "\n");
}
 // 刷新缓存区,将缓存区中的数据写入到文件中
bw.flush();
// 关闭 BufferedWriter,释放资源
bw.close();
br.close();

使用缓冲流可以提高读写效率,减少了频繁的读写磁盘或网络的次数,从而提高了程序的性能。但是,在使用缓冲流时需要注意缓冲区的大小和清空缓冲区的时机,以避免数据丢失或不完整的问题。

对象序列化/反序列化

序列化本质上是将一个 Java 对象转成字节数组,然后可以将其保存到文件中,或者通过网络传输到远程。

 // 创建一个 ByteArrayOutputStream 对象 buffer,用于存储数据
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

// 使用 try-with-resources 语句创建一个 ObjectOutputStream 对象 output,并将其与 buffer 关联
try (ObjectOutputStream output = new ObjectOutputStream(buffer)) {

// 使用 writeUTF() 方法将字符串写入到缓冲区中
     output.writeUTF("字符串");
}
// 使用 toByteArray() 方法将缓冲区中的数据转换成字节数组,并输出到控制台
System.out.println(Arrays.toString(buffer.toByteArray()));

反序列化,就是再将字节数组转成Java对象的过程。

try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(
        new File("b.txt")))) {
    String s = input.readUTF();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值