Java IO详解

这篇具有很好参考价值的文章主要介绍了Java IO详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、I/O简介

IO即Input和Output,即输入和输出。这里的输入和输出都是相对于内存来说的,具体见下图。
java io,java,设计模式,java
InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流。
OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流。
字节是计算机存储容量的基本单位(Byte),1B=8b,二进制中占8位。
字符是文字或符号的统称。
字节流什么类型的文件都可以读取,字符流只能读取纯文本文件。

二、字节流

1、InputStream && OutputStream

InputStream 类图如下:
java io,java,设计模式,java
OutputStream类图如下:
java io,java,设计模式,java

从jdk8文档中,InputStream 方法如下:
java io,java,设计模式,java
OutputStream方法如下:
java io,java,设计模式,java
从 Java 9 开始,InputStream 新增加了多个实用的方法:

readAllBytes():读取输入流中的所有字节,返回字节数组。
readNBytes(byte[] b, int off, int len):阻塞直到读取 len 个字节。
transferTo(OutputStream out):将所有字节从一个输入流传递到一个输出流。

2、FileInputStream && FileOutputStream

我们日常使用的话,比较常见的就是FileInputStream了,其可直接指定文件路径,可以直接读取单字节数据,也可以读取至字节数组中。
FileInputStream 示例代码如下:

 public static void main(String[] args) {
        try {
            FileInputStream fileInputStream = new FileInputStream("inputTest.txt");
            //1、返回从该输入流中可以读取(或跳过)的字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
            int available = fileInputStream.available();
            System.out.println("available:" + available);
            //2、跳过并丢弃来自此输入流的 2字节数据。
            long skip = fileInputStream.skip(2);
            System.out.println("skip:" + skip);
            //3、读取文件内容,为了减少IO,我们创建一个Byte数组作为接收缓冲区
            byte[] bytes = new byte[4];
            int read;
            //4、从输入流读取一些字节数,并将它们存储到缓冲区 b 。
            while ((read = fileInputStream.read(bytes)) != -1) {
                // 把byte数组转换成字符串
                System.out.print(new String(bytes, 0, read));
            }
            if (fileInputStream != null) {
                fileInputStream.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

inputTest.txt文件如下:
java io,java,设计模式,java
输出结果如下:

available:11
skip:2
adafadsff

FileOutputStream有如下构造方法:

public FileOutputStream(String name, boolean append)

boolean append为true表示在创建的文件存在时,不会清空原文件内容,以追加的方式写入。
若文件不存在,则新增文件。
示例代码如下:

 public static void main(String[] args) {
        try {
            FileOutputStream fileOutputStream = new FileOutputStream("outputTest.txt");
            String s = "lalalaaadhawe";
            // 将字符串转换为byte数组
            byte[] bytes = s.getBytes();
            fileOutputStream.write(bytes);
            fileOutputStream.flush();
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

运行结果如下:
java io,java,设计模式,java

3、字节流的文件复制

学完了FileInputStream && FileOutputStream,我们可以利用其做文件复制,代码如下:

public static void main(String[] args) {
        try {
            FileInputStream fileInputStream = new FileInputStream("inputTest.txt");
            FileOutputStream fileOutputStream = new FileOutputStream("copy.txt");
            //一次拷贝4个字节
            byte[] bytes = new byte[4];
            int read;
            //4、从输入流读取一些字节数,并将它们存储到缓冲区 b 。
            while ((read = fileInputStream.read(bytes)) != -1) {
                fileOutputStream.write(bytes, 0, read);
            }
            fileOutputStream.flush();
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

4、BufferedInputStream && BufferedOutputStream

我们通过上面代码,可以看到,为了减少IO次数,可以设立一个缓冲池byte,提高读取效率。而BufferedInputStream 和BufferedOutputStream的设计初衷就是如此,通常我们也是使用带缓冲区的BufferedInputStream ,其源码如下:

public
class BufferedInputStream extends FilterInputStream {
    // 内部缓冲区数组
    protected volatile byte buf[];
    // 缓冲区的默认大小
    private static int DEFAULT_BUFFER_SIZE = 8192;
    // 使用默认的缓冲区大小
    public BufferedInputStream(InputStream in) {
        this(in, DEFAULT_BUFFER_SIZE);
    }
    // 自定义缓冲区大小
    public BufferedInputStream(InputStream in, int size) {
        super(in);
        if (size <= 0) {
            throw new IllegalArgumentException("Buffer size <= 0");
        }
        buf = new byte[size];
    }
}

5、DataInputStream && DataOutputStream

这一对类可以直接写入java基本类型数据(没有String),但写入以后是一个二进制文件的形式,不可以直接查看。
示例代码如下:

DataInputStream dis = new DataInputStream(fileInputStream);
            dis.readInt();
            /**
             * 即使存入越界的树65538,也不会报错,因为超出部分不会被存入,存入的只是超出的部分。
             * short类型占据16位的空间,因此将65538转为二进制数,超出16位的部分自动截掉,只保留16为以内的数据。
             */
            dis.readShort();
            dis.readLong();
            dis.readByte();
            dis.readChar();
            dis.readDouble();
            dis.close()

6、序列化和反序列化 ObjectInputStream && ObjectOutputStream

Java 序列化就是指将对象转换为字节序列的过程,而反序列化则是将字节序列转换成目标对象的过程。具体参考:java中的序列化和transient关键字。
ObjectInputStream 用于从输入流中读取 Java 对象(反序列化),ObjectOutputStream 用于将对象写入到输出流(序列化)。
示例如下:

ObjectInputStream input = new ObjectInputStream(new FileInputStream("object.data"));
MyClass object = (MyClass) input.readObject();
input.close();

7、打印流PrintStream

PrintStream源自OutputStream,其为标准字节的输出流,默认输出到控制台,也就是我们常用的System.out.println()方法。
java io,java,设计模式,java
日志框架的实现原理就是通过PrintStream的使用,输出到日志文件,示例如下:

public static void log(String msg) {
        try {
            // 指向一个日志文件
            PrintStream ps = new PrintStream(new FileOutputStream("log.txt",true));
            // 改变流的输出方向
            System.setOut(ps);
            // 获取系统当前时间
            Date nowTime = new Date();
            // 日期格式化
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
            String strTime = sdf.format(nowTime);
            System.out.println(strTime+": "+msg);
            ps.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        log("第1次打印日志");
        log("第2次打印日志");
        log("第3次打印日志");
    }

运行结果如图:
java io,java,设计模式,java

三、字符流

首先,确认一个问题,已经有字节流了,可以读取任意文件,为什么还要有字符流呢?
主要有以下原因:
1、对于字符文件,先作为字节传输,再转成字符,耗时耗力。
2、对于字符文件,转成字节之后,再转回来,如果是中文,很容易乱码。

1、Reader && Writer

类图如下:
java io,java,设计模式,java
java io,java,设计模式,java

2、FileReader && FileWriter

字符流常用的读写类为FileReader 与 FileWriter,我们还用复制文件来做示例,示例代码如下:

 public static void main(String[] args) throws IOException {
            FileReader fileReader = new FileReader("file.txt");
            FileWriter fileWriter = new FileWriter("file2.txt");
            //一次拷贝4个字节
            char[] chars = new char[1024*1024];
            int read;
            while ((read = fileReader.read(chars)) != -1) {
                fileWriter.write(chars, 0, read);
            }
            fileWriter.flush();
            if (fileReader != null) {
                fileReader.close();
            }
            if (fileWriter != null) {
                fileWriter.close();
            }

    }

执行结果如下:
java io,java,设计模式,java
中文没有乱码。
BufferedReader和BufferedWriter,类似于BufferedInputStream和BufferedOutputStream,内部都维护了一个字节数组作为缓冲区。

四、随机访问流RandomAccessFile

RandomAccessFile 支持随意跳转到文件的任意位置进行读写,任意位置进入文件。
RandomAccessFile 比较常见的就是断点续传,适用于大文件的分片上传,后面单独开一篇文章进行总结。

五、IO中的设计模式

1、适配器模式

适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。具体参考:java(面向对象)的23种设计模式(5)——适配器模式。
在Java IO中,为了实现字符流和字节流之间的相互转换,就产生了两个适配器的类,InputStreamReader 和 OutputStreamWriter 。
代码如下:

InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(isr);

2、装饰器模式

装饰器模式可以将新功能动态地附加于现有对象而不改变现有对象的功能。具体参考:java(面向对象)的23种设计模式(7)——装饰模式。
InputStream 的子类 FilterInputStream,OutputStream 的子类 FilterOutputStream,Reader 的子类 BufferedReader 以及 FilterReader,还有 Writer 的子类 BufferedWriter、FilterWriter 以及 PrintWriter 等,它们都是抽象装饰类。增强了子类对象的功能。

3、工厂模式

工厂模式,通过定义工厂父类负责创建对象的公共接口,而子类则负责生成具体的对象。具体参考:
java(面向对象)的23种设计模式(3)——工厂模式。

NIO 中大量用到了工厂模式,比如 Files 类的 newInputStream 方法用于创建 InputStream 对象(静态工厂)、 Paths 类的 get 方法创建 Path 对象(静态工厂)、ZipFileSystem 类(sun.nio包下的类,属于 java.nio 相关的一些内部实现)的 getPath 的方法创建 Path 对象(简单工厂)。

4、观察者模式

观察者模式:指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。具体参考:java(面向对象)的23种设计模式(11)——观察者模式。
NIO 中的文件目录监听服务基于 WatchService 接口和 Watchable 接口。WatchService 属于观察者,Watchable 属于被观察者。WatchService 用于监听文件目录的变化,同一个 WatchService 对象能够监听多个文件目录。文章来源地址https://www.toymoban.com/news/detail-797325.html

到了这里,关于Java IO详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java设计模式之策略模式详解

    大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,让我们一同踏入Java设计模式之策略模式的世界,探讨代码中的智慧抉择。 策略模式的核心思想 策略模式是一种行为型设计模式,它定义了算法家族

    2024年01月20日
    浏览(47)
  • 03-JAVA设计模式-单例模式详解

    单例模式(Singleton Pattern)是设计模式中的一种,它确保一个类仅有一个实例,并提供一个全局访问点来访问该实例。这种设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 单例模式的应用场景十分广泛,主要涉及需要频繁使用某个对象而又不想重复创建的情况

    2024年04月13日
    浏览(56)
  • JAVA设计模式详解 解构设计模式思想 详细代码对比

    设计模式-01简单工厂模式详解 详细代码对比

    2024年02月09日
    浏览(51)
  • Java设计模式之适配器模式详解

    大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!在今天的篇章中,我们将深入探讨Java设计模式的奇妙世界,而焦点就是适配器模式。这种模式就像是代码变换的艺术大师,让不同的接口和类在项目中和谐

    2024年01月19日
    浏览(49)
  • Java设计模式之备忘录模式详解

    大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天,让我们一起探讨Java设计模式之备忘录模式,这种像时间旅行般的对象记忆术,是如何在程序的世界里实现的。 备忘录模式的引入 备忘录模式是一种

    2024年01月22日
    浏览(72)
  • Java设计模式详解-更新中

            免费阅读,请关注 IT技术馆 公众号。   收藏和关注的同时,请也关注 公众号 “IT技术馆” 各位大家好,从今天开始,作者开始整理 《JAVA软件设计模式(GOF)》 专栏。请各位多多关注!         该专栏是根据作者的技术经验和设计模式的了解,进行详细的讲解。

    2024年01月22日
    浏览(55)
  • JAVA设计模式详解(独家AI解析)

    可以查阅JAVA快速入门体验 设计模式的六大原则是一组指导性原则,它们帮助开发人员设计出灵活、可维护和可扩展的软件系统。以下是这些原则的简要介绍: 单一职责原则 (Single Responsibility Principle,SRP): 一个类应该只有一个引起它变化的原因。换句话说,一个类应该只

    2024年02月08日
    浏览(43)
  • Java设计模式之建造者模式详解(Builder Pattern)

    在日常的开发工作中,我们常常需要创建一些复杂的对象。这些对象可能包含许多不同的属性,并且这些属性的初始化过程可能相当复杂。在这种情况下,建造者模式是一种非常有用的设计模式,因为它允许我们分步骤地创建复杂的对象。 概念和原理: 建造者模式(Builder

    2024年02月09日
    浏览(45)
  • Java设计模式之单例模式详解--独一无二的事物

    本文主要讲述 单例模式 ,文中使用通俗易懂的案例,使你更好的学习本章知识点并理解原理,做到有道无术。 单例模式是23种设计模式中 创建型模式 的一种,通过单例模式的方法创建的类在当前进程或者线程中只有一个实例。单例模式有两种比较常见的实现方式: 饿汉式

    2024年02月07日
    浏览(45)
  • Java设计模式之责任链模式(UML类图分析+代码详解)

    大家好,我是一名在算法之路上不断前进的小小程序猿!体会算法之美,领悟算法的智慧~ 希望各位博友走过路过可以给我点个免费的赞,你们的支持是我不断前进的动力!! 加油吧!未来可期!! 本文将介绍java设计模式之责任链模式 OA系统采购审批需求 传统方案解决OA系

    2024年02月06日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包