今天再次回顾了一些关于java IO流的知识。虽然以前会点IO的方面的编程,但是还是知其然不知其所以然。
首先上一张IO流的主要家族图吧。
该图给出了IO流的具体分类和各类之间的继承关系。其中还给出了各个类的使用场景和用途。
一、IO流的主流分类
IO流主要分为字节流和字符流。它们之间的区别就是:
1、读写的单位不同,字节流是以字节(8bit)为单位的。字符流是以字符为单位的,根据字符码表映射的字符,一次可能读取多个字节。
2、处理的对象不同。字节流处理所有类型的数据,包括图片、音视频等。而字符流只能处理字符型的数据。
3、字节流是直接传输的流通道,在进行流操作时是没有缓冲区的。但是字符流在操作的时候会使用到缓冲区。这就是为什么字符流的类实例都会有flush()方法。
然后针对字节流和字符流会分成相应的输入输出流。
字节流:InputStream输入字节流、OutputStream输出字节流。
字符流:Reader字符输入流、Writer字符输出流。
二、文件类的介绍和说明
在java中表示文件类的有File和RandomAccessFile类。而IO流的类主要是针对文件类中的文件内容来进行读写的操作的。
1、File类表示文件的本身,可以直接使用此类来完成文件的各种操作。比如:创建、删除、判断是否为目录等。
2、RandomAccessFile类可以从指定的位置开始读取信息,主要是因为这个类中定义了文件指针。但是这个类是要求文件中各个数据的保存的长度必须是固定的。
接下来举一个经常会问到的例子:如何遍历一个文件目录中的所用文件??
代码如下:
package com.io; import java.io.*; public class listFile { public static void main(String[] args) { // TODO Auto-generated method stub //1 新建一个File类的实例 File file=new File("d:"+File.separator+"Xiaomi"); //2 进行文件目录的打印 print(file); } public static void print(File file) { // TODO Auto-generated method stub if(file!=null){//判断文件不为空 if(file.isDirectory()){//判断文件是不是目录 File[] fs=file.listFiles();//返回所有的子文件 if(fs!=null){ //开始遍历子文件 for (int i = 0; i < fs.length; i++) { print(fs[i]); } } }else{//如果不是目录就打印文件的路径 System.out.println(file); } } } }
结果显示:
三、输入输出流的介绍
输入输出流主要分为字节流和字符流。但是在传输中使用字节流的操作会比较的多。InputStream输入字节流、OutputStream输出字节流、Reader字符输入流、Writer字符输出流它们都是抽象类,根据使用的子类不同输入或输出的位置会不同。
比如向对上面的File文件类来进行操作时,我们应该会想到使用FileInputStream和FileOutputStream类。
Java的JDK中也提供了将字节流转换为字符流的类:InputStreamReader(InputStream)和OutputStreamWriter(OutputStream)这两个类。
使用ByteArrayInputStream和ByteArrayOutputStream类是可以对内存进行输入和输出的。
在线程之间进行输入和输出时主要使用的是PipedOutputStream和PipedInputStream类。
这里注意一下,在日常的IO输出时最好是使用打印流来进行输出。即PrintWriter和PrintStream类。这样可以方便的打印各种类型的数据,说到底就是打印流中的print方法实现了对各种数据打印方法的重载。还有我们经常使用的System.out实际上就是一个PrintStream类。
—————————————————–*————————————————————————-
当然对于这些IO输入输出类实际上我们是可以进行装饰的。这就是FilterInputStream、FilterReader等类的作用,它们的子类就是对应的各种各样的装饰类。比如以 FilterOutputStream的子类是:BufferedOutputStream、 DataOutputStream、PrintStream。
BufferedOutputStream是可以直接向缓冲区写入数据。该类实现缓冲的输出流。通过设置这种输出流,应用程序就可以将各个字节写入底层输出流中,而不必针对每次字节写入调用底层系统。
DataOutputStream是数据输出流,提供了与平台无关的数据操作。数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
PrintStream 为其他输出流添加了功能,使它们能够方便地打印各种数据值表示形式。
注意这些经过装饰类修饰的IO字节流,有的会带有缓冲区功能。所以也就会有flush()方法。
BufferedOutputStream为IO提供了带有缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提高了IO的性能。从应用程序中把输入放入文件,相当于将一缸水倒入另一个缸中。
1> FileOutputStream—->write方法相当于一滴一滴的把水转移过去。
2> DataOutputStream–>writeXXX方法会方便一些,相当于一瓢一瓢的把水转移过去
3> BufferedOutputStream–>write()方法会更方便一些,相当于一瓢一瓢先放入水桶中,在从桶中倒入缸中,性能提高了。
四、对象的序列化
什么叫对象的序列化。实际上就是把一个对象变为二进制的字节数据流的一种方法。
如果一个类想实现序列化只需要实现Serializable接口即可。接着我们是如何将这个类进行传输的。这时会有两个字节流:ObjectInputStream和ObjectOutputStream(对象输入输出流)。我们要知道类的序列化序列的是属性的内容,不会序列化方法的。如果我们使用transient关键字来修饰某个属性,这就表示这个属性是不会被序列化的。
为何要进行序列化呢.不进行序列化,我的程序不跑的好好的吗?你想要什么结果,我也能给解决不是.我想说确实是这样,如果你的程序与网络无关,那很好你已经可以摒弃它了. 那下面我来简单分析下为何java需要进行序列化呢? 首先我们要明白,序列化是做什么作用的?java序列化:以特定的方式对类实例的瞬时状态进行编码保存的一种操作。(可能不是很精确,咱不是搞学术的,看懂即可)。从此定义可以看出,序列化作用的对象是类的实例。对实例进行序列化,就是保存实例当前在内存中的状态。包括实例的每一个属性的值和引用等。 既然后序列化,便会有反序列化。反序列化的作用便是将序列化后的编码解码成类实例的瞬时状态,申请等同的内存保存该实例。 从上述定义可以发现,序列化就是为了保存java的类对象的状态的。保存这个状态的作用主要用于不同jvm之间进行类实例间的共享。在ORMaping中的缓存机制,进行缓存同步时,便是常见的java序列化的应用之一。在进行远程方法调用,远程过程调用时,采用序列化对象的传输也是一种应用…当你想从一个jvm中
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/292991.html