滚雪球学Java(74):深入理解JavaSE输入输出流:掌握数据流动的奥秘

news/2024/5/1 4:11:39

在这里插入图片描述

  咦咦咦,各位小可爱,我是你们的好伙伴 bug菌,今天又来给大家手把手教学Java SE系列知识点啦,赶紧出来哇,别躲起来啊,听我讲干货记得点点赞,赞多了我就更有动力讲得更欢哦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~


🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

文章目录

  • 前言
  • 摘要
  • 正文
    • 简介
    • 源代码解析
      • InputStream类
      • OutputStream类
      • BufferedInputStream类
      • BufferedOutputStream类
    • 应用场景案例
      • 文件复制
    • 优缺点讲解
      • 优点分析
      • 缺点分析
    • 类常用方法介绍
      • InputStream类
      • OutputStream类
      • BufferedInputStream类
      • BufferedOutputStream类
    • 测试用例
      • 测试代码
      • 测试代码分析
      • 测试结果
    • 小结
  • 全文总结
    • 附录源码
  • ☀️建议/推荐你
  • 📣关于我

前言

  首先,我们都知道输入输出流是Java SE开发中非常重要的一个组成部分,它们可以让程序与外部环境进行数据的交互,若无进行数据交换,则无法动态展示数据。借此,本文将深入探讨JavaSE中的输入输出流机制,并通过详细的源代码解析和实际应用场景案例,帮助大家全面理解JavaSE输入输出流的原理和用法,这对日常工作中的你或者即将步入职场的你都及其有帮助。

摘要

  JavaSE针对输入输出流,它提供了非常丰富的类和方法,供日常处理各种类型的数据流动。通过输入流,我们可以读取外部数据到程序中,拿到数据再进一步操作等;而对应输出流,我们可以将程序中的数据输出到外部环境。这里大家需要理解和灵活运用 Java之输入输出流,这也是身为Java开发人员(程序猿)必备的技能,毕竟我入社会也是从这些知识点学起的。

正文

简介

  首先,大家需要明确知道一点,JavaSE的输入输出流,它是属于面向字节的流,是基于抽象类InputStreamOutputStream以及相应的子类来实现的。数据流动的核心是字节流,而JavaSE中就提供了许多类和方法供大家可方便的操作字节流。下面我们将对JavaSE输入输出流的一些常用类进行源码解析及实战演示,以便于同学们加深理解。

源代码解析

InputStream类

  InputStream,首先它是一个抽象类,它定义了读取字节流的基本方法和属性,比如read()skip(long n)read(byte[] b, int off, int len)close()等,除了这些基本的读取方法外,InputStream还提供了一些其他方法,比如mark(int readlimit)reset()方法,允许在流中标记一个位置,并在需要时返回到该位置。它常用的子类有FileInputStreamByteArrayInputStream。其中,FileInputStream可以从文件中读取数据,而ByteArrayInputStream则可以从字节数组中读取数据。

源码部分截图,如下示意:

在这里插入图片描述
  需要注意的是,由于InputStream是一个抽象类,它是不能直接实例化,只能通过其子类来实现具体的输入流。

OutputStream类

  OutputStream,InputStream类一样,也是一个抽象类;它定义了写入字节流的基本方法。常用的子类有FileOutputStream和ByteArrayOutputStream,我们可以使用它的子类来读取和写入字节流。其中,FileOutputStream可以将数据写入到文件中,而ByteArrayOutputStream则可以将数据写入到字节数组中,这点我们在后面会直接演示给大家看,这里就不详细赘述了。

  对于OutputStream类,它的主要子类有,参考如下:

  • FileOutputStream:用于将数据写入文件。
  • ByteArrayOutputStream:用于将数据写入字节数组。
  • FilterOutputStream:用于添加过滤器功能,例如数据压缩或加密。
  • DataOutputStream:用于将基本数据类型写入输出流。
  • ObjectOutputStream:用于将对象写入输出流。

  接着,OutputStream类定义了以下常用方法,仅供参考:

  • write(int b):将一个字节写入输出流。
  • write(byte[] b):将一个字节数组写入输出流。
  • write(byte[] b, int off, int len):将一个指定长度的字节数组的一部分写入输出流。
  • flush():刷新输出流,确保所有缓冲的字节都被写入输出流。
  • close():关闭输出流,释放相关的资源。

BufferedInputStream类

  BufferedInputStream,它是InputStream类的装饰者类,它提供了带缓冲功能的读取方法,可以提高读取效率。BufferedInputStream内部维护了一个缓冲区,当需要读取数据时,先从缓冲区读取,如果缓冲区没有数据,则从底层流中读取新的数据。

BufferedOutputStream类

  BufferedOutputStream,它是OutputStream的装饰者类,它提供了带缓冲功能的写入方法,可以提高写入效率。BufferedOutputStream内部维护了一个缓冲区,当需要写入数据时,先将数据写入到缓冲区,当缓冲区满了或者需要刷新时,再将缓冲区的数据写入到底层流中。

应用场景案例

  接下来,我们就通过几个案例,由浅入深式的带着大家从理论过渡到实践中去,帮助大家更好的通过实践来理解理论知识点,“实践是检验真理的唯一标准!”毛爷爷曾言,接下来便开始实践部分。

文件复制

  首先,我们先通过使用输入输出流,实现一个文件的复制功能,这里大家可以先思考一下,不太能想到的也没关系,可以接着看下边的。

  实现思路大致步骤如下:首先我们可以使用FileInputStream类创建一个输入流,然后再使用FileOutputStream创建一个输出流,通过循环的方式依次读取输入流中的数据,并将其写入到输出流中,这样一个就可以实现文件的复制,是不是很简单呢?接着大家来参考下我写的代码。

package com.demo.javase.day74;import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;/*** @Author bug菌* @Date 2023-12-27 16:51*/
public class FileCopy {public static void main(String[] args) {try {FileInputStream in = new FileInputStream("source.txt");FileOutputStream out = new FileOutputStream("target.txt");byte[] buffer = new byte[1024];int length;while ((length = in.read(buffer)) != -1) {out.write(buffer, 0, length);}in.close();out.close();System.out.println("文件复制成功!");} catch (IOException e) {e.printStackTrace();}}
}

代码详细分析:

  如上代码,它是一个文件复制的程序,实现功能就是将source.txt文件内容复制到target.txt文件中,具体实现思路如下,不太懂的同学这里要着重听:

  1. 首先是引入了java.io中的相关类,用于文件的输入和输出操作(这里大家肯定都能懂)。

  2. 其次,定义一个main函数,在main方法中,通过FileInputStream来创建一个输入流对象in,并将源文件"source.txt"作为参数传递给它。

  3. 同样地,再通过FileOutputStream来创建一个输出流对象out,并将目标文件"target.txt"作为参数传递过去。

  4. 创建一个字节数组buffer,用于存储读取到的文件数据。

  5. 依次循环,使用in.read(buffer)方法来读取文件中的内容,并将读取到的字节数保存在length变量中,是不是能懂。

  6. 然后呢,我们就要通过判断length的值,如果值不为-1,表示还有数据可以读取,没读取完,则使用out.write(buffer, 0, length)方法将读取到的数据继续写入目标文件即可。

  7. 然后这里循环继续,那什么时候循环结束呢?很简单,就是判断length的值等于-1时,即文件读取完,这里直接跳过循环。

  8. 最后,记得关闭输入流和输出流(如果不关呢?其实大家也需要知道,如下我单独给大家做个拓展。)。

拓展一下:

如果不关闭输入流和输出流,可能会导致以下问题:

  1. 资源泄漏:输入流和输出流占用系统资源,如果不关闭它们,将导致资源无法被释放和复用,最终可能导致系统性能下降或崩溃。

  2. 内存泄漏:输入流和输出流需要占用一定的内存空间,如果不关闭它们,可能会导致内存泄漏问题,即占用的内存空间无法被释放,导致内存溢出。

  3. 数据丢失:如果未关闭输出流,可能会导致数据未完全写入到磁盘或目标文件中,从而导致数据丢失。

  4. 数据损坏:如果未关闭输出流和输入流,可能会导致数据在传输过程中发生错误或被破坏,导致数据的完整性受到影响。

  5. 接着,我们给个文字提示,输出"文件复制成功!"。

  6. 最后,捕获可能抛出的IOException异常,并打印异常信息。

  以上,就是该程序代码实现文件复制功能的思路了,总的来说就是使用了字节数组作为中间存储器,从输入流读取数据,然后通过输出流写入数据到目标文件中,非常的简单。

优缺点讲解

优点分析

  • 输入输出流,它提供了灵活的访问外部数据的方式,可以读取和写入各种类型的数据。
  • 输入输出流,它可以处理大数据量,通过缓冲区的使用,可以提高读写效率。
  • 输入输出流的接口和方法简单易用,对于开发人员来说学习成本较低。

缺点分析

  • 使用输入输出流操作文件需要处理异常,繁琐而且容易出错(这点实际操作中确实)。
  • 输入输出流只能处理字节流,对于字符数据需要进行字符编码的转换。

类常用方法介绍

  接着,我给同学们梳理下InputStream、BufferedInputStream等类的常用方法介绍,方便大家对比及区分方法。

InputStream类

常用方法包括:

  • int read():读取一个字节的数据。
  • int read(byte[] buffer):读取一组字节的数据,并存储到指定的字节数组中。
  • void close():关闭输入流。
  • long skip(long n):跳过n个字节的数据,并返回实际跳过的字节数。如果已经到达流的末尾,则返回0。
  • int available():返回输入流中可以读取的字节数。

  如上这些方法,可以用来从输入流中读取数据,并处理流的末尾、跳过字节、获取可读字节数等操作,具体演示我们往下看。

OutputStream类

常用方法包括:

  • write(int b):将一个字节写入输出流。
  • write(byte[] b):将一个字节数组的所有字节写入输出流。
  • write(byte[] b, int off, int len):将字节数组的一部分字节写入输出流,从偏移量off开始,写入len个字节。
  • flush():刷新输出流,将缓冲区中的数据强制写入输出流。
  • close():关闭输出流,释放与之关联的系统资源。
  • flush()和close()方法都会自动调用write()方法将缓冲区中的数据写入输出流。

BufferedInputStream类

常用方法包括:

  • public int read() throws IOException:从输入流中读取一个字节,并返回读取的字节的整数表示。如果已到达流的末尾,则返回-1。

  • public int read(byte[] b, int off, int len) throws IOException:从输入流中读取最多len个字节到字节数组b的指定偏移量off处,返回实际读取的字节数。如果已到达流的末尾,则返回-1。

  • public long skip(long n) throws IOException:从输入流中跳过n个字节的数据,并返回实际跳过的字节数。

  • public int available() throws IOException:返回可以从输入流中读取的字节数。

  • public synchronized void mark(int readlimit):在当前位置设置一个标记点。

  • public synchronized void reset() throws IOException:将流重置到上次设置的标记点。

BufferedOutputStream类

  • void write(int b):写入一个字节的数据。
  • void write(byte[] buffer):写入一组字节的数据。
  • void flush():刷新输出流,将缓冲区的数据写入到底层流中。
  • void close():关闭输出流。

测试用例

  如下,到了大家最激动人心的阶段,实战环节,检验下大家理论基础到底学习及掌握的如何?所以,这里我给大家通过几个测试用例,尽可能的使用到它们的一些常规方法,运用到实际代码中去,以辅助大家理解。

测试代码

  这里我定义了一个MyInputStream类,具体测试代码如下,在阅读我写的代码的同时,可以思考下我写的内容有何目的性,运用到了那些常规知识点,代码如下:

package com.demo.javase.day74;import java.io.IOException;
import java.io.InputStream;/*** @Author bug菌* @Date 2023-12-27 16:48*/
public class MyInputStream extends InputStream {private byte[] data = {1, 2, 3, 4, 5};private int pos = 0;@Overridepublic int read() throws IOException {if (pos < data.length) {return data[pos++];} else {return -1;}}
}

不知道大家看懂了我写的这段测试代码没,其实很简单的,无非就是模拟读取数据流。接着我来给大家详细分析一下,这段代码的完整思路

代码分析:

  我先自定义了一个的InputStream类MyInputStream,继承自java.io.InputStream。该类重写了InputStream的read()方法,实现了从一个固定的byte数组data中读取数据的功能。

  在MyInputStream类中,定义了一个私有的byte数组data,用于存储数据。还定义了一个私有的整型变量pos,用于记录读取data中的位置。

  在重写的read()方法中,首先判断pos是否小于data的长度,如果是,表示还有数据可以读取,就返回data[pos]对应的字节,并将pos++。如果pos等于或大于data的长度,表示已经读取完所有数据,返回-1。

  总之,则这个MyInputStream类功能就是用于模拟读取数据流,在每次调用read()方法都可以读取data数组中的下一个字节,仅此而已,你们也可以拓展下。

  接着,我再定义一个MyOutputStream.java,大家可以先看,从代码中理解这段代码干了件什么事,具体实现代码如下:

package com.demo.javase.day74;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;public class MyOutputStream extends OutputStream {private ByteArrayOutputStream buffer = new ByteArrayOutputStream();@Overridepublic void write(int b) throws IOException {buffer.write(b);}public byte[] getData() {return buffer.toByteArray();}
}

代码分析:

  这里我给大家也解读下,理解这段代码实现了如何功能,大家请看:

  1. 首先,在 MyOutputStream类中有一个成员变量buffer,它是一个ByteArrayOutputStream类型的对象。
  2. ByteArrayOutputStream类是一个在内存中创建字节数组缓冲区的输出流,可以将数据写入到内存中的字节数组中。
  3. MyOutputStream类重写了write方法,该方法将传入的字节写入到buffer中。
  4. getData方法返回buffer的字节数组表示形式。

  总之,这段代码定义了一个自定义的输出流类MyOutputStream,它可以将数据写入到内存中的字节数组中,并可以获取该字节数组的数据,你们学废了么。

测试3

最后,再次给大家演示下,测试输入流和输出流类的实际操作。

package com.demo.javase.day74;import java.io.IOException;/*** @Author bug菌* @Date 2023-12-27 16:49*/
public class Test {public static void main(String[] args) {try {MyInputStream in = new MyInputStream();MyOutputStream out = new MyOutputStream();int b;while ((b = in.read()) != -1) {out.write(b);}in.close();out.close();byte[] data = out.getData();for (byte d : data) {System.out.print(d + " ");}} catch (IOException e) {e.printStackTrace();}}
}

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  这段代码主要是测试自定义的输入流和输出流类。在主方法中,首先创建一个MyInputStream对象和一个MyOutputStream对象。然后通过循环,从输入流中读取字节,并将其写入到输出流中。在读取和写入的过程中,如果读取的字节等于-1,即表示输入流已经读取完毕,循环结束。接着调用输入流和输出流的close()方法关闭流。

  然后,通过调用输出流的getData()方法获取输出流中的数据,并将数据以字节数组的形式存储在data数组中。最后,通过遍历data数组,将每个字节打印输出。

  需要注意的是,在上述代码中使用了try-catch块来捕获IOException异常。如果在读写过程中发生异常,将会打印异常信息。

测试结果

  根据如上的测试用例,作者在本地进行测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加其他的测试数据或测试方法,以便于进行熟练学习以此加深知识点的理解。

在这里插入图片描述

小结

  在此,给大家做个小结,本文着重演示了并深入理解JavaSE输入输出流的原理和用法,通过源代码解析和实际应用案例的介绍,可以帮助大家更好地掌握输入输出流的知识。输入输出流在Java开发中非常重要,对于处理外部数据流动具有重要作用。

全文总结

  总而言之,JavaSE输入输出流作为Java开发中不可或缺的部分,通过对InputStream、OutputStream、BufferedInputStream和BufferedOutputStream等类的源代码解析,我们可以了解了它们的基本原理和用法。通过如上的应用场景案例讲解,我们能够更加清楚输入输出流在实际开发中的应用价值。掌握输入输出流的知识,对于Java开发人员来说是非常重要的,所以说,大家听我讲,一定可以轻松掌握。

  … …

  好啦,这期的内容就基本接近尾声啦,若你想学习更多,你可以看看专栏的导读篇《「滚雪球学Java」教程导航帖》,本专栏致力打造最硬核 Java 零基础系列学习内容,🚀打造全网精品硬核专栏,带你直线超车;欢迎大家订阅持续学习。功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

附录源码

  如上涉及所有源码均已上传同步在「Gitee」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程感兴趣的跨专业小白,都建议直接入手「滚雪球学Java」专栏;该专栏不仅免费,bug菌还郑重承诺,只要你学习此专栏,均能入门并理解Java SE,以全网最快速掌握Java语言,每章节源码均同步「Gitee」,你真值得拥有;学习就像滚雪球一样,越滚越大,带你指数级提升。

  码字不易,如果这篇文章对你有所帮助,帮忙给bugj菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。

  同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 20w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。



http://www.mrgr.cn/p/02434035

相关文章

c语言,单链表的实现----------有全代码!!!!

1.单链表的定义和结构 单链表是一种链式的数据结构&#xff0c;它用一组不连续的储存单元存反线性表中的数据元素。链表中的数据是以节点的形式来表示的&#xff0c;节点和节点之间相互连接 一般来说节点有两部分组成 1.数据域 &#xff1a;数据域用来存储各种类型的数据&…

这些Git事故灾难, 你经历过几个?

在大规模的协作中, git pull和push是远远不够使用的. 笔者介绍了自己在一线的工作中遇到了各种事故现场, 以及相应的解决方案. 快进来学习下, 也许以后用得上.前言 关于Git, 相信大家最常用的就是pull和push. 但随着协作规模的提升, 遇到的问题也会越来越多. 本篇文章并不科普一…

Ranorex无法使用spy识别element(只能识别外部container) --针对edge浏览器

1.问题 问题如标题,这是一个很严重的问题,表明我们不仅不能通过track识别元素,更重要的是spy无法识别UI元素,就会导致我们无法通过自动化脚本来控制UI元素,实现自动化测试!!! 2.解决 2.1 确保不要同时开启两个Chrome用例(chorme或者edge) 2.2 可以开启 Internet Explorer 模式(…

秋叶Stable diffusion的创世工具安装-带安装包链接

来自B站up秋葉aaaki&#xff0c;近期发布了Stable Diffusion整合包v4.7版本&#xff0c;一键在本地部署Stable Diffusion&#xff01;&#xff01; 适用于零基础想要使用AI绘画的小伙伴~本整合包支持SDXL&#xff0c;预装多种必须模型。无需安装git、python、cuda等任何内容&am…

SAP在中国的合作伙伴有哪些?

SAP作为一家全球领先的企业管理解决方案供应商,深受全球各行各业各规模企业的信赖。SAP拥有超过40年的专业经验,被称为ERP系统的“最后一道防线”。无论是面向中小型企业的Business one,还是面向中、大型集团的S/4HANA,不同规模、行业的企业都能从SAP的多样化企业管理解决方…

ubuntu安装python3.10

1. 官网下载源程序 2. 解压进入文件夹&#xff1a; ./configure --prefix/usr/local/python3/ 3. 编译安装&#xff1a; make && make install 4. 添加环境变量&#xff1a; vim ~/.bashrc PATH/usr/local/python3/bin:$PATH #保存后&#xff0c;刷新配置文件 sour…

EQ-BDS面板部署机器人

一、机器人配置教程 0.预处理 首先处理杀毒软件误报问题。在服务器上安装火绒安全当然,您也可以不选择火绒,使用其他杀毒软件,到时候给插件加上信任即可安装完成后禁用Windows Defender,详见EQ-BDS面板用户手册 1.下载然后解压压缩包 点我跳转到下载页面 这个网盘不需要开会…

探索设计模式的魅力:融合AI大模型与函数式编程、开启智能编程新纪元

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 ✨欢迎加入探索AI大模型与函数式编程模式融合之旅✨ 在编程世界的广阔疆域里&#xff0c;两大…

基于ChatGPT打造安全脚本工具流程

基于ChatGPT打造安全脚本工具流程前言 以前想要打造一款自己的工具,想法挺好实际上是难以实现,第一不懂代码的构造,只有一些工具脚本构造思路,第二总是像重复造轮子这种繁琐枯燥工作,抄抄改改搞不清楚逻辑,想打造一款符合自己工作的自定义的脚本工具难度倍增,但是随着AI…

-sh: ./example: No such file or directory

接上文的问题,咨询了隔壁部门的技术大佬后,认为是使用的交叉编译工具太旧了。因此在ARM官网重新下载工具包:下载到虚拟机后配置,完成后运行source命令使配置生效: source /etc/profile 重新编译目标代码并下载到开发板后运行:看到编译输出,已经能够找到文件了,只是缺少…

lua基本语法

Lua语法入门 初识lua vi hello.lua print("hello,lua") lua hello.lua 变量和循环 变量 循环 条件控制、函数 条件控制

RocketMQ 之 IoT 消息解析:物联网需要什么样的消息技术?

作者&#xff1a;林清山&#xff08;隆基&#xff09; 前言&#xff1a; 从初代开源消息队列崛起&#xff0c;到 PC 互联网、移动互联网爆发式发展&#xff0c;再到如今 IoT、云计算、云原生引领了新的技术趋势&#xff0c;消息中间件的发展已经走过了 30 多个年头。 目前&a…

Mybatis-plus中的分页操作

Mybatis-plus中的分页操作 1.导入Mybatis-plus依赖2.创建mybatis配置类3.参数 1.导入Mybatis-plus依赖 因为是一个springboot项目&#xff0c;其中的pom.xml文件内容如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns&q…

个人项目作品集

前言 个人博客地址: Lovi* - 博客园 (cnblogs.com) 后端代码地址:Lovi (shenqing0202) - Gitee.com 前端代码地址:Lovi-github (Lovi) Java相关项目 Servlet+jsp【热忱冰棒电子相册】 后端架构数据库表项目图片SSM+jsp【比赛抽签分组系统】 代码架构项目图片Springboot+vue…

Mac(M1)配置基于ARM64的Tensorflow

以下步骤最好先执行 conda config --remove-key channels 删除conda镜像源 pip config unset global.index-url 删除pip镜像源 然后接下来的步骤最好挂上梯子。 1.下载miniforge:从https://github.com/conda-forge/miniforge上找到arm64(Apple Silicon)版本进行下载,下一步…

2024 CVPR AIGC集合

完全外行&#xff0c;不建议参考 一、3D重建 PointAvatar: Deformable Point-based Head Avatars from Videos 对原始颜色进行解纠缠&#xff0c;得到固有反射和相关阴影。 基于可变形点云对表情、颜色、位置等信息进行建模。 总结&#xff1a;可以看作是对局部像素的分解与扩…

YOLOv8 测试 5:Linux 中 Docker 部署 YOLOv8,Python 封装 API 接口,base64 图片处理

一、前言 记录时间 [2024-4-14] 系列文章简摘&#xff1a; Docker 学习笔记&#xff08;二&#xff09;&#xff1a;在 Linux 中部署 Docker&#xff08;Centos7 下安装 docker、环境配置&#xff0c;以及镜像简单使用&#xff09; API 接口简单使用&#xff08;二&#xff09;…

EasyPoi表格导入添加校验

EasyPoi表格导入添加校验 项目添加maven依赖实体类自定义校验controller测试结果 代码地址 项目添加maven依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www…

IfcDoorPanelOperationEnum

IfcDoorPanelOperationEnum 类型定义该列举定义了各个门板的基本操作方式,如图所示。EnumeratorIllustrationSwinging DoubleActing Sliding Folding Revolving Rollingup FixedPanel UserDefinedNotDefinedFigure — Door operations 门板的打开方向由IfcDoor的局部位置决定。…