Java中I/O输入输出的深入讲解

目录
  • 前言
  • 一、流概述
  • 二、输入/输出流
    • 1、输入流
    • 2、输出流
  • 三、File类
    • 1、文件的创建与删除
      • 1、File(String pathname)
      • 2、File(String parent,String child)
      • 3、File(File f,String child)
    • 2、获取文件信息
  • 四、文件输入/输出流
    • 1、FillInputStream与FileOutputStream类
    • 2、FileReader和FileWriter类
  • 五、带缓存的输入/输出流
    • 1、BufferedInputStream与BufferedOutputStream类
    • 2、BufferedReader与BufferedWriter类
  • 六、数据输入/输出流
  • 七、ZIP压缩输入/输出流
    • 1、压缩文件
  • 补充:获取目录下的所有目录和文件
  • 总结

前言

在变量、数组和对象中存储的数据是暂时存在的,程序结束后它们就会丢失。为了能够永久地保存创建的数据,需要将其保存在磁盘文件中,这样就可以在其他程序中使用它们。Java的I/O技术可以将数据保存到文本文件、二进制文件甚至是ZIP压缩文件中,已达到永久性保存数据的要求。掌握I/O处理技术能够提高对数据的处理能力。

一、流概述

流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/O(Input/Output,输入/输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然I/O流通常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口等。
Java由数据流处理输入/输出模式,程序从指向源的输入流中读取源中的数据,源可以是文件、网络、压缩包或其他数据源。
输出流的指向是数据要到达的目的地,程序通过向输出流中写入数据把信息传递到目的地。

二、输入/输出流

Java语言定义了许多类专门负责各种方式的输入/输出,这类类都被放在java.io包中。其中,所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。

1、输入流

InputStream类是字节输入流的抽象类,是所有字节输入流的父类。InputStream类的具体层次结构如下所示。
该类中所有方法遇到错误时都会引发IOException异常。下面是对该类中的一些方法的简要说明。

read()方法:从输入流中读取数据的下一个字节。返回0-255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回值为-1。
read(byte[] b):从输入流中读入一定长度的字节,并以整数的形式返回字节数。
mark(int readlimit)方法:在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数。
reset()方法:将输入指针返回到当前所做的标记处。
skip(long n)方法:跳过输入流上的n个字节并返回实际跳过的字节数。
markSupported()方法:如果当前流支持mark()/reset()操作就返回true。
close方法:关闭此输入流并释放与该流关联的所有系统资源。

Java中的字符是Unicode编码,是双字节的。InputStream是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类Reader,但Reader类并不是InputStream类的替换者,只是处理字符串时简化了编程。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。

Reader类中的方法与InputStream类中的方法类似,读者在需要时可查看JDK文档。

2、输出流

OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。
OutputStream类中的所有方法均返回void,在遇到错误时会引发IoException异常。下面对OutputStream类中的方法作简单的介绍。

write(int b)方法:将指定的字节写入此输出流。
write(byte[] b)方法:将b个字节从指定的byte数组写入此输出流。
write(byte[] b,int off, int len)方法:将指定byte数组中从偏移量off开始的len个字节写入此输出流。
flush()方法:彻底完成输出并清空缓存区。
close()方法:关闭输出流。

三、File类

File类是java.io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建、删除、重命名文件等操作。File类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,文件也是数据流最常用的数据媒体。

1、文件的创建与删除

可以使用File类创建一个文件对象。通常使用以下3种构造方法来创建文件对象。

1、File(String pathname)

该构造方法通过将给定路径名字符串转换为抽象路径名来创建一个新File实例。

语法如下:

new File(String pathname);

其中,pathname指定路径名称(包含文件名)。例如:

File file = new File(“d:/1.txt”);

2、File(String parent,String child)

该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象。

语法如下:

new File(String parent,String child);

3、File(File f,String child)

该构造方法根据Parent抽象路径名和child路径名字符串创建一个新的File实例。

语法如下:

new File(File f,String child);

2、获取文件信息

File类提供了很多方法用于获取一些文件本身的信息。如下表

方法| 返回值 | 说明
-------- | -----
getName() | String| 获取文件的名称
canReda()| boolean |判断文件是否为可读的
canWrite()| boolean | 判断文件是否可被写入
exits()|boolean | 判断文件是否存在
length()|long | 获取文件的长度(以字节为单位)
getAbsolutePath() | String | 获取文件的绝对路径
getParent() | String | 获取文件的父路径
isFile() | boolean | 判断文件是否存在
isDirectory() | boolean | 判断文件是否为一个目录
isHidden() | boolean | 判断文件是否为隐藏文件
lastModified() | long | 获取文件最后修改时间

四、文件输入/输出流

程序运行期间,大部分数据都在内存中进行操作,当程序结束或关闭时,这些数据将消失。如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。

1、FillInputStream与FileOutputStream类

FileInputStream类与FileOUtputStream类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputString类,该类继承自InputString类。FileOutputStream类与FileInputStream类对应,提供了基本的文件写入能力。FileOutputStream类是OutputStream类的子类。
FileInputStream类常用的构造方法如下:

FileInputStream(String name)
FileInputStream(File file)

2、FileReader和FileWriter类

使用FileOutputStream类向文件中写入数据与使用FileInputStream类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉子在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流Reader或Writer类即可避免这种现象。

FileReader和FileWriter字符流对应了FileInputStream和FileOutputStream类。FileReader流顺序地读取文件,只要不关闭流,每次调用read()方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。

五、带缓存的输入/输出流

缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区。有了缓存区,使得在流上执行skip()、mark()和reset()方法都成为可能。

1、BufferedInputStream与BufferedOutputStream类

BufferedInputStream类可以对所有InputStream类进行带缓冲区的包装以达到性能的优化。BufferedInputStream类有两个构造方法:

BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)

第一种构造方法创建一个有32个字节的缓存区,第二种构造方法以指定的大小来创建缓存区。

2、BufferedReader与BufferedWriter类

BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。

六、数据输入/输出流

数据输入/输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。

七、ZIP压缩输入/输出流

ZIP压缩管理文件(ZIP archive)是一种十分典型的文件压缩形式,使用它可以节省存储空间。关于ZIP压缩的I/O实现,在Java的内置类中提供了非常好用的相关类,所以其实现方式非常简单。本节将介绍使用java.util.zip包中的ZipOutputStream与ZipInputStream类来实现文件的压缩/解压缩。如要从ZIP压缩管理文件内读取某个文件,要先找到对应文件的“目录进入点”(从它可知该文件在ZIP文件内的位置),才能读取这个文件的内容。如果要将文件内容写入ZIP文件内,必须先写入对应于该文件的“目录进入点”,并且把要写入文件内容的位置移到此进入点所指的位置,然后再写入文件内容。

Java实现了I/O数据流与网络数据流的单一接口,因此数据的压缩、网络传输和解压缩的实现比较容易。ZipEntry类产生的对象,是用来代表一个ZIP压缩文件内的进入点(entry)。ZipInputStream用来写出ZIP压缩格式的文件,所支持的包括已压缩及未压缩的进入点(entry)。

ZipOutputStream类用来写出ZIp压缩格式的文件,而且所支持的包括已压缩及未压缩的进入点(entry)。下面介绍利用ZipEntry、

ZipInputStream和ZipOutputStream3个Java类实现ZIP数据压缩方式的编程方法。

1、压缩文件

利用ZipOutputStream类对象,可将文件压缩为.zip文件。ZipOutputStream类的构造方法如下:

ZipOutputStram(OutputStream out);

ZipOutputStream类的常用方法如表所示:

方法 返回值 说明
putNextEntry(ZipEntry e) void 开始写一个新的ZipEntry,并将流内的位置移至此entry所指数据的开头
write(byte[] b,int off,int len) void 将字节数组写入当前ZIP条目数据
finish() void 完成写入ZIP输出流的内容,无须关闭它所配合的OutputStream
setComment(String comment) void 可设置此ZIP文件的注释文字

2、解压缩ZIP文件

ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)。ZipInputStream类的构造方法如下:

ZipInputStream(InputStream in)

ZipInputStream类的常用方法如下表所示:

方法 返回值 说明
read(byte[] b, int off , int len) int 读取目标b数组内off偏移量的位置,长度是len字节
available() int 判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1
closeEntry() void 关闭当前ZIP条目并定位流以读取下一个条目
skip(long n) long 跳过当前ZIP条目中指定的字节数
getNextEntry() ZipEntry 读取下一个ZipEntry,并将流内的位置移至该entry所指数据的开头
createZipEntry(String name) ZipEntry 以指定的name参数新建一个ZipEntry对象

补充:获取目录下的所有目录和文件

示例:假设目录“D:\TestDir1”下有两个文件夹(dir1 和 dir2)和一个文件 file1.txt 。

File[] listFiles()方法:获取该目录下的所有子目录和文件,返回File类数组。

import java.io.File;

/**
 * 获取目录下的所有目录和文件
 * @author pan_junbiao
 **/
public class DirFileTest
{
    public static void main(String[] args)
    {
        File file = new File("D:\\TestDir1");

        //判断目录是否存在
        if (!file.exists())
        {
            System.out.println("目录不存在");
            return;
        }

        //获取文件数组
        File[] fileList = file.listFiles();
        for (int i = 0; i < fileList.length; i++)
        {
            //判断是否为目录
            if (fileList[i].isDirectory())
            {
                System.out.println("目录:" + fileList[i].getName());
            }
            else
            {
                System.out.println("文件:" + fileList[i].getName());
            }
        }
    }
}

执行结果:

总结

这里的相关内容还没有整理完毕,文章后面持续更新,建议收藏。

文章中涉及到的命令大家一定要像我一样每个都敲几遍,只有在敲的过程中才能发现自己对命令是否真正的掌握了。

到此这篇关于Java中I/O输入输出的文章就介绍到这了,更多相关Java I/O输入输出内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅析Java.IO输入输出流 过滤流 buffer流和data流

    java.io使用了适配器模式装饰模式等设计模式来解决字符流的套接和输入输出问题. 字节流只能一次处理一个字节,为了更方便的操作数据,便加入了套接流. 问题引入: 缓冲流为什么比普通的文件字节流效率高? 不带缓冲的操作,每读一个字节就要写入一个字节. 由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低. 带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里. 等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多! 这就是两者的区

  • Java IO之字节输入输出流详解

    目录 1.字节输出流:OutputStream 2.字节输入流:InputStream 3.用字节流完成文件的复制 总结 那么这篇博客我们讲的是字节输入输出流:InputStream.OutputSteam(下图红色长方形框内),红色椭圆框内是其典型实现(FileInputSteam.FileOutStream) 1.字节输出流:OutputStream public abstract class OutputStream extends Object implements Closeable,

  • JavaI/O深入学习之输入和输出

    前言 编程语言的I/O类库中常使用流这个抽象概念,它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象."流"屏蔽了实际的I/O设备中处理数据的细节. 在文章:<<Java I/O深入学习之File和RandomAccessFile>>中,我们讲到RandomAccessFile可以写入和读取文件,具备I/O功能,但是其只能针对文件,而I/O还涉及到很多其他场景比如网络.读取内存中的字符串等,所以Java类库中提供了一系列的类库来对其进行支持,也

  • Java中I/O输入输出的深入讲解

    目录 前言 一.流概述 二.输入/输出流 1.输入流 2.输出流 三.File类 1.文件的创建与删除 1.File(String pathname) 2.File(String parent,String child) 3.File(File f,String child) 2.获取文件信息 四.文件输入/输出流 1.FillInputStream与FileOutputStream类 2.FileReader和FileWriter类 五.带缓存的输入/输出流 1.BufferedInputSt

  • java 中动态代理机制的实例讲解

    java 中动态代理机制的实例讲解 在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制,所以本篇随笔就是对java的动态机制进行一个回顾. 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)

  • 基于Java中UDP的广播形式(实例讲解)

    UDP---用户数据报协议,是一个简单的面向数据报的运输层协议.UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地 ,也不能保证数据包到达的顺序.由于UDP在传输数据报前不用在客户和服务器之间建立一个连接,且没有超时重发等机制,故而传输速度很快. 在Java中UDP的实现: * UDP: * 客户端: * 1.创建用于UDP通信的socket对象---DatagramSocket(用于UDP数据的发送和接收)---数据报套接字 * 2.准备数据,封装包

  • java中list的用法和实例讲解

    目录: list中添加,获取,删除元素: list中是否包含某个元素: list中根据索引将元素数值改变(替换): list中查看(判断)元素的索引: 根据元素索引位置进行的判断: 利用list中索引位置重新生成一个新的list(截取集合): 对比两个list中的所有元素: 判断list是否为空: 返回Iterator集合对象: 将集合转换为字符串: 将集合转换为数组: 集合类型转换: 去重复: 备注:内容中代码具有关联性. 1.list中添加,获取,删除元素: 添加方法是:.add(e): 获

  • java中使用map排序的实例讲解

    对列表进行排序也是我们经常遇到的问题,这里缩小一下范围,使用map来对列表排序.相信大家都有过TreeMap排序的经历,不过Map.Entry能按值进行排序,在用法上略胜一筹.下面我们会对这两种map排序的方法分别进行介绍,着重讲解Map.Entry排序的方法. 1.Map.Entry方法 把Map.Entry放进list,再用Comparator对list进行排序 List list = new ArrayList(map.entrySet()); Collections.sort(list,

  • Java中wait与sleep的区别讲解(wait有参及无参区别)

    目录 1. wait() 与wait( long timeout ) 区别 2. wait(0) 与 sleep(0)区别 3. wait 和sleep 释放代码 4. wait 与 sleep 区别 相同点: 不同点: 1. wait() 与wait( long timeout ) 区别 public class WaitDemo4 { public static void main(String[] args) { Object lock = new Object(); Object loc

  • Java中序列化和反序列化的完整讲解

    目录 一.序列化 二.序列化和反序列化的应用 三.序列化和反序列化地实现 3.1.JDK类库提供的序列化API 3.2.序列化要求 3.3.实现java序列化和反序列化的三种方法 四.CustomerForm 类序列化和反序列化演示 五.Externalizable接口实现序列化与反序列化 5.1.Externalizable 的不同点 5.2.CustomerForm 实现类 Externalizable 5.3.Externalizable 实现序列化和反序列化 总结 一.序列化 1.1.S

  • Java中的常用输入输出语句的操作代码

    一.概述 输入输出可以说是计算机的基本功能.作为一种语言体系,java中主要按照流(stream)的模式来实现.其中数据的流向是按照计算机的方向确定的,流入计算机的数据流叫做输入流(inputStream),由计算机发出的数据流叫做输出流(outputStream). Java语言体系中,对数据流的主要操作都封装在java.io包中,通过java.io包中的类可以实现计算机对数据的输入.输出操作.在编写输入.输出操作代码时,需要用import语句将java.io包导入到应用程序所在的类中,才可以

  • Java中控制流程语句的深入讲解

    目录 前言 if-then if-then-else switch 使用 String while do-while for break continue return 总结 前言 流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模块. 控制语句分为三类:顺序.选择和循环. 顺序结构:代表"先执行a,再执行b"的逻辑. 选择结构:代表"如果-,则-"的逻辑. 循环结构:代表"如果-,则重复执行-"的逻辑.

  • 简单讲解java中throws与throw的区别

    Java中throws和throw的区别讲解 当然,你需要明白异常在Java中式以一个对象来看待. 并且所有系统定义的编译和运行异常都可以由系统自动抛出,称为标准异常,但是一般情况下Java 强烈地要求应用程序进行完整的异常处理,给用户友好的提示,或者修正后使程序继续执行. 直接进入正题哈: 1.用户程序自定义的异常和应用程序特定的异常,必须借助于 throws 和 throw 语句来定义抛出异常. 1.1   throw是语句抛出一个异常. 语法:throw (异常对象);         

随机推荐