一、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. Linux系统学习之 一:新手必须掌握的Linux命令1

    2018-10-03 16:04:12 一.常用系统工作命令 1.wget 命令 作用:用于在终端中下载网络文件. 格式:wget [参数] 下载地址 参数及作用: -b : 后台下载模式 -d:显示 ...

  2. PAT 1115 Counting Nodes in a BST

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  3. 初识 Dubbo

    Dubbo 官网架构图 0:服务容器负责启动,加载运行服务提供者 1:服务提供者在启动时,向注册中心注册自己提供的服务 2:服务消费者在启动时,想注册中心订阅自己所需的服务 3:注册中心返回服务提供者 ...

  4. 申请SSL证书怎样验证域名所有权

    申请域名型证书时,系统将提供以下三种方式验证域名的所有权,请根据自己的实际情况选择其中一种进行域名验证: 1.管理员邮箱验证 系统会向你选择的管理员邮箱 发送验证邮件,能够收到验证邮件,并点击邮件中验 ...

  5. Wizard's Tour

    F. Wizard's Tour time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  6. noip模拟赛 黑骑士

    题目描述江爷爷给你出了一道题:给你一个图,保证每个点最多属于一个简单环,每个点度数最多为3,求这个图有多少“眼镜图形个数”保证图联通哦~其中“眼镜图形个数”,定义为三元组(x,y,S),其中x和y表示 ...

  7. PatentTips - DMA address translation between peer-to-peer IO devices

    BACKGROUND As processing resources have increased, demands to run multiple software programs and ope ...

  8. C/C++中的64位整数

    C/C++中的64位整数(__int64 and long long) 在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常常显得太小了:其中long 和 int 范围是[-2^31, ...

  9. hdu_1039_Easier Done Than Said_201311051511

    Easier Done Than Said? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/O ...

  10. 使用Visual Studio Code调试Electron主进程

    1.打开VS Code,使用文件->打开,打开程序目录 2.切换到调试选项卡 3.打开launch.json配置文件 4.在“附加到进程”节点上增加localhost配置 5.使用命令行启动el ...