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 构造方法-无参构造方法 本文知识点:构造方法-无参构造方法 说明:因为时间紧张, ...
随机推荐
- Chat Group gym101775A(逆元,组合数)
传送门:Chat Group(gym101775A) 题意:一个宿舍中又n个人,最少k(k >= 3)个人就可以建一个讨论组,问最多可以建多少个不同的讨论组. 思路:求组合数的和,因为涉及除法取 ...
- B树、B+树
when ? why ? how ? what ? 平衡二叉树其查找的时间复杂度是 O(log2N)与树的深度相关,那么降低树的深度自然会提高查找效率. 如果我们要操作的数据集非常大,大到内存已经没法 ...
- 弹层蒙版(mask),ios滚动穿透,我们项目的解决方案
问题描述 项目开发遇到一个ios独有的问题,在wkwebview中稳定复现 问题: 弹出一个蒙版,当在蒙版上面滑动的时候蒙版后面的内容滚动了 这当然是ios的bug,但是经过我们测试iphone7也会 ...
- Python那点事
目录 Python那点事 一. Python介绍 二. 目前python的主要领域 三.Python的运用 四. Python的发展史 Python的种类 Python那点事 相信很多小伙伴会跳过此环 ...
- Java Web项目实战第1篇之环境搭建
写在前面的话 从今天开始一个Java Web实战项目,参考自 http://blog.csdn.net/eson_15/article/details/51277324 这个博客(非常感谢博主的分享精 ...
- HDU 5239 上海大都会 D题(线段树+数论)
打表,发现规律是存在一定次数(较小)后,会出现a=(a*a)%p.可以明显地发现本题与线段树有关.设置标记flag,记录本段内的数是否均已a=a*a%p.若是,则不需更新,否则更新有叶子结点,再pus ...
- 【cocos2d-x 3.7 飞机大战】 决战南海I (十) 游戏主场景
主场景要包括其它类的头文件 #include "cocos2d.h" #include "MyPlane.h" #include "Bullet.h& ...
- 设计模式学习–Decorator
What Decorator:动态地给一个对象加入一些额外的职责. 就添加功能来说.Decorator模式相比生成子类更加灵活. Why Decorator模式适用于能够动态的给对象增删职责.比方qq ...
- 一个伟大的发现,装X一下。笔记本win7系统64位机器执行unity 时,屏幕模糊解决的方法
笔者笔记本win7系统64位机器执行unity 时.往往切换时unity界面屏幕模糊,后来发现此时须要下载DirectXRuntimes201006x64,安装就可以.
- jabberNet 发送出席信息
没代码我说个J8: public void Presence(User.EStatus status) { string statustxt = ""; //说明文字.比如,离开的 ...