导图社区 IO(输入输出)
流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/O(Input/Output,输入/输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然I/O流通常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口等。Java由数据流处理输入/输出模式,程序从指向源的输入流中读取源中的数据,源可以是文件、网络、压缩包或其他数据源。 输出流的指向是数据要到达的目的地,程序通过向输出流中写入数据把信息传递到目的地,输出流的目标可以是文件、网络、
编辑于2022-12-31 16:18:23 贵州微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
社区模板帮助中心,点此进入>>
微信小程序开发知识整理,系统地介绍了微信小程序开发的基础知识,帮助开发者更好地理解和掌握小程序开发的要点和流程。
SpringFramework技术的介绍,SpringFramework,通常简称为Spring,是一个开源的企业级Java应用程序框架,由Rod Johnson创建,并于2004年首次发布。Spring Framework的主要目标是简化企业级Java开发,提高开发效率和应用程序的可维护性。
Maven的特性以及使用部署方法,Maven介绍:Maven是一款为Java项目构建管理、依赖管理的工具(软件),使用Maven可以自动化构建、测试、打包和发布项目,大大提高了开发效率和质量。
I/O(输入/输出)
在变量、数组和对象中存储的数据是暂时存在的,程序结束后它们就会丢失。想要永久地存储程序创建的数据,需要将其保存在磁盘文件中,这样就可以在其他程序中使用它们。Java的I/O技术可以将数据保存到文本文件、二进制文件甚至是ZIP压缩文件中,以达到永久性保存数据的要求。掌握I/O处理技术能够提高对数据的处理能力。
一、 流概述
流是一组有序的数据序列,根据操作的类型,可分为输入流和输出流两种。I/O(Input/Output,输入/输出)流提供了一条通道程序,可以使用这条通道把源中的字节序列送到目的地。虽然I/O流通常与磁盘文件存取有关,但是程序的源和目的地也可以是键盘、鼠标、内存或显示器窗口等。Java由数据流处理输入/输出模式,程序从指向源的输入流中读取源中的数据,源可以是文件、网络、压缩包或其他数据源。 输出流的指向是数据要到达的目的地,程序通过向输出流中写入数据把信息传递到目的地,输出流的目标可以是文件、网络、压缩包、控制台和其他数据输出目标。
二、 输入/输出流
Java语言定义了许多类专门负责各种方式的输入/输出,这些类都被放在java.io包中。其中,所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。
1. InputStream类是字节输入流的抽象类,是所有字节输入流的父类。InputStream类的具体层次结构如图所示。
并不是所有的InputStream类的子类都支持InputStream中定义的所有方法,如skip()、mark()、reset()等方法只对某些子类有用。
该类中的所有方法遇到错误时都会引发IOException异常。下面是该类中的一些方法
1||| read():从输入流中读取数据的下一个字节。返回0~255范围内的int字节值。如果因为已经到达流末尾而没有可用的字节,则返回-1
2||| read(byte[ ] b):从输入流中读入一定长度的字节,并以整数的形式返回字节数
3||| mark(int readlimit):在输入流的当前位置放置一个标记,readlimit参数告知此输入流在标记位置失效之前允许读取的字节数
4||| reset():将输入指针返回到当前所做的标记处
5||| skip(long n):跳过输入流上的n个字节并返回实际跳过的字节数
6||| markSupported():如果当前流支持mark()/reset()操作就返回true
7||| close():关闭此输入流并释放与该流关联的所有系统资源
Java中的字符是Unicode编码,是双字节的。InputStream是用来处理字节的,并不适合处理字符文本。Java为字符文本的输入专门提供了一套单独的类Reader,但Reader类并不是InputStream类的替换者,只是在处理字符串时简化了编程。Reader类是字符输入流的抽象类,所有字符输入流的实现都是它的子类。Reader类的具体层次结构如右图所示。
2. OutputStream类是字节输出流的抽象类,此抽象类是表示输出字节流的所有类的超类。OutputStream类的具体层次如图所示。
OutStream类中的所有方法均返回void,在遇到错误时会引发IOException异常,下面对该类中的方法作简单介绍
1||| write(int b):将指定的字节写入此输出流
2||| write(byte【】b):将b个字节从指定的byte数组写入此输出流
3||| write(byte【】b,int off,int len):将指定byte数组从偏移量off开始的len个字节写入此输出流
4||| flush():彻底完成输出并清空缓存区
5||| close():关闭输出流
Writer类是字符输出流的抽象类,所有字符输出类的实现都是它的子类。Writer类的层次结构如图所示。
三、 File类
File类是java.io包中唯一代表磁盘文件本身的对象。File类定义了一些与平台无关的方法来操作文件,可以通过调用File类中的方法,实现创建、删除、重命名文件等操作。File类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件读写权限等。数据流可以将数据写入到文件中,文件也是数据流最常用的数据媒体
1. 文件的创建与删除:可以使用File类创建一个文件对象。通常使用以下3种构造方法来创建文件对象
1||| File(String pathname):该构造方法通过给定路径名字符串转换为抽象路径名来创建一个新的File实例。语法如下: new File(String pathname) 其中,path指路径名称(包含文件名),例如:File file=new File("d:/1.txt");
2||| File(String parent,String child):该构造方法根据定义的父路径和子路径字符串(包含文件名)创建一个新的File对象。语法如下:new File(String parent,String child)
parent:父路径字符串例如:D:/doc
child:子路径字符串,例如:letter.txt
3||| File(File f,String child):该构造方法根据parent抽象路径名称和child路径名字符串创建一个新的File实例
f:父路径对象,例如:D:/doc/
child:子路径字符串,例如letter.txt
对于Microsoft Windows平台,包含盘符的路径名前缀由驱动器号和一个“:”组成。如果路径名是绝对路径名,还可能后跟“\\”。
当使用File类创建一个文件对象后,例如:File file = new File("word.txt") 如果当前目录中不存在名称为word的文件,File类对象可通过调用createNewFile()方法创建一个名称为word.txt的文件;如果存在word.txt文件,可以通过文件对象的delete()方法将其删除;
package com.FILE; import java.io.File; public class FileTest { public static void main(String[] args) { File file=new File("d:/myword/word.txt"); //创建文件对象 if(file.exists()) { //如果文件存在 file.delete(); //删除文件 System.out.println("文件已经清除"); } else { //如果文件不存在 try{ //try语句捕捉异常 file.createNewFile(); //创建该文件 System.out.println("文件创建成功"); }catch (Exception e) { e.printStackTrace(); } } } }
运行结果: 文件已经清除
由于D:/myword目录下已经创建了word.txt文件,因此运行程序会删除word.txt文件
2. 获取文件信息:File类提供了很多方法来获取文件本身信息,其中常用的方法如图所示
实例代码: package com.FILE; import java.io.File; public class FileTest1 { public static void main(String[] args) { File file=new File("d:/myword/surprise.txt"); //新建文件类 if(file.exists()) { String name= file.getName(); //获取文件名称 long l=file.length(); //获取文件长度 boolean hidden=file.isHidden(); //判断文件是否为隐藏文件 System.out.println("文件名称:"+name); System.out.println("文件长度是:"+l); System.out.println("文件是否为隐藏文件:"+hidden); } else { System.out.println("文件不存在"); } } }
运行结果: 文件名称:surprise.txt 文件长度是:0 文件是否为隐藏文件:true
四、 文件输入/输出流
程序运行期间,大部分数据都在内存中进行操作,当程序结束或关闭时,这些数据将消失。如果需要将数据永久保存,可使用文件输入/输出流与指定的文件建立连接,将需要的数据永久保存到文件中。本节将介绍文件输入/输出流。
1. FileInputStream与FileOutputStream:FileInputStream类与FileOutputStream类都用来操作磁盘文件。如果用户的文件读取需求比较简单,则可以使用FileInputStream类,该类继承自InputStream类。FileOutputStream类与FileInputStream类对应,提供了基本的文件写入能力。FileOutputStream类是OutputStream类的子类。FileInputStream类常用的构造方法如下:
1||| FileInputStream(String name)
使用给定的文件名name创建一个FileInputStream对象
2||| FileInputStream(File file)
使用File对象创建FileInputStream对象,允许在把文件连接输入流之前对文件进一步分析
FileOutputStream类有与FileInputStream类相同的参数构造方法,创建一个FileOutputStream对象时,可以指定不存在的文件名,但此文件不能是一个已被其他程序打开的文件。下面的实例就是使用FileInputStream与FileOutputStream类实现文件的读取与写入功能的。
实例代码: package com.FILE; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; public class FileTest3 { public static void main(String[] args) { File file=new File("d:/myword/word.txt"); //创建文件对象 try //捕捉异常 { FileOutputStream out=new FileOutputStream(file); //创建FileOutputStream对象 byte[] b="只因Java太有趣,练习两年半也停不下来".getBytes(); out.write(b); //将信息写入文件中 out.close(); //关闭流 } catch (Exception e) { e.printStackTrace(); } try { FileInputStream in=new FileInputStream(file); //创建FileInputStream类对象 byte[] byt=new byte[1024]; //创建数组 int len=in.read(byt); //从文件中读取信息 System.out.println("文本中的信息是:"+new String(byt,0,len)); in.close(); //关闭流 }catch (Exception e) { e.printStackTrace(); } } }
虽然Java在程序结束时自动关闭所有打开的流,但是当使用完流后,显式地关闭所有打开的流仍是一个好习惯。一个被打开的流有可能会用尽系统资源,这取决于平台和实现。如果没有将打开的流关闭,当另一个程序试图打开另一个流时,可能会得不到需要的资源。
运行结果: 文本中的信息是:只因Java太有趣,练习两年半也停不下来
2. FileReader和FileWriter类:使用FileOutputStream类向文件中写入数据与使用FileInputStream类从文件中将内容读出来,都存在一点不足,即这两个类都只提供了对字节或字节数组的读取方法。由于汉字在文件中占用两个字节,如果使用字节流,读取不好可能会出现乱码现象,此时采用字符流Reader或Writer类即可避免这种现象。FileReader和FileWriter字符流对应了FileInputStream和FileOutputStream类。FileReader流顺序地读取文件,只要不关闭流,每次调用read()方法就顺序地读取源中其余的内容,直到源的末尾或流被关闭。
3. BufferedInputStream与BufferedPutputStream类:BufferedInputStream类可以对所有InputStream类进行带缓存区的包装以达到对性能的优化。BufferedInputStream类有两个构造方法。使用BufferedOutputStream输出信息和用OutputStream输出信息完全一样,只不过BufferedOutputStream有一个flush()方法用来将缓存区的数据强制输出完。BufferedOutputStream类也有两个构造方法
带缓存的输入/输出流:缓存是I/O的一种性能优化。缓存流为I/O流增加了内存缓存区。有了缓存区,使得在流上执行skip()、mark()和reset()方法都成为可能。
Flush()方法就是用于即使在缓存区没有满的情况下,也将缓存区的内容强制写入到外设,习惯上称这个过程为刷新。flush()方法只对使用缓存区的OutputStream类的子类有效。当调用close()方法时,系统在关闭流之前,也会将缓存区中的信息刷新到磁盘文件中
1||| BufferedInputStream(InputStraem in):创建一个带有32个字节的缓存流
2||| BufferedInputStream(InputStream in,int size):按指定的大小来创建缓存区
BufferedInputStream类的两个构造方法
3||| BufferedOutputStream(OutputStream in):创建一个有32字节的缓存区
4||| BufferedOutputStream(OutputStream in,int size):以指定的大小来创建缓存区
BufferedOutputStream类的两个构造方法
4. BufferedReader与BufferedWriter类:BufferedReader类与BufferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并可以以行为单位进行输入/输出。
在使用BufferedWrite类的Write()方法时,数据并没有立刻被写入输出流,而是首先进入缓存区中。如果想立刻将缓存区中的数据写入输出流,一定要调用flush()方法
1||| read():读取单个字符
2||| readLine():读取一个文本行,并将其返回为字符串。若无数据可读,则返回null
BufferedReader类常用的方法
3||| write(String s,int off,int len):写入字符串的某一部分
4||| flush():刷新该流的缓存
5||| newLine():写入一个行分隔符
BufferedWrite类常用方法
实例代码: package com.FILE; import java.io.*; public class FileTest0 { public static void main(String[] args) { String[] string={"晴天","花海","七里香"}; //定义字符串数组 File file=new File("d:/myword/word.txt"); //创建文件对象 try { FileWriter fw=new FileWriter(file); //创建FileWriter类对象 BufferedWriter bfw=new BufferedWriter(fw); //创建BufferedWriter类对象 for (int i=0;i< string.length;i++) { bfw.write(string[i]); //将字符串数组中的元素写入到磁盘文件中 bfw.newLine(); //将数组中的单个元素以单行的形式写入文件 } bfw.close(); fw.close();; }catch (Exception e) { e.printStackTrace(); } try{ FileReader fr=new FileReader(file); BufferedReader bfr=new BufferedReader(fr); String s=null; //创建字符串对象 int i=0; //如果文件的文本行数不为null,则进入循环 while((s= bfr.readLine())!=null) { i++; System.out.println("第"+i+"行:"+s); } bfr.close(); fr.close(); }catch(Exception e) { e.printStackTrace(); } } }
运行结果: 第1行:晴天 第2行:花海 第3行:七里香
5. 数据输入/输出流(DataInputStream类与DataOutputStream类)允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型。也就是说,当读取一个数据时,不必再关心这个数值应当是哪种字节。DataInputStream类与DataOutputStream类的构造方法如下
1||| DataInputStream(InputStream in):使用指定的基础InputStream创建一个DataInputStream
2||| DataOutputStream(OutputStream out):创建一个新的数据输出流,将数据写入指定基础输出流
由于Java中的字符是Unicode编码,是双字节的,writeBytes只是将字符串中的每一个字符的低字节内容写入目标设备中;而writeChars将字符串中的每一个字符的两个字节的内容都写到目标设备中;writeUTF将字符串按照UTF编码后的字节长度写入目标设备,然后才是每一个字节的UTF编码。 DataInputStream类只提供了一个readUTF()方法返回字符串。这是因为要在一个连续的字节流读取一个字符串,如果没有特殊的标记作为一个字符串的结尾,并且不知道这个字符串的长度,就无法知道读取到什么位置才是这个字符串的结束。DataOutputStream类中只有writeUTF()方法向目标设备中写入字符串的长度,所以也能准确地读回写入字符串。
DataOutputStream类提供3中写入字符串的方法
1||| writeBytes(String s)
2||| writeChars(String s)
3||| writeUTF(String s)
实例代码: package com.FILE; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; public class DataTest { public static void main(String[] args) { try { FileOutputStream fs=new FileOutputStream("d:/myword/word.txt"); //创建FileOutputStream对象 DataOutputStream ds=new DataOutputStream(fs); ds.writeUTF("使用writeUTF方法写入数据"); ds.writeChars("使用writeChars写入数据"); ds.writeBytes("使用writeBytes写入数据"); ds.close(); //关闭流 }catch(Exception e) { e.printStackTrace(); } try{ FileInputStream fis=new FileInputStream("d:/myword/word.txt"); DataInputStream dis=new DataInputStream(fis); System.out.println(dis.readUTF()); //将文件数据输出 }catch(Exception e) { e.printStackTrace(); } } }
运行结果: 使用writeUTF方法写入数据
6. 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和ZipOutputStream 3个Java类实现ZIP数据压缩方式的编程方法。
1||| 压缩文件:利用ZipOutputStream类对象,可将文件压缩为.zip文件。ZipOutputStream类的构造方法如下:ZipOutputStream(OutputStream out)
ZipOutputStream类的常用方法
I. putNextEntry(ZipEntry e):开始写一个新的ZipEntry,并将流内的位置移至此entry所值数据的开头,返回值void
II. write(byte【】 b,int off,int len):将字节数组写入当前ZIP条目数据,返回值void
III. finish():完成写入ZIP输出流的内容,无须关闭它所配合的OutputStream,返回值void
IV. setComment(String comment):可设置此ZIP文件的注释文字,返回值void
2||| 解压缩文件:ZipInputStream类可读取ZIP压缩格式的文件,包括已压缩和未压缩的条目(entry)。ZipInputStream类的构造方法如下: ZipInputStream(InputStream in)
ZipInputStream类常用的方法
I. read(byte[] b,int off,int len):读取目标b数组内off偏移量的位置,长度是len字节,返回值int
II. available():判断是否已读完目前entry所指定的数据。已读完返回0,否则返回1,返回值int
III. closeEntry():关闭当前ZIP条目并定位流以读取下一个条目,返回值void
IV. skip(long n):跳过当前ZIP条目中指定的字节数,返回值long
V. getNextEntry():读取下一个ZipEntry,并将流内的位置移放至该entry所指数据的开头,返回值ZipEntry
VI. createZipEntry(String name):以指定的name参数新建一个ZipEntry对象,返回值ZipEntry