01--Java IO基础
一、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基础的更多相关文章
- java IO基础操作
java IO基础,通熟易懂,好久没复习java 基础了.这里是传送门... http://www.cnblogs.com/nerxious/archive/2012/12/15/2818848.ht ...
- 归纳从文件中读取数据的六种方法-JAVA IO基础总结第2篇
在上一篇文章中,我为大家介绍了<5种创建文件并写入文件数据的方法>,本节我们为大家来介绍6种从文件中读取数据的方法. 另外为了方便大家理解,我为这一篇文章录制了对应的视频:总结java从文 ...
- 总结java创建文件夹的4种方法及其优缺点-JAVA IO基础总结第三篇
本文是Java IO总结系列篇的第3篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- 总结删除文件或文件夹的7种方法-JAVA IO基础总结第4篇
本文是Java IO总结系列篇的第4篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- 086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结
086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结 本文知识点:面向对象基础(类和对象)总结 说明 ...
- 085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用
085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用 本文知识点:构造方法调用 说明:因为时间紧张,本人写博客过程中只是 ...
- 084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字
084 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 03 构造方法-this关键字 本文知识点:构造方法-this关键字 说明:因为时间紧 ...
- 083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法
083 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 02 构造方法-带参构造方法 本文知识点:构造方法-带参构造方法 说明:因为时间紧张, ...
- 082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法
082 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 01 构造方法-无参构造方法 本文知识点:构造方法-无参构造方法 说明:因为时间紧张, ...
随机推荐
- uva340 Master-Mind Hints (UVA - 340)
题目简要 题目意思很简单每个测试都由原题目在第一行,然后后面的都是去猜的答案,如果猜测的位置正确那么输出的结果的数对里面的第一个数就加一,如果仅答案正确(原题目里有这个数,但是位置不一样)那么就在输出 ...
- python爬虫15 | 害羞,用多线程秒爬那些万恶的妹纸们,纸巾呢?
有时候 只是在人群中多看了一眼 就再也没办法忘掉那些容颜 小帅b在普通的一天 上着普通的网 不小心打开了一个不太普通的网站 https://www.mzitu.com/ 从此进入了不普通的一天 看着不 ...
- 【codeforces 509E】Pretty Song
[题目链接]:http://codeforces.com/contest/509/problem/E [题意] 让你计算一个字符串的所有子串里面元音字母出现的频率的和; [题解] 先处理出前缀和-&g ...
- BUPT2017 springtraining(16) #4 ——基础数论
题目在这里 A.手动打表找规律得组合数 n -= 2, m -= 2, ans = C(n, m) #include <bits/stdc++.h> using namespace std ...
- P1464 Function 洛谷
https://www.luogu.org/problem/show?pid=1464 题目描述 对于一个递归函数w(a,b,c) 如果a<=0 or b<=0 or c<=0就返回 ...
- 利用Calendar类测试电脑运行速度
今天学习了很多新知识! 这里使用了Calender类来获取系统时间,并计算循环1w次的时间,判断电脑处理时间. import java.util.Calendar; public class Arra ...
- ZooKeeper可视化Web管理工具收集(待实践)
原来ZooKeeper是有Web管理后台的.但是仅限于操作ZooKeeper的数据,如果要监控性能,估计要借助Nagios去配合. 这些工具应该ZK UI最好用,下面是收集的一些工具安装教程: htt ...
- GTK经常使用控件之行编辑( GtkEntry )
行编辑,仅仅同意输入一行内容的控件.如password输入框. 行编辑的创建: GtkWidget *gtk_entry_new(void); 返回值:行编辑指针 设置行编辑内容的最大长度: void ...
- C# 读取ini文件 百度问问学习文档
C# 读取ini文件 10 有多个section,现想读取整个ini文件和指定section下所有内容 补充: 发布答案可以,请对准题目啊,我不要指定节点的内容,我知道!我要的是读取指定区域的内容,假 ...
- 生活的 tricks
1. 远距离传递 传真(需要附近有传真机):发 QQ.微信拍照,自己打印: 2. 超市的设计 如果是两层的话,入口一定在第一楼,出口在第二楼,也即当你需要出去的时候,需要贯穿整个超市: 用的在第一楼: ...