Java学习IO篇
来吧,同志们,为复习网络编程做准备……
一.理论准备
流是个抽象的概念,是对输入输出设备的抽象,Java程序中,对于数据的输入/输出操作都是以“流”的方式进行,设备可以是文件、网络、内存等。流具有方向性,至于是输入流还是输出流则是一个相对的概念,一般以程序(小马哥说的是机器)为参考,如果数据的流向是程序至设备,我们成为输出流,反之我们称为输入流,可以将流想象成一个“水流管道”(很多资料都这么讲的),自然就出现了方向的概念。
流把I/O设备内部的具体操作给隐藏起来了。所有InputStream和Reader的派生类都有一个基本的,继承下来的,能读取单个或byte数组的read( )方法。
Java分为字节流(Stream结尾)和字符流(Reader、Write结尾),再分为输入流(InputStream、Reader)和输出流(OutputStream、Write),输入输出相对于内存而言。在读字符的时候用字符流,如文本文件、XML(我想xml明明是字母字符组成的,属于ASCII文件,为何不用stream读取呢?)等。在读二进制文件时候用字节流,如RAR、EXE等不是文本以外的文件(图片)。Buffered开头的流只是加了缓冲区,为了读写提高效率。字符流不能直接输出,需要转换成字节流才能输出(这个确实是刚知道的)!
Java 2 SDK中有三种基本类型的节点:文件(file)、内存(memory)、管道(pipe)。
下面来看郑莉教材上IO章节的那个经典图片。
继承自InputStream/OutputStream的流都是用于向程序中输入/输出数据,且数据的单位都是字节(byte=8bit),如图,深色的为节点流,浅色的为处理流。

继承自Reader/Writer的流都是用于向程序中输入/输出数据,且数据的单位都是字符(2byte=16bit),如图,深色的为节点流,浅色的为处理流。

二.用法分析
Java IO的一般使用原则(部分来自百度文库):
(1) 按数据来源(去向)分类:
- 是文件: FileInputStream, FileOutputStream, FileReader, FileWriter
- 是byte[]:ByteArrayInputStream, ByteArrayOutputStream
- 是Char[]: CharArrayReader, CharArrayWriter
- 是String: StringBufferInputStream, StringReader, StringWriter
- 网络数据流:InputStream, OutputStream, Reader, Writer
(2) 按是否格式化输出分:
要格式化输出:PrintStream, PrintWriter
(3) 按是否要缓冲分:
要缓冲:BufferedInputStream, BufferedOutputStream, BufferedReader, BufferedWriter。
(4) 按数据格式分:
- 二进制格式(只要不能确定是纯文本的): InputStream, OutputStream及其所有带Stream结束的子类
- 纯文本格式(含纯英文与汉字或其他编码方式);Reader, Writer及其所有带Reader, Writer的子类
(5) 按输入输出分:
输入:Reader, InputStream类型的子类;输出:Writer, OutputStream类型的子类
(6) 特殊需要:
- 从Stream到Reader,Writer的转换类:InputStreamReader, OutputStreamWriter
- 对象输入输出:ObjectInputStream, ObjectOutputStream
- 进程间通信:PipeInputStream, PipeOutputStream, PipeReader, PipeWriter
- 合并输入:SequenceInputStream
- 更特殊的需要:PushbackInputStream, PushbackReader, LineNumberInputStream, LineNumberReader
(7) 决定使用哪个类以及它的构造进程的一般准则如下(不考虑特殊需要):
考虑最原始的数据格式是什么:是否为文本?是输入还是输出?是否需要转换流:InputStreamReader, OutputStreamWriter?数据来源(去向)是什么:文件?内存?网络?是否要缓冲:bufferedReader (特别注明:一定要注意的是readLine()是否有定义,有什么比read, write更特殊的输入或输出方法)是否要格式化输出:print。
三.若干实例
还是寒假时候写的,权当复习了,折叠代码的插件找不到了,先看着吧。
1.System.in
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;/** System.in是InputStream static final的,包含了多态,叫同步式或者阻塞式* 读取ASCII和二进制文件(图片),而字母就是ASCII字符(个人理解)。*/public class TestSystemIn {public static void main(String[] args) {InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);//有readlineString s = null;try {s = br.readLine();while(s!=null) {if(s.equalsIgnoreCase("exit")) {break;}System.out.println(s.toUpperCase());s = br.readLine();}br.close();}catch (IOException e) {e.printStackTrace();}}}
2.buffer
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class TestBuffer {public static void main(String[] args) {try {//查看修改日就可以判断文件是否是新建的了BufferedWriter bw = new BufferedWriter(new FileWriter("d:/java.txt"));BufferedReader br = new BufferedReader(new FileReader("d:/java.txt"));String s = null;for(int i=1; i<100; i++) {s = String.valueOf(Math.random());bw.write(s);bw.newLine();//换行}//刷新该流的缓冲,br没有该方法bw.flush();while((s=br.readLine())!=null) {System.out.println(s);}bw.close();br.close();}catch (IOException e) {e.printStackTrace();}}}
3.FileInputStream
import java.io.*;public class TestFileInputStream {public static void main(String[] args) {FileInputStream in = null;try {in = new FileInputStream("e:/1.txt");}catch(FileNotFoundException e) {System.out.println("找不到文件");System.exit(-1);}//下面表示找到了文件int tag = 0;try {long num = 0;while((tag = in.read())!=-1) {//read是字节流,若是有汉字就显示不正常了,使用reader就解决了System.out.print((char)tag);num++;}in.close();System.out.println();System.out.println("共读取了" + num + "字符");}catch(IOException e1) {//read和close都会抛出IOExceptionSystem.out.println("文件读取错误");System.exit(-1);}}}
4.FileOutputStream实现复制功能
import java.io.*;/** 实现复制功能*/public class TestFileOutputStream {public static void main(String[] args) {int b = 0;FileInputStream in = null;FileOutputStream out = null;try {in = new FileInputStream("d:/java.txt");//下面的若是不存在的话会自动建立out = new FileOutputStream("d:/my_java.txt");while((b=in.read())!=-1) {out.write(b);}in.close();out.close();}catch(FileNotFoundException e) {System.out.println("找不到指定文件");System.exit(-1);}catch(IOException e1) {System.out.println("文件复制错误");System.exit(-1);}System.out.println("文件已复制");}}
5.ObjectOutputStream与Serializable
import java.io.*;/** transient(透明的),可以用来修饰成员变量,* 当进行序列化时不予考虑,修饰int 的话,不管原来的值是多少* 输出的就是0*/public class TestObjectIO {public static void main(String[] args) throws Exception {T t = new T();t.k = 8;FileOutputStream fos = new FileOutputStream("d:/1.txt");ObjectOutputStream oos = new ObjectOutputStream(fos);oos.writeObject(t);oos.flush();oos.close();FileInputStream fis = new FileInputStream("d:/1.txt");ObjectInputStream ois = new ObjectInputStream(fis);T tRead = (T)ois.readObject();System.out.println(tRead.i + " " + tRead.j + " " + tRead.k);}}class T implements Serializable {int i = 10;int j = 9;double d = 2.3;int k = 15;}
6.转换编码方式
import java.io.*;/** 中文windows默认GBK编码方式* 追加的内容显示为问号,不知道咋回事*/public class TestTransForm {public static void main(String[] args) {try {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d:/java.txt"));osw.write("你好123");//可以直接写入字符串,包括中文,因为外边的是字符流System.out.println("编码方式:" + osw.getEncoding());//ISO8859_1是西欧语言,又叫latin-1,此时未考虑东方人,国标(ISO)为Unicodeosw.close();osw = new OutputStreamWriter(new FileOutputStream("d:/java.txt",true),"ISO8859_1");//true表示追加osw.write("这是追加的内容");System.out.println("编码方式:" + osw.getEncoding());osw.close();}catch(IOException e) {e.printStackTrace();}}}
7.输出重定向
import java.io.*;/** Print流属于输出流,提供了重载的方法很多,* PrintWriter和PrintStream不会抛异常,用户通过检测错误状态获取信息,* 包含自动flush功能,有什么用呢,在jsp里也要输出一些东西,* 但不必每次抛异常。*/public class TestPrintStream {public static void main(String[] args) {PrintStream ps = null;try {FileOutputStream fos = new FileOutputStream("d:/java.txt");ps = new PrintStream(fos);}catch (IOException e) {e.printStackTrace();}if(ps!=null) {System.setOut(ps);//输出重定向}int ln = 0;for(char c=0; c<65535; c++) {System.out.print(c + " ");if(ln++>100) {System.out.println();ln = 0;}}}}
8.DataStream
import java.io.*;public class TestDataStream {public static void main(String[] args) {//先在内存里分配一个字节数组,再有一个 OutputStream,再加上一个数据流ByteArrayOutputStream baos = new ByteArrayOutputStream();DataOutputStream dos = new DataOutputStream(baos);try {//写出读入dos.writeDouble(Math.random());dos.writeBoolean(true);ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());System.out.println(bais.available());//共几个字节可用DataInputStream dis = new DataInputStream(bais);////先写的先读(队列),下面这两个输出不可以调换,否则就先输出了double里的一个字节System.out.println(dis.readDouble());System.out.println(dis.readBoolean());dos.close();dis.close();}catch (IOException e) {e.printStackTrace();}}}
四.小问题
为什么Writer/Reader不继承自Stream呢?字符最终也要转换成二进制呀。Writer/Readre继承OutputStream/InputStream,这样的继承层次不是更好,为什么要单独做一个呢,而且Stream也有些子类能够实现字符串的读写。大神回答:单一职责。太牵强了。
Java学习IO篇的更多相关文章
- 从.Net到Java学习第二篇——IDEA and start spring boot
从.Net到Java学习第一篇——开篇 所谓工欲善其事,必先利其器,做java开发也一样,在比较了目前最流行的几个java IDE(eclipse,myeclipse.IDEA)之后,我果断选择IDE ...
- 从.Net到Java学习第一篇——开篇
以前我常说,公司用什么技术我就学什么.可是对于java,我曾经一度以为“学java是不可能的,这辈子不可能学java的.”结果,一遇到公司转java,我就不得不跑路了,于是乎,回头一看N家公司交过社保 ...
- 从.Net到Java学习第九篇——SpringBoot下Thymeleaf
从.Net到Java学习系列目录 Thymeleaf概述 Thymeleaf 是一个流行的模板引擎,该模板引擎采用java语言开发.模板引擎是一个技术名称,是跨领域平台的概念,在java语言体系下有模 ...
- Java学习IO流第一天
今日内容介绍 字节流 字符流 1 字节流 在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据.现在我们就要开始给文件中写数据,或者读取文件中的数据. 1.1 字节输出流Ou ...
- java学习总结篇二--3 种简单排序
本篇文章,先从数据结构开始,一边总结,一边反思,寻求最优解. 本文简单温习下最基础的三类算法:选择,冒泡,插入.先定义一个交换数组作为备用: /** * 交换数组元素 * @param arr * @ ...
- java学习总结篇一--写在正式成为码农一年后
一直想写一写工作了一年多的总结与感悟,今天正好有时间,也有这个兴致,随手总结一下这一年来学习及工作的情况. 大学时很无奈地被选择了计算机专业,本人对计算机,不讨厌,也算不上多喜欢.只是当惯了好学生,好 ...
- Java学习---IO操作
基础知识 1.文件操作 Java语言统一将每个文件都视为一个顺序字节流.每个文件或者结束于一个文件结束标志,或者根据系统维护管理数据中所纪录的具体字节数来终止.当一个文件打开时,一个对象就被创建,同时 ...
- java 学习第一篇简单基础
Java基础 Java Java 和C#有着极为相似的语法. 和C#都是面向对象的高级程序语言. JAVA是一个开源,公开的语言,有着极其丰富的开源库和其他资源. JAVA分类 JAVA分SE EE ...
- Java学习第一篇:变量,数据类型,运算符,流程控制(简介)
一.安装和配置jdk 1.jdk是什么? (1).jdk全称是Java Development Kit, Java开发工具包; (2).jdk是sun公司开发的; (3).jdk主要包括:jre(Ja ...
随机推荐
- 第一个Xcode项目 - 代码修改布局约束
第一行的选中效果已经有了,那第二行的选中效果怎么做呢?我这里选择改变布局约束来实现选中效果 [我有个用object-c做APP的同事他说,我觉得这个应该去获取色块的位置,然后赋给选中用的View,然后 ...
- 谷歌google搜索打不开、谷歌gmail邮箱及相关服务无法登录的解决的方法
歌打不开 google打不开,与中国大陆封杀有关,可是主要是由于近期googleserver在全球范围内又一次进行了布局调整. 解决的方法是仅仅要改动用户本地计算机hosts文件就能够了. 一.Win ...
- C++之枚举
1. 声明枚举类型格式 enum Day{ Mon,Tue=5,Wed};//Mon=0;Tue=5;Wed=6 enumDay1{Mon1,Tue1,Wed1};//Mon1=0;Tue1=1;We ...
- 《Linux内核修炼之道》 系列
http://blog.csdn.net/fudan_abc/article/category/655796
- JDK1.5中线程池,定时器知识
package cn.it.pool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executo ...
- iOS开发-javaScript交互
前言 当前混合开发模式迎来了前所未有的发展,跨平台开发.热更新等优点决定了这种模式的重要地位.虽然前端界面在交互.动效等多方面距离原生应用还有差距,但毫无疑问混合开发只会被越来越多的公司接受.在iOS ...
- http协议通信原理的问答
1.dns怎么解析?答:假设一个网站www.tianyik.com的ip是192.168.31.36 浏览器(URL:www.tianyik.com)--> 客户机 h ...
- ueditor 添加微软雅黑字体 异常“从客户端中检测到有潜在危险的 request.form值”,解决
使用ueditor往数据库添加文本内容时,如果字体有css样式, <,>," 这些字符会导致报出异常信息:从客户端中检测到有潜在危险的 request.form值 因为这些字符有 ...
- query 防止ajax重复提交
项目用到js了,首选jquery,能用库用库,原则. 碰到重复提交的问题,禁止住才行.百度google,还是Google给力. 知乎上有个高人,总结了四种,利用Jquery .post方法返回jqXH ...
- 根据文件夹的GUid找到该文件夹
Guid guid = Guid.Parse(folderGuID); SPFolder folder = list.Folders[guid].Folder;