zoukankan      html  css  js  c++  java
  • Java中的 I/O知识点

    对于Java I/O来说,I意味着Input(输入),O意味着Output(输出)。读书写作并非易事,而创建一个好的I/O系统更是一项艰难的任务。

    古人云:“读书破万卷,下笔如有神”。也就是说,只有大量的阅读,写作的时候才能风生水起——写作意味着输出(我的知识传播给他人),而读书意味着输入(从他人的知识中汲取营养)。

    01、数据流之字节与字符

    Java所有的I/O机制都是基于数据流进行的输入输出。数据流可分为两种:

    1)字节流,未经加工的原始二进制数据,最小的数据单元是字节

    2)字符流,经过一定编码处理后符合某种格式规定的数据,最小的数据单元是字符——占用两个字节。

    OutputStreamInputStream用来处理字节流;WriterReader用来处理字符流;OutputStreamWriter可以把OutputStream转换为WriterInputStreamReader可以把InputStream转换为Reader

    Java的设计者为此设计了众多的类,见下图。

    看到这么多类,你一定感觉头晕目眩。反正我已经看得不耐烦了。搞这么多类,看起来头真的大——这也从侧面说明实际的应用场景各有各的不同——你也完全不用担心,因为实际项目当中,根本就不可能全用到(我就没用过SequenceOutputStream)。

    我建议你在学习的时候要掌握一种“挑三拣四”的能力——学习自己感兴趣的、必须掌握的、对能力有所提升的知识。切不可囫囵吞枣,强迫自己什么都学。什么都学,最后的结果可能是什么都不会。

    字符流是基于字节流的,因此,我们先来学习一下字节流的两个最基础的类——OutputStreamInputStream,它们是必须要掌握的。

    1)OutputStream

    OutputStream提供了4个非常有用的方法,如下。

    • public void write(byte b[]):将数组b中的字节写到输出流。

    • public void write(byte b[], int off, int len):将数组b的从偏移量off开始的len个字节写到输出流。

    • public void flush() : 将数据缓冲区中数据全部输出,并清空缓冲区。

    • public void close() : 关闭输出流并释放与流相关的系统资源。

    其子类ByteArrayOutputStreamBufferedOuputStream最为常用(File相关类放在下个小节)。

    ①、ByteArrayOutputStream通常用于在内存中创建一个字节数组缓冲区,数据被“临时”放在此缓冲区中,并不会输出到文件或者网络套接字中——就好像一个中转站,负责把输入流中的数据读入到内存缓冲区中,你可以调用它的toByteArray()方法来获取字节数组。

    来看下例。

    ByteArrayOutputStream的责任就是把InputStream中的字节流“一字不差”的读出来——这个工具方法很重要,很重要,很重要——可以解决粘包的问题。

    ②、BufferedOuputStream实现了一个缓冲输出流,可以将很多小的数据缓存为一个大块的数据,然后一次性地输出到文件或者网络套接字中——这里的“缓冲”和ByteArrayOutputStream的“缓冲”有着很大的不同——前者是为了下一次的一次性输出,后者就是单纯的为了缓冲,不存在输出。

    来看下例。

    使用BufferedOuputStream的时候,一定要记得调用flush()方法将数据从缓冲区中全部输出。使用完毕后,调用close()方法关闭输出流,释放与流相关的系统资源。

    2)InputStream

    InputStream也提供了4个非常有用的方法,如下。

    • public int read(byte b[]):读取b.length个字节的数据放到数组b中,返回值是读取的字节数。

    • public int read(byte b[], int off, int len):从输入流中最多读取len个字节的数据,存放到偏移量为off的数组b中。

    • public int available():返回输入流中可以读取的字节数。

    • public int close() :使用完后,对打开的流进行关闭。

    其子类BufferedInputStream(缓冲输入流)最为常用,效率最高(当我们不确定读入的是大数据还是小数据)。

    无缓冲流上的每个读取请求通常会导致对操作系统的调用以读取所请求的字节数——进行系统调用的开销非常大。但缓冲输入流就不一样了,它通过对内部缓冲区执行(例如)高达8k字节的大量读取,然后针对缓冲区的大小再分配字节来减少系统调用的开销——性能会提高很多。

    使用示例如下。

    先来看一个辅助方法byteToInt,把字节转换成int。

    再来看如何从输入流中,根据指定的长度contentLength来读取数据。readBytes()方法在之前已经提到过。

    我敢保证,只要你搞懂了字节流,字符流也就不在话下——所以,我们在此略过字符流。

    02、File类

    前面我们了解到,数据有两种格式:字节与字符。那么这些数据从哪里来,又存往何处呢?

    一个主要的方式就是从物理磁盘上进行读取和存储,磁盘的唯一最小描述就是文件。也就是说上层应用程序只能通过文件来操作磁盘上的数据,文件也是操作系统和磁盘驱动器交互的一个最小单元。

    在Java中,通常用File类来操作文件。当然了,File不止是文件,它也是文件夹(目录)。File类保存了文件或目录的各种元数据信息(文件名、文件长度、最后修改时间、是否可读、当前文件的路径名等等)。

    通过File类以及文件输入输出流(FileInputStreamFileOutputStream),可以轻松地创建、删除、复制文件或者目录。

    这里,我提供给你一个实用的文件工具类——FileUtils。

    限于篇幅,就不贴太多代码了,需要的话找我(微信:qing_gee)要。

    • public static boolean createFile(String descFileName):创建文件。

    • public static boolean createDirectory(String descDirName):创建目录。

    • public static boolean copyFile(String srcFileName, String descFileName):复制文件。

    • public static boolean copyDirectory(String srcDirName, String descDirName):复制目录。

    • public static boolean deleteFile(String fileName):删除文件。

    • public static boolean deleteDirectory(String dirName):删除目录。

    • public static void writeToFile(String fileName, String content, boolean append):向文件中写入内容。

    03、网络套接字——Socket

    虽然网络套接字(Socket)并不在java.io包下,但它和输入输出流密切相关。FileSocket是两组主要的数据传输方式。

    Socket是描述计算机之间完成相互通信的一种抽象。可以把 Socket比作为两个城市之间的交通工具,有了交通工具(高铁、汽车),就可以在城市之间来回穿梭了。交通工具有多种,每种交通工具也有相应的交通规则。Socket也一样,也有多种。大部分情况下,我们使用的都是基于TCP/IP的套接字——一种稳定的通信协议。

    假设主机A是客户端,主机B是服务器端。客户端要与服务器端通信,客户端首先要创建一个Socket实例,操作系统将为这个Socket实例分配一个没有被使用的本地端口号,并创建一个套接字数据结构,直到这个连接关闭。

    示例如下。

    与之对应的,服务端需要创建一个ServerSocket实例,之后调用accept()方法进入阻塞状态,等待客户端的请求。当一个新的请求到来时,将为这个连接创建一个新的套接字数据结构。

    示例如下。

    Socket一旦打通,就可以通过InputStreamOutputStream进行数据传输了。

    04、压缩

    Java I/O 支持压缩格式的数据流。在Socket通信中,我常用GZIPOutputStreamGZIPInputStream来对数据流进行简单地压缩和解压。

    压缩的好处就在于能够减小网络传输中数据的体积。代码如下。

    PS:如果大家在学习过程中遇到什么问题,或者缺乏相关的学习资料,可查看我的公告栏获取,有问题随问随答,还有我这段时间整理的一些Java学习手册,面试题,开发工具,PDF文档书籍教程,需要的话都可以免费分享给大家。

  • 相关阅读:
    Linear Regression总结
    Logistic Regression总结
    LOG算子
    斑点检测
    从 SVM 到多核学习 MKL
    目标检测的图像特征提取之(二)LBP特征
    HOG:从理论到OpenCV实践
    web前端升级之路
    webpack入门
    VUE2.0实现购物车和地址选配功能学习第七节
  • 原文地址:https://www.cnblogs.com/lcywuwuwu/p/13992652.html
Copyright © 2011-2022 走看看