Java中IO流常见的几种流

本文介绍了Java中的IO流,包括序列流如何合并和切割文件,打印流的操作过程,以及流的编码解码基础案例。同时,详细探讨了转换流的使用,帮助理解Java IO流在实际开发中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序列流

序列流合并文件

package com.cloud.day5;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.ArrayList;

import java.util.Enumeration;

import java.util.Vector;

/*

SequenceInputStream(序列流)

 */

public class Demo1 {

   public static void main(String[] args) throws IOException {

      merge1();

   }

   //3个文件合并成一个文件

   public static void merge3() throws IOException{

      File file1 = new File("F:\\a.txt");

      File file2 = new File("F:\\b.txt");

      File file3 = new File("F:\\c.txt");

      File file4 = new File("F:\\d.txt");

      //建立对应的输入输出流对象

      FileOutputStream fileOutputStream = new FileOutputStream(file4);

      FileInputStream fileInputStream1 = new FileInputStream(file1);

      FileInputStream fileInputStream2 = new FileInputStream(file2);

      FileInputStream fileInputStream3 = new FileInputStream(file3);     

      //创建序列流对象

      Vector<FileInputStream> vector = new Vector<FileInputStream>();

      vector.add(fileInputStream1);

      vector.add(fileInputStream2);

      vector.add(fileInputStream3);

      Enumeration<FileInputStream> e = vector.elements();

      SequenceInputStream sequenceInputStream = new SequenceInputStream(e);

      //读取文件数据

      byte[] buf = new byte[1024];

      int length = 0;

      while((length = sequenceInputStream.read(buf))!=-1){

        fileOutputStream.write(buf, 0, length);

      }

      sequenceInputStream.close();

      fileOutputStream.close();

   }

   //SequenceInputStream合并文件夹

   public static void meege2() throws IOException{

      File inFile1 = new File("F:\\a.txt");

      File inFile2 = new File("F:\\b.txt");

      File outFile = new File("F:\\c.txt");     

      FileOutputStream fileOutputStream = new FileOutputStream(outFile);

      FileInputStream fileInputStream1 = new FileInputStream(inFile1);

      FileInputStream fileInputStream2 = new FileInputStream(inFile2);     

      //建立序列流对象

      SequenceInputStream inputStream = new SequenceInputStream(fileInputStream1, fileInputStream2);

      byte[] buf = new byte[1024];

      int len=0;

      while((len = inputStream.read(buf))!=-1){

        fileOutputStream.write(buf, 0, len);

      }

      inputStream.close();

      fileOutputStream.close();

   }

   //合并a.txtb.txt内容

   public static void merge1() throws IOException{

      File inFile1 = new File("F:\\a.txt");

      File inFile2 = new File("F:\\b.txt");

      File outFile = new File("F:\\c.txt");

      FileOutputStream fileOutputStream = new FileOutputStream(outFile);

      FileInputStream fileInputStream1 = new FileInputStream(inFile1);

      FileInputStream fileInputStream2 = new FileInputStream(inFile2);

      ArrayList<FileInputStream> list = new ArrayList<FileInputStream>();

      list.add(fileInputStream1);

      list.add(fileInputStream2);

      byte[] buf = new byte[1024];

      int length = 0;

      for(int i=0;i<list.size();i++){

        FileInputStream fileInputStream = list.get(i);

        while((length = fileInputStream.read(buf))!=-1){

           fileOutputStream.write(buf, 0, length);

        }

        fileInputStream.close();

      }

      fileOutputStream.close();

   }

}

序列流切割文件

package com.cloud.day5;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.SequenceInputStream;

import java.util.Enumeration;

import java.util.Vector;

/*

切割一首MP3再合并

 */

public class Demo2 {

   public static void main(String[] args) throws IOException {

      File dir = new File("F:\\music");

      Vector<FileInputStream> vector = new Vector<FileInputStream>();

      File[] files = dir.listFiles();

      for(File file:files){

        if(file.getName().endsWith(".mp3")){

           vector.add(new FileInputStream(file));

        }

      }

      Enumeration<FileInputStream> e = vector.elements();

      SequenceInputStream inputStream = new SequenceInputStream(e);

      FileOutputStream fileOutputStream = new FileOutputStream("F:\\sum.mp3");

      byte[] buf = new byte[1024];

      int length = 0;

      while((length = inputStream.read(buf))!=-1){

        fileOutputStream.write(buf,0,length);

      }

      fileOutputStream.close();

      inputStream.close();

   }

   //切割MP3

   public static void cutFile() throws IOException{

      File file = new File("F:\\1.mp3");

      File dir = new File("F:\\music");

      FileInputStream fileInputStream = new FileInputStream(file);

      byte[] buf = new byte[1024*1024];

      int length = 0;

      for(int i=0;(length = fileInputStream.read(buf))!=-1;i++){

        FileOutputStream fileOutputStream = new FileOutputStream(new File(dir,"part"+i+".mp3"));

        fileOutputStream.write(buf, 0, length);

        fileOutputStream.close();

      }

      fileInputStream.close();

   }

}

打印流

打印流过程

package com.cloud.day1;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.PrintStream;

/*

打印流(printStream  打印流可以打印任意类型的数据,而且打印数据之前都会先把数据转换成字符串再进行打印。

*/

class Animal {

   String name;

   String color;

   public Animal(String name, String color) {

      this.name = name;

      this.color = color;

   }

   @Override

   public String toString() {

      return "Animal [name=" + name + ", color=" + color + "]";

   }

}

public class Demo1 {

   public static void main(String[] args) throws IOException {

      File file = new File("E:\\a.txt");

      //创建一个打印流

      /*

      PrintStream printStream = new PrintStream(file);

      printStream.println(123);

      printStream.println("spring");

      Animal animal = new Animal("Cat","black");

      printStream.println(animal);

      //默认标准的输出流就是向控制台输出

      System.out.println(printStream);

      */

      //收集日常的日志信息

      File logFile = new File("E:\\execption.log");

      PrintStream printStream = new PrintStream(new FileOutputStream(logFile,true));

      try {

        int c = 4/0;

        System.out.println("c="+c);

        int[] arr = null;

        System.out.println(arr.length);

      } catch (Exception e) {

        e.printStackTrace();

      }

   }

}

流的编码解码问题

基本案例

package com.cloud.day1;

import java.util.Arrays;

/*

编码和解码问题

编码:把看得懂的字符变成看懂码值,这个过程叫做编码

解码:把码值查找对应的字符,我们把这个过程称作为解码

注意:编码与解码一般我们都使用统一的码表。否则非常容易出乱码

 */

public class Demo2 {

   public static void main(String[] args) throws Exception {

      String str = "中国";

      //平台默认的编码表GBK

      byte []buf = str.getBytes("utf-8");

      System.out.println("数组的元素:"+Arrays.toString(buf));

      //默认使用GBK码表解码

      str = new String(buf,"utf-8");

      System.out.println("解码后的字符串:"+str);

      String str1 = "大家好";

      //使用GBK进行编码

      byte []buf1 = str1.getBytes();

      System.out.println("字节数组:"+Arrays.toString(buf1));

      str1 = new String(buf1 , "iso8859-1");

      //出现乱码后还原

      byte []buf2 = str1.getBytes("iso8859-1");

      str1 = new String(buf2 , "gbk");

      System.out.println(str1);

   }

}

转换流

转换流使用

package com.cloud.day1;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

/*

转换流:

输入字节流的转换流:InputStreamReader 是字节流通向字符流的桥

   InputStreamReader

输出字节流的转换流:

   OutputStreamWriter   可以把输出字节流转换成输出字符流 

转换流的作用:

   1. 如果目前所获取到的是一个字节流需要转换字符流使用,这时候就可以使用转换流。  字节流----> 字符流

   2. 使用转换流可以指定编码表进行读写文件。

*/

public class Demo3 {

   public static void main(String[] args) throws IOException {

      //readTest();

      //writeTest();

      readTest2();

   }

   //使用输入字节流的转换流指定码表进行读取文件数据

   public static void readTest2() throws IOException{

      File file = new File("D:\\a.txt");

      FileInputStream fileInputStream = new FileInputStream(file);

      //这里的编码如果使用UTF-8会发生乱码

      InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"gbk");

      char []buf = new char[1024];

      int length = 0;

      while((length = inputStreamReader.read(buf))!=-1){

        System.out.println(new String(buf , 0 , length));

      }

   }

   public static void writeTest() throws IOException{

      File file = new File("D:\\a.txt");

      FileOutputStream fileOutputStream = new FileOutputStream(file);

      OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);

      outputStreamWriter.write("Hello,春天");

      outputStreamWriter.close();

   }

   /**

    * 控制台输入:asa

    * 内容:asa

    * @throws IOException

    */

   public static void readTest() throws IOException{

      //获取标准的输入流

      InputStream in = System.in;

      //字节流转换成字符流

      InputStreamReader inputStreamReader = new InputStreamReader(in);

      //使用字符流的缓冲类

      BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

      String line = null;

      while((line = bufferedReader.readLine())!=null){

        System.out.println("内容:"+line);

      }

   }

}

<think>我们参考了关于Java IO的多个引用资料,现在需要回答用户的问题:JavaIO的分类有哪些? 根据引用资料,我们可以从多个角度对IO进行分类: 1. 按数据向分类(以内存为参照): - 输入(Input Stream):将数据从数据源(如文件)读取到内存中。 - 输出(Output Stream):将数据从内存写入到数据目的地(如文件)。 2. 按操作数据单位分类: - 字节:以8位字节(1 byte)为单位进行读写操作。可以处理所有类型的数据(包括文本、图片、音频、视频等)。 - 字符流:以16位字符(2 bytes)为单位进行读写操作。主要用于处理文本数据,能够处理字符编码问题。 3. 按的角色分类: - 节点:直接从数据源或目的地读写数据的,也称为低级。 - 处理:对已存在的(节点或处理)进行封装,提供更强大的读写功能(如缓冲、转换等),也称为高级。 此外,引用中还提到Java IO体系中有4个抽象基类,它们分别是: - 字节输入:`InputStream` - 字节输出:`OutputStream` - 字符输入:`Reader` - 字符输出:`Writer` JavaIO体系中的40多个类都是从这4个抽象基类派生出来的,并且子类的名称都是以父类名作为后缀(例如`FileInputStream`、`FileReader`等)。 下面我们详细展开每个分类: ### 1. 按数据向分类 - **输入**:用于从数据源读取数据。常见的输入有: - `InputStream`(字节输入基类) - `Reader`(字符输入基类) - 具体实现类:`FileInputStream`、`FileReader`等。 - **输出**:用于向目标写入数据。常见的输出有: - `OutputStream`(字节输出基类) - `Writer`(字符输出基类) - 具体实现类:`FileOutputStream`、`FileWriter`等。 ### 2. 按操作数据单位分类 - **字节**:用于处理二进制数据,如图片、音频、视频等。字节的基本单位是字节(8 bits)。主要的抽象基类有: - `InputStream`(字节输入) - `OutputStream`(字节输出) - **字符流**:用于处理文本数据,字符流的基本单位是字符(16 bits)。字符流在读写时会自动处理字符编码(如UTF-8、GBK等)。主要的抽象基类有: - `Reader`(字符输入) - `Writer`(字符输出) 注意:字符流实际上是在字节的基础上,通过`InputStreamReader`和`OutputStreamWriter`(属于处理)将字节转换为字符流,并指定字符编码。 ### 3. 按的角色分类 - **节点**:直接连接到数据源或目的地,负责直接读写数据。例如: - 文件:`FileInputStream`、`FileOutputStream`、`FileReader`、`FileWriter` - 数组:`ByteArrayInputStream`、`ByteArrayOutputStream`、`CharArrayReader`、`CharArrayWriter` - 管道:`PipedInputStream`、`PipedOutputStream`、`PipedReader`、`PipedWriter` - **处理**:对节点或其他处理进行包装,提供更便捷或更高效的功能。例如: - 缓冲:`BufferedInputStream`、`BufferedOutputStream`、`BufferedReader`、`BufferedWriter`(提供缓冲功能,减少I/O次数) - 转换:`InputStreamReader`(将字节输入转换为字符输入)、`OutputStreamWriter`(将字节输出转换为字符输出) - 数据:`DataInputStream`、`DataOutputStream`(用于读写基本数据类型和字符串) - 对象:`ObjectInputStream`、`ObjectOutputStream`(用于对象的序列化和反序列化) - 打印:`PrintStream`、`PrintWriter`(提供方便的打印方法) - 合并:`SequenceInputStream`(将多个输入合并为一个输入) ### 总结 Java中的IO分类可以归纳为三个维度: 1. **向**:输入 vs 输出 2. **数据单位**:字节 vs 字符流 3. **角色**:节点 vs 处理 整个Java IO体系都是建立在四个抽象基类(`InputStream`、`OutputStream`、`Reader`、`Writer`)之上的,通过组合和扩展这些基类,形成了丰富的IO类库。 下面是一个简单的类图关系(使用mermaid语法): ```mermaid classDiagram direction BT class InputStream class OutputStream class Reader class Writer class FileInputStream FileInputStream --|> InputStream class FileOutputStream FileOutputStream --|> OutputStream class FileReader FileReader --|> Reader class FileWriter FileWriter --|> Writer class BufferedInputStream BufferedInputStream --|> FilterInputStream FilterInputStream --|> InputStream class BufferedReader BufferedReader --|> Reader class InputStreamReader InputStreamReader --|> Reader ``` 注意:`FilterInputStream`是处理的基类,它包装了另一个输入(节点或其他处理)。 ### 示例代码 下面是一个使用字节字符流读取文件的简单示例: **字节读取文件(适合二进制文件)**: ```java try (InputStream in = new FileInputStream("test.jpg")) { int data; while ((data = in.read()) != -1) { // 处理每个字节 } } catch (IOException e) { e.printStackTrace(); } ``` **字符流读取文件(适合文本文件)**: ```java try (Reader reader = new FileReader("test.txt")) { int data; while ((data = reader.read()) != -1) { char ch = (char) data; // 处理每个字符 } } catch (IOException e) { e.printStackTrace(); } ``` **使用缓冲提高效率(处理)**: ```java try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) { String line; while ((line = br.readLine()) != null) { // 处理一行文本 } } catch (IOException e) { e.printStackTrace(); } ``` 通过以上分类和示例,我们可以清晰地了解Java IO的分类体系。 §§相关问题§§ 1. 字节字符流在什么场景下使用? 2. 处理(如缓冲)是如何提高IO效率的? 3. Java IO中哪些是节点?哪些是处理? 4. 如何选择使用字节还是字符流?</think>### Java IO 分类详解 根据引用资料,Java IO 体系主要从三个维度进行分类: #### 1. **按数据向分类**(以内存为参照) | 类型 | 功能描述 | 核心抽象类 | 典型实现类 | |------------|----------------------------------|----------------|------------------------| | **输入** | 将数据从外部源读取到内存 | `InputStream` | `FileInputStream` | | | | `Reader` | `FileReader` | | **输出** | 将数据从内存写入到外部目标 | `OutputStream` | `FileOutputStream` | | | | `Writer` | `FileWriter` | #### 2. **按操作数据单位分类** | 类型 | 单位 | 适用场景 | 抽象基类 | 特点 | |------------|--------|-----------------------------|----------------|-----------------------| | **字节** | 8 bit | 处理二进制文件(图片/视频等) | `InputStream` | 后缀为`Stream` | | | | | `OutputStream` | 如`FileInputStream` | | **字符流** | 16 bit | 处理文本文件 | `Reader` | 后缀为`Reader`/`Writer` | | | | | `Writer` | 如`FileReader` | #### 3. **按的角色分类** | 类型 | 功能描述 | 特点 | 典型实现类 | |--------------|----------------------------------|--------------------------|------------------------| | **节点** | 直接连接数据源/目的地 | 基础IO操作 | `FileInputStream` | | | | | `ByteArrayInputStream` | | **处理** | 包装节点,增强功能 | 提供高级功能 | `BufferedReader` | | (包装) | | 需传入节点作为参数 | `ObjectInputStream` | #### 完整分类体系图示 ```mermaid graph TD A[Java IO] --> B[按向] A --> C[按数据单位] A --> D[按角色] B --> B1[输入] B --> B2[输出] C --> C1[字节] C --> C2[字符流] D --> D1[节点] D --> D2[处理] B1 --> C1 B1 --> C2 B2 --> C1 B2 --> C2 D1 --> F[FileInputStream等] D2 --> G[BufferedReader等] ``` #### 关键特性对比 1. **抽象基类关系**: - 所有字节均派生自`InputStream`/`OutputStream` - 所有字符流均派生自`Reader`/`Writer` - 子类命名规则:父类名作为后缀(如`FileInputStream`)[^1][^2] 2. **处理工作原理**: ```java // 典型处理使用示例 try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { String line; while ((line = br.readLine()) != null) { // 增强的读取功能 System.out.println(line); } } ``` - 处理通过包装节点实现功能扩展(如缓冲、数据类型转换等) 3. **字符流本质**: - 底层通过`InputStreamReader`/`OutputStreamWriter`将字节转换为字符流 - 自动处理字符编码(如UTF-8、GBK等)[^2][^4] #### 典型应用场景 | 场景 | 推荐类型 | 原因 | |---------------------|------------------------|--------------------------| | 图片/视频传输 | 字节(如`FileInputStream`) | 保持二进制数据完整性 | | 文本文件读取 | 字符流(如`BufferedReader`) | 自动处理编码,支持按行读 | | 对象序列化 | 处理(`ObjectInputStream`) | 可直接读写Java对象 | | 内存数据操作 | 字节数组(`ByteArrayInputStream`) | 无需物理文件 | ### 总结 Java IO通过**向**(输入/输出)、**数据单位**(字节/字符)、**角色**(节点/处理)三个维度构建了完整的IO体系。40多个IO类均派生自4个抽象基类(`InputStream`, `OutputStream`, `Reader`, `Writer`),这种设计提供了高度灵活性和扩展性[^1][^2][^3]。 --- ### 相关问题 1. **字节字符流在读取文本文件时有何性能差异?** 2. **为什么处理需要包装节点才能工作?** 3. **如何选择合适的缓冲提高IO效率?** 4. **Java NIO与传统IO的主要区别是什么?** [^1]: IO的分类。按操作数据单位不同分为:字节(8 bit),字符流(16 bit)... [^2]: Java IO分类。按操作数据单位不同分为:字节(8bit)如二进制文件;字符流,如文本文件... [^3]: java中的IO:的分类。输入进行读操作,输出进行写操作... [^4]: Java IO的分类。这些类如果是以Stream单词结尾就是字节, 如果是以Reader结尾就是字符输入...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值