一、java.io包概览

Java IO包主要可以分为如下4类:

基于字节操作的I/O接口:InputStream和OutputStream。

基于字符操作的I/O接口:Writer和Reader

基于磁盘操作的I/O接口:File。

基于网络操作的I/O接口:Socket(没在IO包下)。

前2种区分I/O操作中数据的格式,后2种主要是数据传输的方式。

二、基于字节的I/O操作

1、 InputStream介绍

InputStream是所有基于字节格式处理读数据的父类,其类层次结构如及大致介绍下:

1.1 ByteArrayInputStream

包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read 方法要提供的下一个字节。 关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。实例代码如下:

 public static void main(String[] args) throws IOException {

 // TODO Auto-generated method stub

         byte [] buf = {0x3A,0x22,0x33};

        InputStream is = new ByteArrayInputStream(buf);

        int c = is.read();

        while(c != -1){

        System.out.println(c);

        c = is.read();

        }

        is.close();

        is.reset();

        System.out.println(is.read());

 }

1.2 FileInputStram

利用此类可以以字节方式读取文件内容,一般用于读取二进制文件,若读取文本文件,考虑使用FileReader,示例代码如下:

        File file = new File("test.txt");
InputStream inputStream = new FileInputStream(file);
byte [] content = new byte[10];
StringBuffer sb = new StringBuffer();
while(inputStream.read(content) != -1){
sb.append(new String(content));
content = new byte[10];
}
inputStream.close();
System.out.println(sb.toString());

1.3 FilterInputStream

封装其它的输入流,并为它们提供额外的功能,它的常用的子类有BufferedInputStream和DataInputStream。BufferedInputStream的作用就是为“输入流提供缓冲功能,以及mark()和reset()功能”。
DataInputStream 是用来装饰其它输入流,它“允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型”。应用程序可以使用DataOutputStream(数据输出流)写入由DataInputStream(数据输入流)读取的数据。示例代码如下:

        BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.txt"));
byte [] data = new byte[10];
StringBuffer sb = new StringBuffer();
while(in.read(data) != -1){
sb.append(new String(data));
data = new byte[10];
}
in.close();
System.out.println(sb.toString());

2. OutputStream介绍

OutputStream是所有基于字节格式处理写数据的父类,其类层次结构如及大致介绍下:

2.1 ByteArrayOutputStream

此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()和 toString()获取数据,关闭后仍可使用。由于这个原因,ByteArrayOutputStream常用于存储数据以用于一次写入。

     public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
ByteArrayOutputStream os = new ByteArrayOutputStream();
Random random = new Random();
for(int i=0;i<5;i++){
int a = random.nextInt(999);
os.write(a);
System.out.println(a);
}
System.out.println(os.toByteArray().length); //length:5
for(int i=0;i<os.toByteArray().length;i++){
System.out.println(os.toByteArray()[i]);
}
}

2.2 FileOutputStream

A file output stream is an output stream for writing data to a File or to a FileDescriptor. Whether or not a file is available or may be created depends upon the underlying platform. Some platforms, in particular, allow a file to be opened for writing by only one FileOutputStream (or other file-writing object) at a time. In such situations the constructors in this class will fail if the file involved is already open. 示例代码如下:

        String content = "\n今天没吃药\n明天再吃药";
OutputStream os = new FileOutputStream("test_write.txt",true);
os.write(content.getBytes());
os.close();
System.out.println("dddd");

2.3 FilterOutputStream

This class is the superclass of all classes that filter output streams. These streams sit on top of an already existing output stream (the underlying output stream) which it uses as its basic sink of data, but possibly transforming the data along the way or providing additional functionality.
The class FilterOutputStream itself simply overrides all methods of OutputStream with versions that pass all requests to the underlying output stream. Subclasses of FilterOutputStream may further override some of these methods as well as provide additional methods and fields.

与FilterInputStream用法类似,示例代码如下:

        String data = "新年好\n红包呢";
File file = new File("filter_output_stream.txt");
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(file, true));
os.write(data.getBytes("UTF-8"));
os.close();
System.out.println("write over!!!");

三、基于字符的I/O操作

不管是磁盘还是网络操作,最小的存储单元都是字节, 而不是字符,所以I/O操作都是字节,而不是字符。但由于程序中通常操作的都是字符,为了方便使用,java提供了字符接口。

但字节到字符必须经过转码,而编码非常耗时,而且还会经常出现乱码。

1. Reader介绍

Reader类是所有字符操作的父类,Abstract class for reading character streams. The only methods that a subclass must implement are read(char[], int, int) and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.

        StringBuffer sb = new StringBuffer();
char [] buf = new char[10];
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream("test.txt"),"UTF-8"));//一般会包一层BufferedReader以提升性能
while(reader.read(buf) != -1){
sb.append(buf); }
reader.close();
System.out.println(sb.toString());

2. Writer介绍

Abstract class for writing to character streams. The only methods that a subclass must implement are write(char[], int, int), flush(), and close(). Most subclasses, however, will override some of the methods defined here in order to provide higher efficiency, additional functionality, or both.

        String data = "你好周杰伦\n快来快来\n顶顶顶顶";
Writer writer =
new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("output_stream_writer.txt",true),"UTF-8"));
writer.write(data);
System.out.println("write over");
writer.close();

3. 字节与字符的转化接口

数据持久化或网络传输都是以字节进行的,所以必须有从字符到字节或字节到字符的转化接口,从字符到字节需要转化,其过程为:

InputStreamReader类是从字节到字符的转化的桥梁,从InputStream到Reader要制定编码字符集,否则会用系统某人字符集,很可能出现乱码问题。StreamDecoder是完成从字节到字符解码功能实现类。

FileReader类就是按上述方式读取文件内容的,FileReader继承自InputStreamReader类,实际上是读取文件,然后通过StreamDecoder解码成char,此处用的默认字符编码集。

写入过程类似,

通过OutputStreamWriter类  完成从字符到字节的编码过程,有StreamEncoder完成编码过程。

四、磁盘I/O机制分析

读取和写入文件需调用操作系统接口,分别对应read和write2个系统调用,而只要是系统调用,就可能存在内核地址空间和用户地址空间转换的问题,因为操作系统需保护自身运行的安全性。

但内核调用时存在数据从内核复制到用户空间的问题,若遇到非常耗时的I/O操作,性能会很差。

因此,操作系统在内核使用缓存机制,以减少I/O相应时间。下面是常见的文件访问方式。

1. 标准文件访问方式

read时,OS检查内核缓存是否有,有则返回缓存,无则从磁盘读取,并缓存。

write时,OS将用户空间数据复制到内核地址缓存,这是对用户程序来说,write已经完成,但写入磁盘的时机由OS决定,除非显示调用sync命令。

2. 直接I/O方式

直接I/O方式指应用程序直接访问磁盘数据,而不经过OS内核缓冲区,目的是为了减少从内核缓冲区到用户空间数据复制的时间,此种方式常用于数据库。

因为数据库明确知道应该缓存哪些数据,且可对热点数据提前预加载到内存,负面影响是若数据不在应用缓存中,则会直接去磁盘操作,此时耗时较多。

因此,直接I/O通常会跟异步I/O结合使用。

3. 同步访问文件的方式

数据写入和读取都是同步的,只有数据成功写到磁盘时才返回写成功,性能较差,用于对数据安全性要求较高的场合,且硬件通常是定制的。

4. 异步访问方式

发出访问数据请求后,线程会接着处理其他事情,而不是堵塞等待,请求数据返回后才处理下面的操作。

此方式明显提高应用程序的效率,但不会改变访问文件的效率。

5. 内存映射方式

将内存和硬盘映射,当访问内存时,转化到访问磁盘,目的是减少内核到用户空间的数据复制,因为此时这2个空间的数据是共享的。

五、 File和FileDescriptor类

1. File类

Java中的File类并不代表一个真实存在的文件对象,当创建一个File对象时,返回代表这个路径的虚拟对象

该路径本身可能是个文件或文件夹,不会检查改路径是否存在。

2. FileDescriptor类

当真正访问文件时,会创建一个关联真实存在的磁盘文件的文件描述符FileDescriptor,通过这个对象可以直接控制磁盘文件。

File对象可以通过getFD方法获取FileDescriptor对象,FileDescriptor.sync()方法将OS缓存数据强制刷新到磁盘中。

六、Java序列化技术

一般会用通用技术存储,如JSON或XML,且尽量存储通用的数据结构。

01--Java IO基础的更多相关文章

  1. java IO基础操作

    java IO基础,通熟易懂,好久没复习java 基础了.这里是传送门... http://www.cnblogs.com/nerxious/archive/2012/12/15/2818848.ht ...

  2. 归纳从文件中读取数据的六种方法-JAVA IO基础总结第2篇

    在上一篇文章中,我为大家介绍了<5种创建文件并写入文件数据的方法>,本节我们为大家来介绍6种从文件中读取数据的方法. 另外为了方便大家理解,我为这一篇文章录制了对应的视频:总结java从文 ...

  3. 总结java创建文件夹的4种方法及其优缺点-JAVA IO基础总结第三篇

    本文是Java IO总结系列篇的第3篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  4. 总结删除文件或文件夹的7种方法-JAVA IO基础总结第4篇

    本文是Java IO总结系列篇的第4篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  5. 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇

    本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...

  6. 086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结

    086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结 本文知识点:面向对象基础(类和对象)总结 说明 ...

  7. 085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用

    085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用 本文知识点:构造方法调用 说明:因为时间紧张,本人写博客过程中只是 ...

  8. 084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字

    084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字 本文知识点:构造方法-this关键字 说明:因为时间紧 ...

  9. 083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法

    083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法 本文知识点:构造方法-带参构造方法 说明:因为时间紧张, ...

  10. 082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法

    082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法 本文知识点:构造方法-无参构造方法 说明:因为时间紧张, ...

随机推荐

  1. 学习Spring框架等技术的方向、方法和动机

    学习Spring框架最早学习Spring框架是在大二的时候,当时看了几本书,看了一些视频,主要是传智播客的.更多的,还是写代码,单独写Spring的,也有与Struts和Hibernate等框架整合的 ...

  2. WEB 移动端 CSS3动画性能 优化

    很多时候,我们在开发移动端的时候要使自己的网页兼容不同的机型,很多时候会采用CSS3动画,但是很多时候在安卓机下,动画明显会出现卡顿,很难看,那么这里我介绍几个CSS 属性进行硬件加速那么就会得到明显 ...

  3. 清北学堂模拟赛d7t5 做实验

    题目描述有一天,你实验室的老板给你布置的这样一个实验.首先他拿出了两个长度为 n 的数列 a 和 b,其中每个 ai 以二进制表示一个集合.例如数字 5 = (101)2 表示集合 f1; 3g.第 ...

  4. CF #EDU R1 E

    最二的一次了~我开始以为是带有贪心的DP,谁知道想错了.后来才想明白,暴力二分+记忆化DP #include <iostream> #include <cstdio> #inc ...

  5. Corona 不同设备分辨率适应

    移动平台下,不同设备的宽高比不同,那么必然存在与游戏设计时的宽高比不一致的情况,Corona的解决方案是定义了一个虚拟的屏幕高宽,比如1024*768,然后在不同设备上通过定义的适应模式去调整这个虚拟 ...

  6. C语言编程入门——程序练习(上)

    大家能够敲写一下以下的练习代码.看下执行结果,都非常easy.关键要理解. if: # include <stdio.h> int main(void) { int i = 1; i = ...

  7. Single document interface和Multiple document interface

    https://en.wikipedia.org/wiki/Single_document_interface https://msdn.microsoft.com/en-us/library/b2k ...

  8. hdoj--3790--最短路径问题(双权值迪杰斯特拉)

     最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  9. B2321 [BeiJing2011集训]星器 数学&&物理

    这个题貌似特别奇怪,根本什么算法都想不出来,然而...看完题解之后,竟然用了能量守恒?惊了! 这里有一个题解: https://blog.csdn.net/Mima_Reincarnation/art ...

  10. B1060 [ZJOI2007]时态同步 dfs

    两遍dfs,第一遍有点像找重链,第二遍维护答案,每个点维护一个当前深度,然后就没啥了. ps:memset(lst,-1,sizeof(lst));这一句多余的话让我debug半天... 题干: De ...