当前位置: 首页 > news >正文

Java IO流详解

1. IO概述

IO(Input/Output)即输入和输出,指的是设备或环境之间进行数据的输入或输出。例如,键盘是输入设备,显示器是输出设备。在Java中,输入输出问题通过流(Stream)对象来解决。以程序为中心,读取文件是输入,写入文件是输出。

1.1 流的分类

Java中的IO流可以从两个角度进行分类:

  1. 从输入输出角度分类

    • 输入流:用于读取数据。

    • 输出流:用于写入数据。

  2. 从数据的角度分类

    • 字符流:处理文本数据,如文章、Java文件等。

    • 字节流:处理二进制数据,如图片、MP3文件等。

2. 字符流

字符流用于处理文本数据,如文章、Java文件等。字符流的类命名规则如下:

  • 如果是输出流,类名以Writer结尾。

  • 如果是输入流,类名以Reader结尾。

2.1 案例:使用字符流向文件写入"HelloWorld"

public class IOTest {

    public static void main(String[] args) {
        // 创建一个文件
        File file = new File("test.txt");
        Writer writer = null;

        try {
            // 创建输出流对象
            writer = new FileWriter(file);
            // 写入数据
            writer.write("HelloWorld");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.2 文件的追加

public class IOTest4 {

    public static void main(String[] args) {
        Writer writer = null;

        try {
            // 追加模式
            writer = new FileWriter("test1.txt", true);
            writer.write("liangliang");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.3 换行

不同操作系统下的换行符不同:

  • Windows: \r\n

  • Linux: \n

  • Mac: \r

public class IOTest5 {

    public static void main(String[] args) {
        File file = new File("test.txt");
        Writer writer = null;

        try {
            writer = new FileWriter(file);
            for (int i = 0; i < 100; i++) {
                writer.write("HelloWorld\r\n");
                if (i % 10 == 0) {
                    writer.flush();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.4 Writer的五种写入方法

public class IOTest6 {
    public static void main(String[] args) {
        File file = new File("test.txt");
        Writer writer = null;

        try {
            writer = new FileWriter(file);
            char[] c = {'a', 'b', 'p', 'b', 'p'};
            writer.write(c); // 写入整个数组
            writer.write(c, 2, 2); // 写入数组的一部分
            writer.write(97); // 写入单个字符
            writer.write("helloworld", 2, 2); // 写入字符串的一部分
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

2.5高效缓冲流

高效缓存字符输入流:BufferReader

高效缓存字符输出流:BufferWriter

高效缓存字节流:

BufferedInputStream,BufferedOutputStream

用法案例

package cn.tedu.buffer;

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

public class BufferWriterDemo {

    public static void main(String[] args) {
        //创建高效缓冲字符输出流
        BufferedWriter writer = null;

        try {
            writer = new BufferedWriter(new FileWriter("IOTest.java"));
            //写一行数据
            writer.write("helloworld");
            //换行
            writer.newLine();
            writer.write("helloworld");
            writer.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {

            //资源关闭
            if(writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }
}

2.6 文件的复制

利用字符输入输出流 实现文件的拷贝功能

案例

package cn.tedu.demo1;

import java.io.*;

/**
 * 利用字符输入输出流
 * 实现文件的拷贝功能
 */
public class CopyDemo2 {

    //主函数  主程序   入口
    public static void main(String[] args) {
        //1.创建需要的输出输入流对象
        Reader reader=null;
        Writer writer=null;
        //2.创建要拷贝的文件file对象  以及要到达的新文件
        File file=new File("test3.txt");
        File file1=new File("test5.txt");
        //3.利用字符输入流读取文件test3.txt
        try {
            //读取文件test3.txt
            reader = new FileReader(file);
            //创建字符输出流对象
            writer=new FileWriter(file1);
            //创建一个字符数组  减少读取的io次数
            char [] cs = new char[1024];
            //定义边界值
            int len = -1;
            //利用循环  找到边界值  读取文件
            while((len = reader.read(cs)) != -1){
                //此时读到的内容要写进新的文件通过字符输出流
                //把输入流读取到的数据写入字符输出流
                writer.write(cs, 0, len);
            }
            //为了解决传递压迫性能问题  使用flush操作
            writer.flush();
            //改成大异常 更方便
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //最后把两个流关闭
            try {
                if(writer != null){
                    writer.close();
                }
                if(reader != null){
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3. 字符流与字节流的桥梁

OutputStreamWriter是字符流转向字节流的桥梁,可以指定编码格式。

public class ConverterDemo {

    public static void main(String[] args) {
        OutputStreamWriter ow = null;

        try {
            ow = new OutputStreamWriter(new FileOutputStream("b.txt"), "GBK");
            ow.write("中");
            ow.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (ow != null) {
                    ow.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4. Properties类

Properties类表示一个持久的属性集,可以保存在流中或从流中加载。它继承自Hashtable,是线程安全的键值对存储结构。

public class PropTest6 {
    public static void main(String[] args) {
        Properties prop = new Properties();
        InputStream in = null;

        try {
            in = PropTest6.class.getClassLoader().getResourceAsStream("names.properties");
            prop.load(in);
            System.out.println(prop);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

5. 序列化流

序列化流用于将对象写入输出流或从输入流中读取对象。

5.1 ObjectOutputStream

要序列化的对象需要实现Serializable接口。

public class ObjectOutputStreamDemo {

    public static void main(String[] args) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.txt"))) {
            oos.writeObject(new Person("张三", 20));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;

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

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

6. 字符编码

字符编码决定了字符在计算机中的存储和展示方式。常见的编码方式有ASCII、GBK、UTF-8等。

  • ASCII:最早的字符编码标准,仅支持英文字符。

  • GBK:用于存储中文字符的编码。

  • UTF-8:一种通用的字符编码,支持几乎所有字符。

注意:编码和解码需要使用相同的字符集,否则会出现乱码。

代码演示案例:

package cn.tedu.test;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Utf8Cladd {
    public static void main(String[] args) {
        String str="中";
        try {
            //str=new String(str.getBytes("UTF-8"),"GBK");
            System.out.println(str);
            byte[] bytes = str.getBytes();
            System.out.println(Arrays.toString(bytes));
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

相关文章:

  • Web3 开发者周刊 36 | 构建自主未来:Agent、可扩展性与赏金
  • Android ndk兼容 64bit so报错
  • 【Elasticsearch】simple_query_string
  • AI 工具相关的临床研究或是不久将来主要的临床研究内容之一
  • Git 建立远端仓库并push
  • MacOS使用PhpWebStudy搭建PHP开发环境
  • The Simulation技术浅析(六):机器学习
  • LabVIEW袜品压力测试系统
  • IP 路由基础 | 路由条目生成 / 路由表内信息获取
  • 自制游戏——斗罗大陆
  • HtmlRAG:RAG系统中,HTML比纯文本效果更好
  • 用于处理元素的全屏显示和退出全屏操作--useFullScreen
  • 在Vue中,JavaScript数组常用方法,添加,插入,查找,删除等整理
  • 【线性代数】1行列式
  • SpringBoot初始化8个常用方法
  • 浅聊如何通过redis去做一个排行榜
  • 人工智能浪潮下脑力劳动的变革与重塑:挑战、机遇与应对策略
  • Redis 内存回收机制
  • 通过docker安装部署deepseek以及python实现
  • Git 分布式版本控制工具使用教程
  • 巴基斯坦外长:印巴停火
  • 湖北宜昌:在青山绿水间解锁乡村振兴“密码”
  • 北京2025年住房发展计划:供应商品住房用地240-300公顷,建设筹集保租房5万套
  • “毛茸茸”的画,诗意、温暖又治愈
  • 溢价26.3%!保利置业42.4亿元竞得上海杨浦宅地,楼板价80199元/平方米
  • 欧盟公布关税反制清单,瞄准美国飞机、汽车等产品