栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA IO流

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA IO流

目录

1、流体系及实现类

2、流的划分

3、File类介绍

4、字节流

4、字符流

5、转换流

6、缓冲流

7、对象流

8、RandomAccessFile类


流介绍:Java中所有的数据都是使用流读写的,流是一组有顺序、有方向,有起点和终点的字节集合,通过使用流我们可以完成设备之间的数据传输。

1、流体系及实现类

流的体系

流的实现类

2、流的划分

按照方向划分:

输入流:从各种输入设备(磁盘、网卡、键盘...)将数据读取到当前程序

输出流:从当前程序将数据写入输出设备(磁盘、网卡、屏幕)

按照数据传输单元划分

字节流:以字节为单位的数据传输流, InputStream和OutputStream

字符流:以字符为单位的数据传输流,Reader、Writer

按照功能划分

节点流:用于直接操作目标设备的流

过滤流(高级流):对一个已存在的流进行包装,以提供更强大灵活的读写功能

3、File类介绍

File类主要是对文件或者目录的抽象表示

文件可以理解为保存数据的一种方式

文件一共有两部分组成,属性(文件名、大小、类型)和内容(文件中存储的内容)

File类的构造函数

构造函数
File (String pathName)通过路径字符串获取file实例
File(String parent, String child)第一个参数:父路径字符串 第二个参数:文件名字符串
File(File parent, String child)第一个参数:父路径File对象 第二个参数:文件名字符串

调用示例  

 String path = "/Userstest1.txt";
 ​
         //通过一个字符串路径创建file实例
         File file = new File(path);
 ​ ​
         String parentPathName = "/Userstest";
         String name = "test1.txt";
         //通过父路径字符串和文件名字符串创建file实例
         File file1 = new File(parentPathName, name);
 ​
         File parentFileName = new File(parentPathName);
         //通过父路径的file对象和文件名字符串创建file实例
         File file2 = new File(parentFileName, name);

绝对路径和相对路径

绝对路径:带盘符开始的路径, 比如:windows系统:C: Linux: /

相对路径:不带盘符的路径 '.'当前路径 '..':父路径

路径分割符:

Linux:‘/’ 例如:/Users       // int read(byte[] bytes) ; // 读取的字节保存在数组中     byte[] bytes = new byte[2];        int read = -1;        while((read = inputStream.read(bytes) )!= -1){            System.out.print(new String(bytes,0,read));        }                 int read(int byte[], int begin,int len)   获取从指定位置开始,获取指定长度的字节         byte[] bytes = new byte[10];         int read = -1;         while((read = inputStream.read(bytes,2,5)) != -1){            System.out.println(read);              System.out.print(new String(bytes,2,read));         }          ​   } catch (FileNotFoundException e) {        e.printStackTrace();   } catch (IOException e) {        e.printStackTrace();   }finally {        try {            //关闭流            inputStream.close();       } catch (IOException e) {            e.printStackTrace();       }   }

2、OutputStream类

OutputStream是字节输出的基类

 public abstract class OutputStream implements Closeable, Flushable 

核心方法:

文件输出流

FileOutputStream:将数据从程序写入目标存储设备:文件

构造函数:

当文件不存在时,会创建出指定文件,当路径不存在时,会抛出FileNotFoundException异常。append默认是false,表示写入的数据会覆盖文件原本内容,如果append为true,可以进行内容追加,将新写入的内容追加到文件的后面

  FileOutputStream(String name) throws FileNotFoundException
  FileOutputStream(String name, boolean append) throws FileNotFoundException
  FileOutputStream(File file) throws FileNotFoundException
  FileOutputStream(File file, boolean append)  throws FileNotFoundException

方法调用:         

String path = "/Users/苏亚/Desktop/IO/Java.txt";
 ​
         FileOutputStream outputStream=null;
         try {
             outputStream = new FileOutputStream(path);
             //写一个字节
             
            outputStream.write('d');
 ​
             
             byte[] bytes = {'a', 'b', 'c'};
             outputStream.write("hello".getBytes());
 ​
             
             byte[] bytes1 = "hello tulun".getBytes();
             outputStream.write(bytes1,6,5);
             
             //将数据刷入磁盘
             outputStream.flush();

4、字符流

Reader:字符输入流

Reader是IO库提供到的一个输入流基类

和InputStream的区别是:InputStream是一个字节流,操作的是以byte为单位读取;Reader是一个字符流,操作的是以char为单位读取

Reader的继承关系如下:

 public abstract class Reader 
     implements Readable, Closeable

FileReader类

该类是Reader的实现类,其主要功能是从磁盘文件中读取数据

读取方法:

 public int read() throws IOException
 public int read(char cbuf[]) throws IOException
 public int read(char cbuf[], int off, int len) throws IOException
 public int read(java.nio.CharBuffer target) throws IOException

读取操作:        

  //读取数据
             int read = fd.read();
             System.out.println((char) read);
 ​
             
             char[] chars = new char[12];
             int read1 = fd.read(chars);
             System.out.println(new String(chars,0,read1));
 ​
             
             fd.read();

Writer:字符输出流

字符输出流, Writer操作的是字符,以char为单位进行操作

OutputStream操作的是字节,以byte为单位操作

Writer操作带有编码装换器的OutputStream

Reader操作带有编码转换器的InputStream

Writer的继承关系如下:

public abstract class Writer implements Appendable, Closeable, Flushable 

核心方法

FileWriter类

该类是Writer的实现类主要功能是向磁盘文件中写入数据。

文件的写操作

构造函数:

构造函数注意: 1、如果文件不存在可以自动创建,如果目录不存在,则抛出异常

2、如果需要将写入的数据以追加的形式存储,需要传递append参数为true

方法介绍:

     FileWriter fw = null;
         try {
             fw = new FileWriter(path,true);
             
             fw.write('a');
 ​
             
             char[] chars = {'a', 'b', 'c'};
             fw.write(chars);
 ​
             
             fw.write(chars,0,3);
 ​
             
             fw.write("hello");
 ​
             
             fw.write("hello",0,5);
 ​
             fw.append(" tulun");
 ​
             fw.flush();

5、转换流

将字节流和字符流进行相互转换

OutputStreamWriter:将字节输出流转换为字符输出流

InputStreamReader:将字节输入流转换为字符输入流

 public class OutputStreamWriter extends Writer
 ​
 public OutputStreamWriter(OutputStream out) {
         super(out);
         try {
             se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);
         } catch (UnsupportedEncodingException e) {
             throw new Error(e);
         }
     }
     
 ​
 public class InputStreamReader extends Reader
 ​
     public InputStreamReader(InputStream in) {
         super(in);
         try {
             sd = StreamDecoder.forInputStreamReader(in, this, (String)null); // ## check lock object
         } catch (UnsupportedEncodingException e) {
             throw new Error(e);
         }
     }

由源码分析可知OutputStreamWriter是继承Writer这个类,InputStreamReader继承Reader这个类,主要的目的就是把字节流转换成字符流的形式进行数据的读和写操作。

Reder和InputStream的关系

普通的Reader实际上是基于InputStream改造的,因为Reader需要从INputStream中读取字节流(byte),然后根据编码设置,在转化为字符流(char),在底层实现上持有一个转换器(StreamDecoder)

使用方式如下:  

 //字节流
         //原始流
         FileInputStream inputStream = new FileInputStream(path);
         //高级流,通过封装原始流提供高级特征
         InputStreamReader inputStreamReader = new InputStreamReader(inputStream);

6、缓冲流

缓冲罐流的作用就是磁盘的I/O次数减少,提高IO读写速度,也就是把数据读取或者写入时就会先把数据先保存在缓冲流中,到达一定的数据量后或者读取/写入数据已经结束后在IO操作。

缓冲流划分:字节缓冲流、字符缓冲流

字节缓冲流:BufferedInputStream、BufferedOutputStream

字符缓冲流:BufferedReader、BufferedWriter

继承关系

 public class BufferedInputStream extends FilterInputStream
 ​
 public class BufferedOutputStream extends FilterOutputStream
 ​
 public class BufferedReader extends Reader
 ​
 public class BufferedWriter extends Writer
以字符缓冲流为例介绍
 InputStream inputStream = null;
         BufferedInputStream bufferedInputStream = null;
         try {
             inputStream = new FileInputStream(file);
             bufferedInputStream = new BufferedInputStream(inputStream);
         } catch (FileNotFoundException e) {
             e.printStackTrace();
         }

BufferedReader和BufferedWriter缓冲流

字符输出流:

String readLine() 分行读取 读取结束为null

字符输入流:

void newline() 根据当前系统,写入一个换行符

7、对象流

在介绍对象流之前首先了解序列化和反序列化的概念

序列化和发序列化

序列化:将对象转化为字节流的过程,可以将流进行保存到磁盘或者是发送到网络中(rpc)

反序列化:将字节流转化为对象的过程

序列化的特点:

1、在Java中,只要一个类实现了Serializable接口,那么就可以支持序列化和反序列化

2、通过ObjectInputStream和ObjectOutputStream对对象进行序列化和发序列化

3、transient关键字用于控制变量的序列化,在变量前添加该关键字,可以阻止该字段被序列化到文件中,在反序列化后,transient关键字修饰的变量给定的就是初始化,对象类型是null,int类型是0

4、虚拟机是否允许反序列化,不仅仅取决于类路径和代码是否一致,还要看两个类的序列化Id是否一致

什么是serialVersionUID?

称之为版本标识符,使用对象的哈希码序列化会标记在对象上

两种生成方式,一种是默认的1L、另一种是通过类名、接口名、成员变量及属性等生成的64位的哈希字段,UID的生成的默认值是依赖于Java编译器的,对于同一个类,不同的编译器生成的结果UID可能是不同。idea中的具体操作设置如下

版本号的作用:

1、确保不同的版本有不同的UID

2、在类中新增或者修改属性,不设置UID,会抛出异常

对象流的处理使用ObjectInputStream和ObjectOutputStream类

以ArrayList为例介绍序列化和反序列化,在ArrayList中定义了writeObject和readObject方法

在序列化的过程中,如果被定义的类中定义类writeObject,虚拟机会试图来调用类中writeObject方法来进行序列化,如果没有这个存在,调用默认的ObjectOutputStream中defaultWriteObject方法来序列化

反序列化的类似

对ArrayList集合进行序列化和反序列代码如下: 

 public static void objectReader() {
         String path = "/Users/gongdezhe/Desktop/IO/test1.txt";
 ​
         try {
             ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(path));
             ArrayList list = (ArrayList) inputStream.readObject();
             Iterator iterator = list.iterator();
             while (iterator.hasNext()) {
                 System.out.println(iterator.next());
             }
 ​
         } catch (IOException e) {
             e.printStackTrace();
         } catch (ClassNotFoundException e) {
             e.printStackTrace();
         }
 ​
     }
 ​
     public static void objectWrite() {
         String path = "/Users/gongdezhe/Desktop/IO/test1.txt";
 ​
         ArrayList  list = new ArrayList <>(100);
         list.add(11);
         list.add(22);
         list.add(33);
 ​
         try {
             ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(path));
 ​
             outputStream.writeObject(list);
 ​
             outputStream.close();
 ​
         } catch (IOException e) {
             e.printStackTrace();
         }
     }

源码实现思路

在ArrayList中显性实现了WriteObject和ReadObject方法。在对ArrayList的对象进行序列化和反序列化过程中,会自动调用到ArrayList中定义的WriteObject和ReadObject方法,在ArrayList中存储数据的属性定义为ElementData属性,该属性是通过transient关键字修饰

该关键字的目的是不让修改的属性参与序列化,而ArrayList中数据就存储在elementData中,如果不参与序列化,则ArrayList中的数据则无法持久化这就需要进行特殊处理。

 private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         elementData = EMPTY_ELEMENTDATA;
 ​
         // Read in size, and any hidden stuff
         s.defaultReadObject();
 ​
         // Read in capacity
         s.readInt(); // ignored
 ​
         if (size > 0) {
             // be like clone(), allocate array based upon size not capacity
             ensureCapacityInternal(size);
 ​
             Object[] a = elementData;
             // Read in all elements in the proper order.
             for (int i=0; i

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/531909.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号