36. 【Java教程】输入输出流

本小节将会介绍基本输入输出的 Java 标准类,通过本小节的学习,你将了解到什么是输入和输入什么是流;输入输出流的应用场景,File类的使用,什么是文件,Java 提供的输入输出流相关 API 等内容。

1. 什么是输入和输出(I / O)

1.1 基本概念

输入/输出这个概念,对于计算机相关专业的同学并不陌生,在计算中,输入/输出Input / Output,缩写为 I / O)是信息处理系统(例如计算机))与外界(可能是人类或其他信息处理系统)之间的通信。输入是系统接收的信号或数据,输出是从系统发送的信号或数据。

那么在 Java 中,什么是输入和输出呢?要理解这个概念,可将 Java 平台视作一个系统。Java 平台是一个孤立的系统,系统之外的所有东西都是它的环境。系统与其环境之间的交互是一种双向对话。系统要么从其环境接收消息,要么将其消息传递给环境。当系统接收到消息时,将其称为输入,与之相反的是输出。

本小节将介绍 Java 的基本输入和输出,包括从键盘读取文本输入,将文本输出到屏幕以及从文件系统读取/写入文件。

Java 提供了两个用于 I / O 的包:较旧的java.io包(不支持符号链接)和较新的java.nio(“new io”)包,它对java.nio.file的异常处理进行了改进。

1.2 简单的 Java 输出——打印内容到屏幕

一直以来,我们都在向屏幕输出内容以验证我们编写的代码逻辑。向屏幕输出内容非常简单,可以由以下两种方式来完成:

// 打印 Hello World,不换行
System.out.print("Hello World");
// 打印 Hello Java,并换行
System.out.println("Hello Java");

1.3 简单的 Java 输入——从键盘输入

java.util包下的Scanner类可用于获取用户从键盘输入的内容,我们在Java Scanner 类这一小节已经介绍过具体使用,实例如下:

import java.util.Scanner;/*** @author colorful@TaleLin*/
public class ScannerDemo {public static void main(String[] args) {// 创建扫描器对象Scanner scanner = new Scanner(System.in);System.out.println("请输入您的姓名:");// 可以将用户输入的内容扫描为字符串String name = scanner.nextLine();// 打印输出System.out.println("你好 ".concat(name).concat(" ,欢迎来到CSDN!"));// 关闭扫描器scanner.close();}
}

运行结果:

请输入您的姓名:
Colorful
你好 Colorful ,欢迎来到CSDN!

2. 什么是流(Stream)

Java 中最基本的输入/输入是使用流来完成的。

流是代表数据源和数据目标的对象,怎么理解这句话呢?简单来说,可以读取作为数据源的流,也可以写入作为数据目标的流。Java中的流是长度不确定的有序字节序列,它是一连串流动的字符,是以先进先出的方式发送信息的通道。

3. 输入输出流的应用场景

上面我们已经了解了输入输出流的基本概念,那么它具体是做什么用的呢?

web产品的开发中,最常开发的功能就是上传文件到服务器了,这个文件的读写过程就要用到输入输出流。对于计算机中文件的读写、复制和删除等操作也都要用到输入输出流。输入输出流可以说是无处不在,下面我们将会介绍 Java 中输入输出流相关的 API

4. File 类

在 Java 中,提供了java.io.File类对文件和目录进行操作。

File 意思为文件,文件在计算机中非常重要,我们编写的 word 文档、PPT 演示文稿、运行游戏的.exe可执行文件以及我们编写的 Java 源代码等等都是文件。

4.1 实例化

要实例化File对象,需要传入一个文件或目录的路径。

File 类提供了如下 4 个构造方法:

  1. File(File parent, String child):从父抽象路径名和子路径名字符串创建新的文件实例;
  2. File(String pathName):通过将给定的路径名字符串转换为抽象路径名,创建一个新的文件实例(最常用);
  3. File(String parent, String child):从父路径名字符串和子路径名字符串创建新的文件实例;
  4. File(URI uri):通过将给定的文件: URI转换为抽象路径名,创建一个新的文件实例。

Windows系统为例,在桌面下有一个mybj目录,该目录下有一个Hello.java文件和一个空的images目录。

我们可以单击Windows的路径栏,来获取mybj目录的绝对路径。

有了目录和文件以及路径。我们分别实例化两个File对象,实例如下:

import java.io.File;public class FileDemo1 {public static void main(String[] args) {// 传入目录绝对路径File dir = new File("C:\\Users\\Colorful\\Desktop\\mybj\\images");// 传入文件绝对路径File file = new File("C:\\Users\\Colorful\\Desktop\\mybj\\Hello.java");// 打印两个File对象System.out.println(dir);System.out.println(file);}
}

我们可以直接打印File对象,File类重写了toString()方法,查看 Java 源码,toString()方法直接返回了getPath()实例方法,此方法返回构造方法传入的路径字符串:

运行结果:

C:\Users\Colorful\Desktop\mybj\images
C:\Users\Colorful\Desktop\mybj\Hello.java

上面代码中,使用\\表示Windows下的路径分隔符\LinuxMacOS下使用正斜杠/作为路径分隔符。假设是同样的目录结构,在MacOSLinux下是这样表示的:

File dir = new File("/Users/Colorful/Desktop/mybj/images");

因为Windows平台和其他平台路径分隔符不同,使用不同平台的开发者就难以保证路径分隔符的统一。

为了保证代码更好的兼容性,File类下提供了一个静态变量separator,用于表示当前平台的系统分隔符:

// 根据当前平台输出 / 获取 \
System.out.println(File.separator);

4.2 绝对路径和相对路径

在实例化File对象时,既可以传入绝对路径,也可以传入相对路径。

绝对路径是以根目录开头的完整的全路径,上面代码实例中传入的是绝对路径,我们再来看看什么是相对路径,以及如何传入相对路径。

相对路径指的是当前文件所在的路径引起的跟其它文件(或文件夹)的路径关系。听起来有点绕,我们举例来说明一下,在mybj目录下新建一个FileDemo2.java文件,此时mybj目录的文件目录树结构如下:

└── mybj├── FileDemo2.java├── Hello.java└── images

内容如下:

import java.io.File;
import java.io.IOException;public class FileDemo2 {public static void main(String[] args) throws IOException {// 传入目录相对路径File dir = new File(".\\images");File mybjDir = new File("..\\mybj");// 传入文件相对路径File file = new File(".\\Hello.java");}
}

上面代码的File构造方法中传入的就是相对路径,代码中的.表示当前目录,..表示上级目录。

Tips: 我们在实例化 File 对象时,不会产生对磁盘的操作,因此即使传入的文件或目录不存在,代码也不会抛出异常。只有当调用 File 对象下的一些方法时,才会对磁盘进行操作。

File 对象下有 3 个表示路径的实例方法:

  1. String getPath():将抽象路径名转换为路径名字符串;
  2. String getAbsolute():返回此抽象路径名的绝对路径名字符串;
  3. String getCanonicalPath():返回此抽象路径名的规范路径名字符串。

我们可以调用这 3 个方法并打印结果,实例如下:

import java.io.File;
import java.io.IOException;public class FileDemo2 {public static void main(String[] args) throws IOException {// 传入目录相对路径File imagesDir = new File(".\\images");File mybjDir = new File("..\\mybj");// 传入文件相对路径File file = new File(".\\Hello.java");System.out.println("-- imagesDir ---");System.out.println(imagesDir.getPath());System.out.println(imagesDir.getAbsolutePath());System.out.println(imagesDir.getCanonicalPath());System.out.println("-- mybjDir ---");System.out.println(mybjDir.getPath());System.out.println(mybjDir.getAbsolutePath());System.out.println(mybjDir.getCanonicalPath());System.out.println("-- file ---");System.out.println(file.getPath());System.out.println(file.getAbsolutePath());System.out.println(file.getCanonicalPath());}
}

运行结果:

-- imagesDir ---
.\images
C:\Users\Colorful\Desktop\mybj\.\images
C:\Users\Colorful\Desktop\mybj\images
-- mybjDir ---
..\mybj
C:\Users\Colorful\Desktop\mybj\..\mybj
C:\Users\Colorful\Desktop\mybj
-- file ---
.\Hello.java
C:\Users\Colorful\Desktop\mybj\.\Hello.java
C:\Users\Colorful\Desktop\mybj\Hello.java

通过运行结果可以看出,规范路径名就是把...转换为标准的绝对路径。

4.3 判断对象是文件还是目录

我们可以通过如下两个方法判断 File 对象是文件还是目录:

  1. boolean isFile():测试此抽象路径名表示的文件是否为普通文件;
  2. boolean isDirectory():测试此抽象路径名表示的文件是否为目录。

实例如下:

import java.io.File;public class FileDemo3 {public static void printResult(File file) {// 调用isFile()方法并接收布尔类型结果boolean isFile = file.isFile();String result1 = isFile ? "是已存在文件" : "不是已存在文件";// 掉用isDirectory()方法并接收布尔类型而己过boolean directory = file.isDirectory();String result2 = directory ? "是已存在目录" : "不是已存在目录";// 打印该file对象是否是已存在文件/目录的字符串结果System.out.print(file);System.out.print('\t' + result1 + '\t');System.out.println(result2);}public static void main(String[] args) {// 传入目录绝对路径File dir = new File("C:\\Users\\Colorful\\Desktop\\mybj\\images");// 传入文件绝对路径File file = new File("C:\\Users\\Colorful\\Desktop\\mybj\\test.java");FileDemo3.printResult(dir);FileDemo3.printResult(file);}
}

运行结果:

C:\Users\Colorful\Desktop\mybj\images	不是已存在文件	是已存在目录
C:\Users\Colorful\Desktop\mybj\test.java	不是已存在文件	不是已存在目录

代码中我们封装了一个静态方法printResult(),此方法打印 File 对象是否是文件/目录。值得注意的是,我们的磁盘中不存在C:\Users\Colorful\Desktop\mybj\test.java,因此无论调用isFile()方法还是isDirectory()方法,其返回结果都为false

4.4 创建和删除目录

4.4.1 创建目录

对于一个不存在的目录,我们可以使用boolean mkdir()方法创建一个目录。例如,我们想在mybj目录下创建一个codes目录,就可以使用该方法编写一段创建目录的代码。

实例如下:

import java.io.File;public class FileDemo4 {public static void main(String[] args) {// 传入目录绝对路径File dir = new File("C:\\Users\\Colorful\\Desktop\\mybj\\codes");if (!dir.exists()) {// 调用 mkdir() 方法boolean result = dir.mkdir();if (result) {System.out.println("目录创建成功");}}}
}

代码中我们调用了File对象的boolean exists()方法,此方法用于测试由此抽象路径名表示的文件或目录是否存在。当不存在时,我们才去创建目录。

运行代码前,mybj文件目录树结构如下:

└── mybj├── FileDemo2.java├── Hello.java└── images

运行结果:

目录创建成功

运行代码后,mybj目录下多了一个codes目录,树结构如下:

└── mybj├── FileDemo2.java├── Hello.java├── images└── codes

另外,File 类也提供了一个boolean mkdirs()方法,用来创建由这个抽象路径名命名的目录,包括任何必要但不存在的父目录。实际上是在递归执行mkdir()方法。

4.4.2 删除目录

如果我们想要删除刚刚创建的codes目录,可以调用boolean delete()方法,实例如下:

import java.io.File;public class FileDemo5 {public static void main(String[] args) {// 传入目录绝对路径File dir = new File("C:\\Users\\Colorful\\Desktop\\mybj\\codes");if (dir.exists()) {// 调用 delete() 方法boolean deleted = dir.delete();if (deleted) {System.out.println("删除目录成功");}}}
}

运行代码前,mybj文件目录树结构如下:

└── mybj├── FileDemo2.java├── Hello.java├── images└── codes

运行结果:

删除目录成功

运行代码后,树结构如下:

└── mybj├── FileDemo2.java├── Hello.java└── images

4.5 创建和删除文件

对于文件类型的File对象,可以通过boolean createNewFile()方法创建一个新文件,使用boolean delete()方法删除文件。其调用方法和创建/删除目录相同,此处不再赘述。

关于更多File对象的操作,可翻阅官方文档。

5. InputStream 抽象类

5.1 概述

java.io.InputStream抽象类是 Java 提供的最基本的输入流,它是所有输入流的父类。其最常用的抽象方法int read()签名如下:

public abstract int read() throws IOException;

这个方法用于读取输入流的下一个字节,返回的int如果为-1,则表示已经读取到文件末尾。

InputStream与其子类的 UML 图如下所示:

5.2 FileInputStream 实现类

我们将以最常用的FileInputStream实现类为例进行学习。其他实现类大同小异,如有需要可翻阅官方文档。

FileInputStream就是从文件流中读取数据,我们在mybj目录下新建一个文本文档Hello.txt,并输入如下内容:

Hello mybj!

读取Hello.txt文件中数据的实例代码如下:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;public class FileInputStreamDemo1 {public static void main(String[] args) throws IOException {// 实例化文件流FileInputStream fileInputStream = new FileInputStream("C:\\Users\\Colorful\\Desktop\\mybj\\Hello.txt");for (;;) {int n = fileInputStream.read();if (n == -1) {// read() 方法返回-1 则跳出循环break;}// 将n强制转换为 char 类型System.out.print((char) n);}// 关闭文件流fileInputStream.close();}
}

运行结果:

Hello mybj!

如果我们打开了一个文件并进行操作,不要忘记使用close()方法来及时关闭。这样可以让系统释放资源。

6. OutputStream 抽象类

6.1 概述

OutPutStream抽象类是与InputStream对应的最基本的输出流,它是所有输出流的父类。其最常用的抽象方法void write(int b)签名如下:

public abstract void write(int b) throws IOException;

这个方法用于写入一个字节到输出流。

OutputStream与其子类的 UML 图如下所示:

6.2 FileOutputStream 实现类

我们同样以最常用的FileOutputStream实现类为例进行学习。其他实现类大同小异,如有需要可翻阅官方文档。

FileOutputStream就是向文件流中写入数据,下面我们向mybj目录下的文本文档Hello.txt输入一段字符串HHH。完整实例如下:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;public class FileOutputStreamDemo1 {public static void main(String[] args) throws IOException {FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Colorful\\Desktop\\mybj\\Hello.txt");// 写入 3 个H字符fileOutputStream.write(72);fileOutputStream.write(72);fileOutputStream.write(72);fileOutputStream.close();}
}

运行代码后,Hello.txt后面成功写入了 3 个字符H

7. 小结

通过本小节的学习,我们知道了什么是输入输出流的概念,输入输出流经常用于上传文件到服务器的场景。想要通过 Java 操作文件和目录,要学会使用java.io.File类,InputStreamOutputStream分别是所有输入流和所有输出流的父类,FileInputStream实现了文件流的输入,FileOutputStream实现了文件流的输出。还有很多其它实现类我们没有介绍到,但使用方法大同小异,希望同学可以在用到时自行查阅文档来学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/340666.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AVL树的介绍与实现

前言 我们上一期介绍了二叉搜索树并做了实现,本期我们来继续学习另一个更优的树即AVL树! 本期内容介绍 什么是AVL树? AVL树的实现 AVL树的性能分析 在正式的介绍AVL树之前,我们先来回忆一下二叉搜索树的特点:左子树的…

OceanBase 4.3.0 列存引擎解读:OLAP场景的入门券

近期,OceanBase 发布了4.3.0版本,该版本成功实现了行存与列存存储的一体化,并同时推出了基于列存的全新向量化引擎和代价评估模型。通过强化这些能力,OceanBase V4.3.0 显著提高了处理宽表的效率,增强了在AP&#xff0…

PS插件一键轻松搞定电商产品摄影图!

在电商行业中,一张高质量的产品摄影图往往能够吸引更多潜在消费者的目光,从而增加产品的销量。然而,对于许多电商卖家和摄影师来说,后期处理产品图片却是一个既耗时又费力的工作。 最近我发现一款PS插件可以一键生成电商产品摄影…

Flutter基础 -- Dart 语言 -- 基础类型

目录 0. 配置 1. 变量 1.1 弱类型 var Object dynamic 1.2 强类型 1.3 使用场景 var 简化定义变量 查询参数定义 返回的实例对象 2. 常量 final 和 const 2.1 相同点 类型声明可以省略 初始后不能再赋值 不能和 var 同时使用 2.2 不同点 const 需要确定的值 …

【Python绘画】画笑脸简笔画

本文收录于 《一起学Python趣味编程》专栏,从零基础开始,分享一些Python编程知识,欢迎关注,谢谢! 文章目录 一、前言二、代码示例三、知识点梳理四、总结 一、前言 本文介绍如何使用Python的海龟画图工具turtle&#…

fastjson 泛型转换问题(详解)

系列文章目录 附属文章一:fastjson TypeReference 泛型类型(详解) 文章目录 系列文章目录前言一、代码演示1. 不存在泛型转换2. 存在泛型转换3. 存在泛型集合转换 二、原因分析三、解决方案1. 方案1:重新执行泛型的 json 转换2. …

23种模式之一— — — —适配器模式的详细介绍与讲解

适配器介绍与讲解 一、概念二、适配器模式结构适配器分类核心思想核心角色模式的UML类图应用场景模式优点模式缺点 实例演示图示代码演示运行结果 一、概念 适配器模式(别名:包装器) 是一种结构型设计模式 将一个类的接口转换成客户希望的另…

每日一练:利用多态思想和ArrayList集合,编写一个模拟KTV点歌系统的程序。【多态思想和ArrayList集合的综合应用】

目录 一、设计程序使用ArrayList集合,编写一个模拟KTV点歌系统的程序。参考代码歌曲类歌单类KTV类测试类运行效果 总结 最后 一、设计程序 使用ArrayList集合,编写一个模拟KTV点歌系统的程序。 要求: 输入0代表添加歌曲输入1代表将所选歌曲…

STM32高级控制定时器之输入捕获模式

目录 概述 1 输入捕获模式 1.1 原理介绍 1.2 实现步骤 1.3 发生输入捕获流程 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM调制占空比函数 3.2 应用函数库 4 测试 4.1 功能框图 4.2 运行结果 源代码下载地址&#xf…

MySQL 存储过程(一)

本篇主要介绍MySQL存储过程的相关内容 目录 一、什么是存储过程? 二、基本语法 创建存储过程 调用存储过程 查看存储过程 删除存储过程 三、变量 系统变量 用户自定义变量 局部变量 四、存储过程的参数 in out inout 一、什么是存储过程&#xff1f…

9 个步骤内快速完成 SEO 审核

SEO审计对于提高网站在搜索引擎结果中的性能和可见性至关重要。这种系统评估涉及仔细检查各种元素,从关键字和页面优化到网站结构和页面速度等技术方面。在本指南中,我们将概述执行全面 SEO 检查器的 12 个基本步骤,帮助您确定优势、劣势和改…

基于小波区间相关的信号降噪方法(MATLAB 2021B)

在我们处理信号过程中最重要的任务就是找到信号隐藏的规律和信号的特征。常用的傅里叶分析法只能用于在时间域或者频率域上分析信号,而通常的数据会在时间域和频率域均有特征。而小波分析是继傅里叶分析之后的一大突破性创新,也是近年来在学术界非常热门…

小熊家务帮day5-day7 客户管理模块1 (小程序认证,手机验证码认证,账号密码认证,修改密码,找回密码等)

客户管理模块 1.认证模块1.1 认证方式介绍1.1.1 小程序认证1.1.2 手机验证码登录1.1.3 账号密码认证 1.2 小程序认证1.2.1 小程序申请1.2.2 创建客户后端工程jzo2o-customer1.2.3 开发部署前端1.2.4 小程序认证流程1.2.4.1 customer小程序认证接口设计Controller层Service层调用…

使用import语句导入模块

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 创建模块后,就可以在其他程序中使用该模块了。要使用模块需要先以模块的形式加载模块中的代码,这可以使用import语句实现。im…

react、vue动态form表单

需求在日常开发中反复写form 是一种低效的开发效率,布局而且还不同这就需要我们对其封装 为了简单明了看懂代码,我这里没有组件,都放在一起,简单抽离相信作为大佬的你,可以自己完成, 一、首先我们做动态f…

外包小菜鸡花了几个w报的课立志进大厂

不知不觉已经毕业了好几年,但是感觉还是自己的年龄增长了而已,对应的技术却没学到,最后一咬牙报了图灵的架构VIP班,不得不说,诸葛老师讲的是真的好呀,大家可以看看他的公开课,希望学完下面这些视…

JVMの内存泄漏内存溢出案例分析

1、内存溢出 内存溢出指的是程序在申请内存时,没有足够的内存可供分配,导致无法满足程序的内存需求,常见的内存溢出情况包括堆内存溢出(Heap Overflow)和栈溢出(Stack Overflow): …

《数字图像处理-OpenCV/Python》第15章:图像分割

《数字图像处理-OpenCV/Python》第15章:图像分割 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第15章:图像分割 图像分割是由图像处理到图像分析的关键步骤…

spark的简单学习二

一 spark sql基础 1.1 Dataframe 1.介绍: DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表 格,除了数据以外,还掌握数据的结构信息,即schema。同时,与Hive类似,DataFrame也支 持…