Java基础——I/O流

Java基础——I/O流超详细讲解

引言

在Java编程中,I/O(Input/Output)流是非常重要的概念,它为程序与外部设备(如文件、网络等)之间的数据传输提供了一种机制。无论是读取文件内容、向文件写入数据,还是进行网络通信,都离不开I/O流的支持。本文将对Java的I/O流进行全面而深入的讲解。

一、I/O流的基本概念

1.1 流的定义

流是一种抽象的概念,它代表了数据的有序传输。就像水流一样,数据从一个源(如文件、网络连接)流向一个目标(如内存、另一个文件)。在Java中,流可以看作是一系列的数据序列,程序可以从流中读取数据(输入流),也可以向流中写入数据(输出流)。

1.2 流的分类

1.2.1 按流向分类
  • 输入流:用于从数据源读取数据到程序中。例如,从文件中读取内容到内存。在Java中,所有输入流的基类是InputStream(字节输入流)和Reader(字符输入流)。
  • 输出流:用于将程序中的数据写入到目标设备。比如,将内存中的数据写入到文件。所有输出流的基类是OutputStream(字节输出流)和Writer(字符输出流)。
1.2.2 按处理数据的单位分类
  • 字节流:以字节为单位进行数据处理,适合处理二进制数据,如图片、音频、视频等。InputStreamOutputStream是字节流的抽象基类。
  • 字符流:以字符为单位进行数据处理,主要用于处理文本数据。ReaderWriter是字符流的抽象基类。
1.2.3 按功能分类
  • 节点流:直接与数据源或目标相连,用于实际的数据传输。例如,FileInputStreamFileOutputStream用于直接操作文件。
  • 处理流:也称为包装流,它是对节点流的进一步封装,提供了更高级的功能,如缓冲、加密等。例如,BufferedInputStreamBufferedOutputStream提供了缓冲功能,提高了数据读写的效率。

二、字节流

2.1 字节输入流(InputStream)

InputStream是所有字节输入流的抽象基类,它定义了一系列用于读取字节数据的方法。常见的子类有FileInputStreamByteArrayInputStream等。

2.1.1 FileInputStream示例

FileInputStream用于从文件中读取字节数据。以下是一个简单的示例,展示了如何使用FileInputStream读取文件内容:

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("test.txt")) {
            int data;
            while ((data = fis.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,read()方法用于读取一个字节的数据,返回值为读取的字节,如果到达文件末尾则返回 -1。使用try-with-resources语句可以确保流在使用完毕后自动关闭,避免资源泄漏。

2.2 字节输出流(OutputStream)

OutputStream是所有字节输出流的抽象基类,它定义了一系列用于写入字节数据的方法。常见的子类有FileOutputStreamByteArrayOutputStream等。

2.2.1 FileOutputStream示例

FileOutputStream用于将字节数据写入到文件中。以下是一个简单的示例,展示了如何使用FileOutputStream写入数据到文件:

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamExample {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("test.txt")) {
            String data = "Hello, World!";
            byte[] bytes = data.getBytes();
            fos.write(bytes);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,write(byte[] b)方法用于将字节数组写入到文件中。

三、字符流

3.1 字符输入流(Reader)

Reader是所有字符输入流的抽象基类,它定义了一系列用于读取字符数据的方法。常见的子类有FileReaderBufferedReader等。

3.1.1 FileReader示例

FileReader用于从文件中读取字符数据。以下是一个简单的示例,展示了如何使用FileReader读取文件内容:

import java.io.FileReader;
import java.io.IOException;

public class FileReaderExample {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("test.txt")) {
            int data;
            while ((data = fr.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileInputStream类似,read()方法用于读取一个字符的数据,返回值为读取的字符,如果到达文件末尾则返回 -1。

3.2 字符输出流(Writer)

Writer是所有字符输出流的抽象基类,它定义了一系列用于写入字符数据的方法。常见的子类有FileWriterBufferedWriter等。

3.2.1 FileWriter示例

FileWriter用于将字符数据写入到文件中。以下是一个简单的示例,展示了如何使用FileWriter写入数据到文件:

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterExample {
    public static void main(String[] args) {
        try (FileWriter fw = new FileWriter("test.txt")) {
            String data = "Hello, World!";
            fw.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,write(String str)方法用于将字符串写入到文件中。

四、处理流

4.1 缓冲流

缓冲流是一种常见的处理流,它通过在内存中设置缓冲区,减少了与外部设备的直接交互次数,从而提高了数据读写的效率。常见的缓冲流有BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter

4.1.1 BufferedReader示例

BufferedReader用于高效地读取文本数据,它提供了readLine()方法,可以一次读取一行数据。以下是一个简单的示例:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,readLine()方法用于读取一行文本,返回值为读取的行内容,如果到达文件末尾则返回null

4.2 转换流

转换流用于在字节流和字符流之间进行转换。常见的转换流有InputStreamReaderOutputStreamWriter

4.2.1 InputStreamReader示例

InputStreamReader可以将字节输入流转换为字符输入流。以下是一个简单的示例:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("test.txt");
             InputStreamReader isr = new InputStreamReader(fis)) {
            int data;
            while ((data = isr.read()) != -1) {
                System.out.print((char) data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,InputStreamReaderFileInputStream转换为字符输入流,从而可以按字符读取文件内容。

五、对象流

对象流用于实现对象的序列化和反序列化。序列化是将对象转换为字节流的过程,反序列化则是将字节流恢复为对象的过程。常见的对象流有ObjectInputStreamObjectOutputStream

5.1 序列化示例

要实现对象的序列化,对象的类必须实现Serializable接口。以下是一个简单的示例:

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;

class Person implements Serializable {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class ObjectOutputStreamExample {
    public static void main(String[] args) {
        try (FileOutputStream fos = new FileOutputStream("person.ser");
             ObjectOutputStream oos = new ObjectOutputStream(fos)) {
            Person person = new Person("John", 30);
            oos.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,ObjectOutputStreamPerson对象序列化并写入到文件person.ser中。

5.2 反序列化示例

以下是一个简单的反序列化示例:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectInputStreamExample {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("person.ser");
             ObjectInputStream ois = new ObjectInputStream(fis)) {
            Person person = (Person) ois.readObject();
            System.out.println("Name: " + person.getName());
            System.out.println("Age: " + person.getAge());
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

在上述代码中,ObjectInputStream从文件person.ser中读取字节流,并将其反序列化为Person对象。

六、总结

Java的I/O流提供了丰富的类和方法,用于处理各种数据传输需求。通过合理选择字节流、字符流、处理流和对象流,可以高效地完成文件读写、网络通信等任务。在使用I/O流时,要注意资源的正确关闭,避免资源泄漏。同时,要根据具体的应用场景选择合适的流类型,以提高程序的性能和可维护性。希望本文对你理解Java的I/O流有所帮助。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值