本文首发自「慕课网」,想了解更多IT干货内容,程序员圈内热闻,欢迎关注!

作者| 慕课网精英讲师 ColorfulC

本篇文章将会介绍基本输入输出的 Java 标准类,你将了解到什么是输入和输入,什么是流;输入输出流的应用场景,File类的使用,什么是文件,Java 提供的输入输出流相关 API 等内容。1. 什么是输入和输出(I / O)1.1 基本概念输入/输出这个概念,对于计算机相关专业的同学并不陌生,在计算中,输入/输出(Input / Output,缩写为 I / O)是信息处理系统(例如计算机))与外界(可能是人类或其他信息处理系统)之间的通信。输入是系统接收的信号或数据,输出是从系统发送的信号或数据。那么在 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");
代码块12// 打印 Hello Java,并换行
System.out.println("Hello Java");
代码块121.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(" ,欢迎来到慕课网!"));
    // 关闭扫描器
    scanner.close();
}

}
代码块123456789101112131415161718运行结果:请输入您的姓名:
Colorful
你好 Colorful ,欢迎来到慕课网!
代码块1232. 什么是流(Stream)Java 中最基本的输入/输入是使用流来完成的。流是代表数据源和数据目标的对象,怎么理解这句话呢?简单来说,可以读取作为数据源的流,也可以写入作为数据目标的流。Java中的流是长度不确定的有序字节序列,它是一连串流动的字符,是以先进先出的方式发送信息的通道。3. 输入输出流的应用场景上面我们已经了解了输入输出流的基本概念,那么它具体是做什么用的呢?在web产品的开发中,最常开发的功能就是上传文件到服务器了,这个文件的读写过程就要用到输入输出流。对于计算机中文件的读写、复制和删除等操作也都要用到输入输出流。输入输出流可以说是无处不在,下面我们将会介绍 Java 中输入输出流相关的 API。4. File 类在 Java 中,提供了java.io.File类对文件和目录进行操作。File 意思为文件,文件在计算机中非常重要,我们编写的 word 文档、PPT 演示文稿、运行游戏的.exe可执行文件以及我们编写的 Java 源代码等等都是文件。4.1 实例化要实例化File对象,需要传入一个文件或目录的路径。File 类提供了如下 4 个构造方法:File(File parent, String child):从父抽象路径名和子路径名字符串创建新的文件实例;File(String pathName):通过将给定的路径名字符串转换为抽象路径名,创建一个新的文件实例(最常用);File(String parent, String child):从父路径名字符串和子路径名字符串创建新的文件实例;File(URI uri):通过将给定的文件: URI转换为抽象路径名,创建一个新的文件实例。以Windows系统为例,在桌面下有一个imooc目录,该目录下有一个Hello.java文件和一个空的images目录,截图如下:
图片
我们可以单击Windows的路径栏,来获取imooc目录的绝对路径:
图片
有了目录和文件以及路径。我们分别实例化两个File对象,实例如下:import java.io.File;

public class FileDemo1 {

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

}
代码块12345678910111213我们可以直接打印File对象,File类重写了toString()方法,查看 Java 源码,toString()方法直接返回了getPath()实例方法,此方法返回构造方法传入的路径字符串:
图片
运行结果:C:\Users\Colorful\Desktop\imooc\images
C:\Users\Colorful\Desktop\imooc\Hello.java
代码块12上面代码中,使用\表示Windows下的路径分隔符\,Linux和MacOS下使用正斜杠/作为路径分隔符。假设是同样的目录结构,在MacOS和Linux下是这样表示的:File dir = new File("/Users/Colorful/Desktop/imooc/images");
代码块1因为Windows平台和其他平台路径分隔符不同,使用不同平台的开发者就难以保证路径分隔符的统一。为了保证代码更好的兼容性,File类下提供了一个静态变量separator,用于表示当前平台的系统分隔符:// 根据当前平台输出 / 获取 \
System.out.println(File.separator);
代码块124.2 绝对路径和相对路径在实例化File对象时,既可以传入绝对路径,也可以传入相对路径。绝对路径是以根目录开头的完整的全路径,上面代码实例中传入的是绝对路径,我们再来看看什么是相对路径,以及如何传入相对路径。相对路径指的是当前文件所在的路径引起的跟其它文件(或文件夹)的路径关系。听起来有点绕,我们举例来说明一下,在imooc目录下新建一个FileDemo2.java文件,此时imooc目录的文件目录树结构如下:└── imoooc

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

代码块1234内容如下: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 imoocDir = new File("..\\imooc");
    // 传入文件相对路径
    File file = new File(".\\Hello.java");
}

}
代码块123456789101112上面代码的File构造方法中传入的就是相对路径,代码中的.表示当前目录,..表示上级目录。Tips: 我们在实例化 File 对象时,不会产生对磁盘的操作,因此即使传入的文件或目录不存在,代码也不会抛出异常。只有当调用 File 对象下的一些方法时,才会对磁盘进行操作。File 对象下有 3 个表示路径的实例方法:String getPath():将抽象路径名转换为路径名字符串;String getAbsolute():返回此抽象路径名的绝对路径名字符串;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 imoocDir = new File("..\\imooc");
    // 传入文件相对路径
    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("-- imoocDir ---");
    System.out.println(imoocDir.getPath());
    System.out.println(imoocDir.getAbsolutePath());
    System.out.println(imoocDir.getCanonicalPath());

    System.out.println("-- file ---");
    System.out.println(file.getPath());
    System.out.println(file.getAbsolutePath());
    System.out.println(file.getCanonicalPath());
}

}
代码块123456789101112131415161718192021222324252627运行结果:-- imagesDir ---
.\images
C:\Users\Colorful\Desktop\imooc.\images
C:\Users\Colorful\Desktop\imooc\images
-- imoocDir ---
..\imooc
C:\Users\Colorful\Desktop\imooc..\imooc
C:\Users\Colorful\Desktop\imooc
-- file ---
.\Hello.java
C:\Users\Colorful\Desktop\imooc.\Hello.java
C:\Users\Colorful\Desktop\imooc\Hello.java
代码块123456789101112通过运行结果可以看出,规范路径名就是把.和..转换为标准的绝对路径。4.3 判断对象是文件还是目录我们可以通过如下两个方法判断 File 对象是文件还是目录:boolean isFile():测试此抽象路径名表示的文件是否为普通文件;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\\imooc\\images");
    // 传入文件绝对路径
    File file = new File("C:\\Users\\Colorful\\Desktop\\imooc\\test.java");
    FileDemo3.printResult(dir);
    FileDemo3.printResult(file);
}

}
代码块1234567891011121314151617181920212223242526运行结果:C:\Users\Colorful\Desktop\imooc\images 不是已存在文件 是已存在目录
C:\Users\Colorful\Desktop\imooc\test.java 不是已存在文件 不是已存在目录
代码块12代码中我们封装了一个静态方法printResult(),此方法打印 File 对象是否是文件/目录。值得注意的是,我们的磁盘中不存在C:\Users\Colorful\Desktop\imooc\test.java,因此无论调用isFile()方法还是isDirectory()方法,其返回结果都为false。4.4 创建和删除目录4.4.1 创建目录对于一个不存在的目录,我们可以使用boolean mkdir()方法创建一个目录。例如,我们想在imooc目录下创建一个codes目录,就可以使用该方法编写一段创建目录的代码。实例如下:import java.io.File;

public class FileDemo4 {

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

}
代码块12345678910111213141516代码中我们调用了File对象的boolean exists()方法,此方法用于测试由此抽象路径名表示的文件或目录是否存在。当不存在时,我们才去创建目录。运行代码前,imooc文件目录树结构如下:└── imoooc

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

代码块1234运行结果:目录创建成功
代码块1运行代码后,imooc目录下多了一个codes目录,树结构如下:└── imoooc

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

代码块12345另外,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\\imooc\\codes");
    if (dir.exists()) {
        // 调用 delete() 方法
        boolean deleted = dir.delete();
        if (deleted) {
            System.out.println("删除目录成功");
        }
    }
}

}
代码块123456789101112131415运行代码前,imooc文件目录树结构如下:└── imoooc

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

代码块12345运行结果:删除目录成功
代码块1运行代码后,树结构如下:└── imoooc

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

代码块12344.5 创建和删除文件对于文件类型的File对象,可以通过boolean createNewFile()方法创建一个新文件,使用boolean delete()方法删除文件。其调用方法和创建/删除目录相同,此处不再赘述。关于更多File对象的操作,可翻阅官方文档。5. InputStream 抽象类5.1 概述java.io.InputStream抽象类是 Java 提供的最基本的输入流,它是所有输入流的父类。其最常用的抽象方法int read()签名如下:public abstract int read() throws IOException;
代码块1这个方法用于读取输入流的下一个字节,返回的int如果为-1,则表示已经读取到文件末尾。InputStream与其子类的 UML 图如下所示:
图片
5.2 FileInputStream 实现类我们将以最常用的FileInputStream实现类为例进行学习。其他实现类大同小异,如有需要可翻阅官方文档。FileInputStream就是从文件流中读取数据,我们在imooc目录下新建一个文本文档Hello.txt,并输入如下内容:
图片
读取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\\imooc\\Hello.txt");
    for (;;) {
        int n = fileInputStream.read();
        if (n == -1) {
            // read() 方法返回-1 则跳出循环
            break;
        }
        // 将n强制转换为 char 类型
        System.out.print((char) n);
    }
    // 关闭文件流
    fileInputStream.close();
}

}
代码块12345678910111213141516171819202122运行结果:Hello imooc!
代码块1如果我们打开了一个文件并进行操作,不要忘记使用close()方法来及时关闭。这样可以让系统释放资源。6. OutputStream 抽象类6.1 概述OutPutStream抽象类是与InputStream对应的最基本的输出流,它是所有输出流的父类。其最常用的抽象方法void write(int b)签名如下:public abstract void write(int b) throws IOException;
代码块1这个方法用于写入一个字节到输出流。OutputStream与其子类的 UML 图如下所示:
图片
6.2 FileOutputStream 实现类我们同样以最常用的FileOutputStream实现类为例进行学习。其他实现类大同小异,如有需要可翻阅官方文档。FileOutputStream就是向文件流中写入数据,下面我们向imooc目录下的文本文档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\\imooc\\Hello.txt");
    // 写入 3 个H字符
    fileOutputStream.write(72);
    fileOutputStream.write(72);
    fileOutputStream.write(72);
    fileOutputStream.close();
}

}
代码块1234567891011121314运行代码后,Hello.txt后面成功写入了 3 个字符H。7. 小结通过本篇文章,我们知道了什么是输入输出流的概念,输入输出流经常用于上传文件到服务器的场景。想要通过 Java 操作文件和目录,要学会使用java.io.File类,InputStream和OutputStream分别是所有输入流和所有输出流的父类,FileInputStream实现了文件流的输入,FileOutputStream实现了文件流的输出。还有很多其它实现类我们没有介绍到,但使用方法大同小异,希望同学可以在用到时自行查阅文档来学习。

欢迎关注「慕课网」,发现更多IT圈优质内容,分享干货知识,帮助你成为更好的程序员!


慕课网
29 声望8 粉丝

慕课网,国内深受欢迎的互联网IT技能学习网站,IT教育行业的造梦者,也是前沿技术内容的创造者和传播者!在慕课网,只学有用的。