java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java流(Stream)、文件(File)和IO

Java中流(Stream)、文件(File)和IO示例详解

作者:杜小白也想的美

Java的流、文件和IO库为Java应用程序提供了强大且灵活的数据处理能力,这篇文章主要介绍了Java中流(Stream)、文件(File)和IO的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、Java 流(Stream)、文件(File)和IO概念和关系

Java 中的流(Stream)、文件(File)和 IO 之间是紧密关联但又各有侧重的概念,它们共同构成了 Java 输入输出系统的核心。可以用"工具-对象-操作"的关系来理解:

  1. IO 是总称
    IO(Input/Output,输入/输出)是所有数据传输操作的统称,涵盖了程序与外部设备(文件、网络、键盘等)之间的数据交换。
    流(Stream)和文件(File)都是实现 IO 操作的具体方式或操作对象。

  2. File 是操作的实体
    java.io.File 类代表文件系统中的一个文件或目录,是 IO 操作的具体对象
    但它本身不能直接读写数据,只能描述文件的属性(如路径、大小、是否存在等),并提供创建、删除等文件管理功能。

  3. Stream 是操作的工具
    流(Stream)是连接程序与外部数据源(包括 File)的数据传输通道,是实现 IO 操作的核心工具。
    当需要读写 File 中的内容时,必须通过流来实现:

    • 读文件:用输入流(如 FileInputStream)从 File 中读取数据到程序
    • 写文件:用输出流(如 FileOutputStream)从程序写入数据到 File
  4. 三者协作关系
    一个典型的文件 IO 操作流程是:
    创建 File 对象(指定要操作的文件) → 通过流连接 File(如 new FileInputStream(file)) → 通过流进行 IO 操作(读/写数据)

二、读写文件

2.1 操作文件时涉及的字符流和字节流的概念介绍:

字节流

字符流

字节流、字符流常用关系图

2.2 字节流常用方法

字节流常用于处理二进制数据,例如文件、图像、时频。

类名类型描述
InputStream抽象类(输入流)所有字节输入流的超类,处理字节的输入操作
OutputStream抽象类(输出流)所有字节输出流的超类,处理字节的输出操作
FileInputStream输入流从文件中读取字节数据
FileOutputStream输出流将字节数据写入文件
BufferedInputStream输入流为字节输入流提供缓冲功能,提高读取效率
BufferedOutputStream输出流为字节输出流提供缓冲功能,提高写入效率
ByteArrayInputStream输入流将内存中的字节数组作为输入源
ByteArrayOutputStream输出流将数据写入到内存中的字节数组
DataInputStream输入流允许从输入流中读取Java原生数据类型(如int、float、boolean等)
DataOutputStream输出流允许向输出流中写入Java原生数据类型
ObjectInputStream输入流从输入流中读取序列化对象
ObjectOutputStream输出流将对象序列化并写入输出流中
PipedInputStream输入流用于在管道中读取字节数据,通常与PipedOutputStream配合使用
PipedOutputStream输出流用于在管道中写入字节数据,通常与PipedInputStream配合使用
FilterInputStream输入流字节输入流的包装类,用于对其他输入流进行过滤处理
FilterOutputStream输出流字节输出流的包装类,用于对其他输出流进行过滤处理
SequenceInputStream输入流将多个输入流串联为一个输入流进行处理

以下是基于表格中各类字节流的读写文件示例,涵盖不同场景的文件操作:

1. FileInputStream/FileOutputStream(基础文件读写)

FileInputStream 和 FileOutputStream 是 Java IO 中用于直接操作文件的字节流,专门负责从文件读取字节数据和向文件写入字节数据,是处理文件字节流的基础类。

import java.io.*;

public class Main {
    public static void main(String[] args) {
        // 写入文件
        try {
            FileOutputStream fileOutputStream =new FileOutputStream("file.txt");
            String data="Hello byteStream!";
            fileOutputStream.write(data.getBytes());
            fileOutputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            FileInputStream fileInputStream =new FileInputStream("file.txt");
            int c;
            while((c=fileInputStream.read())!=-1){
                System.out.print((char)c);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2. BufferedInputStream/BufferedOutputStream(缓冲流高效读写)

BufferedInputStream 和 BufferedOutputStream 是 Java IO 中提供缓冲功能的过滤流,它们通过在内存中维护缓冲区来减少物理 I/O 操作次数,从而显著提升读写效率。

import java.io.*;

public class Main {
    public static void main(String[] args) {
        // 写入文件
        try {
            BufferedOutputStream bufferedOutputStream =new BufferedOutputStream(new FileOutputStream("file.txt"));
            String data="Hello byteStream!";
            bufferedOutputStream.write(data.getBytes());
            bufferedOutputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            BufferedInputStream bufferedInputStream =new BufferedInputStream(new FileInputStream("file.txt"));
            int c;
            while((c=bufferedInputStream.read())!=-1){
                System.out.print((char)c);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

3. DataInputStream/DataOutputStream(读写基本数据类型)

DataInputStream 和 DataOutputStream 是 Java IO 中用于读写基本数据类型的过滤流,它们可以直接操作 Java 原生数据类型(如 int、double、boolean 等),无需手动处理字节转换,简化了基本类型数据的读写操作。

import java.io.*;

public class Main {
    public static void main(String[] args) {
        // 写入文件
        try {
            DataOutputStream bufferedOutputStream =new DataOutputStream(new FileOutputStream("file.bat"));
            bufferedOutputStream.writeInt(100);       // 写入整数
            bufferedOutputStream.writeDouble(3.14);   // 写入双精度浮点数
            bufferedOutputStream.writeUTF("Hello byteStream!");
            bufferedOutputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            DataInputStream bufferedInputStream =new DataInputStream(new FileInputStream("file.bat"));
            System.out.println(bufferedInputStream.readInt());
            System.out.println(bufferedInputStream.readDouble());
            System.out.println(bufferedInputStream.readUTF());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

4. ObjectInputStream/ObjectOutputStream(对象序列化)

ObjectInputStream 和 ObjectOutputStream 是 Java 中用于对象序列化与反序列化的字节流,主要功能是将内存中的 Java 对象转换为字节序列(序列化)并写入流中,或从流中读取字节序列并恢复为 Java 对象(反序列化)。

import java.io.*;

// 需实现Serializable接口才能被序列化
class User implements Serializable {
    private String name;
    private int age;

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

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + "}";
    }
}

public class Main {
    public static void main(String[] args) {
        // 序列化对象写入文件
        try {
            ObjectOutputStream objectOutputStream =new ObjectOutputStream(new FileOutputStream("file.obj"));
            User user=new User("Alice", 18);
            objectOutputStream.writeObject(user);
            objectOutputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        try {
            ObjectInputStream objectInputStream=new ObjectInputStream(new FileInputStream("file.obj"));
            User user=(User) objectInputStream.readObject();
            System.out.println(user);
        } catch (IOException | ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
}

5.ByteArrayOutputStream(内存字节数组读写)

它可以将数据写入内存中的字节数组缓冲区。创建后可以用来收集和操作字节数据,常用于临时存储或处理二进制数据。

public class Main {
    public static void main(String[] args) {
        ByteArrayOutputStream byteArrayOutputStream =new ByteArrayOutputStream();
        byte [] bytes = new byte[1024];

        try {


            bytes[0]=(byte) 'H';
            bytes[1]=(byte) 'e';
            bytes[2]=(byte) 'l';
            bytes[3]=(byte) 'l';
            bytes[4]=(byte) 'o';
            byteArrayOutputStream.write(bytes,0,5);
            byteArrayOutputStream.close();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        ByteArrayInputStream byteArrayInputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        byte [] bytes1 = new byte[1024];
        int c;
        try{
            while ((c=byteArrayInputStream.read(bytes1))!=-1){
                System.out.println(new String(bytes1, 0, c));
            }
        }catch (IOException e){
            throw new RuntimeException(e);
        }


    }
}

6. SequenceInputStream(合并多个输入流)

import java.io.*;

public class Main {
    public static void main(String[] args) {
        try {
            SequenceInputStream sequenceInputStream =new SequenceInputStream(new FileInputStream("file.txt"),new FileInputStream("test.txt"));
            int c;
            while((c=sequenceInputStream.read())!=-1){
                System.out.print((char)c);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

}
}

7. FilterInputStream/FilterOutStream

FilterInputStream 和 FilterOutputStream 是 Java IO 中的过滤流基类,属于装饰器模式(Decorator Pattern)的典型实现,用于对现有流进行功能扩展或增强。

import java.io.FilterInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;

// 自定义过滤输入流:转换为大写
class UpperCaseInputStream extends FilterInputStream {
    /**
     * Creates a <code>FilterInputStream</code>
     * by assigning the  argument <code>in</code>
     * to the field <code>this.in</code> so as
     * to remember it for later use.
     *
     * @param in the underlying input stream, or <code>null</code> if
     *           this instance is to be created without an underlying stream.
     */
    protected UpperCaseInputStream(InputStream in) {
        super(in);
    }
    @Override
    public int read(byte [] b,int off,int len ) throws IOException {
         int result = super.read(b, off, len);//读取的字节数
         if(result!=-1){
             for(int i=off;i<off+result;i++){
                 b[i]= (byte) Character.toUpperCase((char)b[i]);
             }
         }
         return result;

    }
}

public class Main {
    public static void main(String[] args) {
        try {
            UpperCaseInputStream
                    upperCaseInputStream =new UpperCaseInputStream(new FileInputStream("file.txt"));
            int c;
            byte [] bytes=new byte[1024];
            while((c=upperCaseInputStream.read(bytes))!=-1){
                System.out.print(new String(bytes,0,c));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

8.pipedOutputStream/pipedInputStream

PipedOutputStream 和 PipedInputStream 是 Java 中用于线程间通信的管道流,二者必须配合使用,形成 “生产者 - 消费者” 模式的数据传输通道。

public class Main {
    public static void main(String[] args) {
        PipedOutputStream pipedOutputStream =new PipedOutputStream();
        PipedInputStream pipedInputStream;
        try {
            pipedInputStream =new PipedInputStream(pipedOutputStream);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    pipedOutputStream.write("Hello byteStream!".getBytes());
                    pipedOutputStream.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();

        new Thread(new Runnable(){
            @Override


            public void run() {
                try {
                    int c;
                    while((c=pipedInputStream.read())!=-1){
                        System.out.print((char)c);
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }

}

2.3 字符流常用方法

字符流常用于处理文本数据。

类名类型描述
Reader抽象类(输入流)所有字符输入流的超类,处理字符的输入操作
Writer抽象类(输出流)所有字符输出流的超类,处理字符的输出操作
FileReader输入流从文件中读取字符数据
FileWriter输出流将字符数据写入文件
BufferedReader输入流为字符输入流提供缓冲功能,支持按行读取,提高读取效率
BufferedWriter输出流为字符输出流提供缓冲功能,支持按行写入,提高写入效率
CharArrayReader输入流将字符数组作为输入源
CharArrayWriter输出流将数据写入到字符数组
StringReader输入流将字符串作为输入源
StringWriter输出流将数据写入到字符串缓冲区
PrintWriter输出流便捷的字符输出流,支持自动刷新和格式化输出
PipedReader输入流用于在管道中读取字符数据,通常与 PipedWriter 配合使用
PipedWriter输出流用于在管道中写入字符数据,通常与 PipedReader 配合使用
LineNumberReader输入流带行号的缓冲字符输入流,允许跟踪读取的行号
PushbackReader输入流允许在读取字符后将字符推回流中,以便再次读取

以下是字符流各类的读写文件示例,每个示例均包含写入和读取操作:

1. FileReader/FileWriter(文件字符读写)

import java.io.*;

public class Main {
    public static void main(String[] args) {
        // 写入文本到文件
        try (FileWriter writer = new FileWriter("test.txt")) {
            writer.write("Hello, FileReader/FileWriter!\n");
            writer.write("这是一行行中文文本");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 从文件读取文本
        try (FileReader reader = new FileReader("test.txt")) {
            char[] buffer = new char[1024];
            int len;
            while ((len = reader.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. BufferedReader/BufferedWriter(缓冲字符流)

public class Main {
    public static void main(String[] args) {
        // 按行写入文本(指定UTF-8编码)
        try (BufferedWriter writer = new BufferedWriter(
                new OutputStreamWriter(new FileOutputStream("buffered.txt"), StandardCharsets.UTF_8))) {
            writer.write("第一行内容");
            writer.newLine(); // 跨平台换行
            writer.write("第二行内容");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 按行读取文本
        try (BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream("buffered.txt"), StandardCharsets.UTF_8))) {
            String line;
            while ((line = reader.readLine()) != null) { // 按行读取
                System.out.println("读取到:" + line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. CharArrayReader/CharArrayWriter(字符数组流)

CharArrayReader 和 CharArrayWriter 是 Java 中以字符数组为操作对象的字符流,所有操作均在内存中基于字符数组完成,无需依赖外部存储。

import java.io.*;

public class CharArrayReadWriteExample {
    public static void main(String[] args) {
        // CharArrayWriter先写入字符数组(内存中)
        CharArrayWriter caw = new CharArrayWriter();
        try {
            caw.write("先写入内存字符数组,再转存到文件");
            char[] charData = caw.toCharArray(); // 获取字符数组

            // 写入文件
            try (FileWriter fw = new FileWriter("charArray.txt")) {
                fw.write(charData);
            }

            // CharArrayReader从字符数组读取
            CharArrayReader car = new CharArrayReader(charData);
            char[] buffer = new char[1024];
            int len;
            System.out.println("CharArrayReader读取内容:");
            while ((len = car.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
            car.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            caw.close();
        }
    }
}

4. StringReader/StringWriter(字符串流)

StringReader 和 StringWriter 是 Java 中操作内存字符串的字符流,无需依赖外部文件,所有操作均在内存中完成。

import java.io.*;

public class StringReadWriteExample {
    public static void main(String[] args) {
        // StringWriter写入字符串缓冲区
        StringWriter sw = new StringWriter();
        try {
            sw.write("字符串流操作示例\n");
            sw.write("数据保存在StringBuffer中");
            String data = sw.toString(); // 获取字符串

            // 写入文件
            try (FileWriter fw = new FileWriter("string.txt")) {
                fw.write(data);
            }

            // StringReader从字符串读取
            StringReader sr = new StringReader(data);
            char[] buffer = new char[1024];
            int len;
            System.out.println("StringReader读取内容:");
            while ((len = sr.read(buffer)) != -1) {
                System.out.print(new String(buffer, 0, len));
            }
            sr.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            sw.close();
        }
    }
}

5. PrintWriter(格式化字符输出流)

PrintWriter 是 Java 中功能强大的字符输出流,提供了便捷的文本写入、格式化输出和自动刷新等功能,广泛用于输出文本数据到文件、控制台或其他输出流。

import java.io.*;

public class PrintWriterExample {
    public static void main(String[] args) {
        // PrintWriter写入(支持格式化和自动刷新)
        try (PrintWriter pw = new PrintWriter(new FileWriter("print.txt"), true)) { // 第二个参数开启自动刷新
            pw.println("PrintWriter便捷输出");
            pw.printf("格式化输出:%d + %d = %d%n", 2, 3, 5); // 类似printf格式
            pw.println("自动刷新生效");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 读取验证
        try (BufferedReader br = new BufferedReader(new FileReader("print.txt"))) {
            System.out.println("PrintWriter写入内容:");
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6. PipedReader/PipedWriter(管道字符流,线程间通信)

import java.io.*;

public class PipedReadWriteExample {
    public static void main(String[] args) throws IOException {
        // 创建管道流对(必须绑定)
        PipedWriter pw = new PipedWriter();
        PipedReader pr = new PipedReader(pw);

        // 写入线程
        Thread writerThread = new Thread(() -> {
            try {
                pw.write("管道流线程间通信数据");
                pw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        // 读取线程(并写入文件)
        Thread readerThread = new Thread(() -> {
            try (FileWriter fw = new FileWriter("piped.txt")) {
                char[] buffer = new char[1024];
                int len;
                while ((len = pr.read(buffer)) != -1) {
                    fw.write(buffer, 0, len); // 写入文件
                    System.out.println("管道读取内容:" + new String(buffer, 0, len));
                }
                pr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        });

        writerThread.start();
        readerThread.start();
    }
}

7. LineNumberReader(带行号的字符输入流)

LineNumberReader 是 Java 中带有行号跟踪功能的缓冲字符输入流,继承自 BufferedReader,在提供高效缓冲读取的同时,能自动跟踪当前读取的行号,方便定位文本中的特定行。

import java.io.*;

public class LineNumberReaderExample {
    public static void main(String[] args) {
        // 先写入多行数据
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("linenumber.txt"))) {
            bw.write("第一行内容");
            bw.newLine();
            bw.write("第二行内容");
            bw.newLine();
            bw.write("第三行内容");
        } catch (IOException e) {
            e.printStackTrace();
        }

        // LineNumberReader读取并跟踪行号
        try (LineNumberReader lnr = new LineNumberReader(new FileReader("linenumber.txt"))) {
            lnr.setLineNumber(1); // 设置起始行号(默认从0开始)
            String line;
            System.out.println("带行号的内容:");
            while ((line = lnr.readLine()) != null) {
                System.out.printf("第%d行:%s%n", lnr.getLineNumber(), line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

8. PushbackReader(可回退字符的输入流)

PushbackReader 是 Java 中的一个字符输入流,继承自 FilterReader,它的特殊之处在于允许将已读取的字符 “推回”(回退)到流中。

import java.io.*;

public class Main {
    public static void main(String[] args) {

        try {
            PushbackReader reader =new PushbackReader(new FileReader("file.txt"));
            int c;
            while((c=reader.read())!=-1){
                if(c=='o'){
                    reader.unread(c);
                    break;
                }
                System.out.println(":"+(char)c
                );
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }
}

总结 

到此这篇关于Java中流(Stream)、文件(File)和IO的文章就介绍到这了,更多相关Java流(Stream)、文件(File)和IO内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文