目录:

一、java流式输入/输出原理

二、java流类的分类

三、输入/输出流类

四、常见的节点流和处理流

五、文件流

六、缓冲流

七、数据流

八、转换流

九、Print流

十、Ubject流

一、java流式输入/输出原理

java中,对于数据的输入/输出操作以”流”(Stream)方式进行;JDK提供了各种各样的”流”类,用以获取不同类型的数据;程序中通过标准的方法输入或输出数据

二、java流类的分类

  • 按数据流的方向不同可以分为输入流和输出流
  • 按处理数据单位不同可以分为字节流和字符流
  • 按照功能不同可以分为节点流和处理流

jdk所提供的所有流类型位于包java.io内,分别继承自以下四种抽象流类型

  字节流 字符流
输入流 InputStream Reader
输出流 OutputStrean Writer

节点流:可以从一个特定的数据源(节点)读写数据(如:文件、内存)

处理流:是链接已存在的流(节点流或处理流)纸上,通过对数据的处理为程序提供更为强大的读写功能

三、输入/输出流类

1.InputStream

继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit);下图中神色为节点流,浅色为处理流

InputSream的基本方法:

//读取一个字节并以整数的形式返回(0-255),如果返回-1则已经到输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer,返回实际读取的字节数。如果读取前已经到输入流的末尾返回-1
int read(byte[] buffer) throws IOException
//读取length个字节,并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数,如果读取前已经到输入流的末尾返回-1
int read(byte[] buffer, int offset, int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException

2.OutputStream

继承自OutPutStream的流是用于程序输出数据,且数据的单位为字节(8bit);下图中神色为节点流,浅色为处理流

OutputStream的基本方法:

//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中还从的数据全部写入到目的地
void flush() throws IOException

3.Reader

继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit);下图中神色为节点流,浅色为处理流

Reader的基本方法:

//读取一个字符并以整数的形式返回(0-255),如果返回-1则已经到输入流的末尾
int read() throws IOException //读取一系列字符并存储到一个数组buffer,返回实际读取的字符数。如果读取前已经到输入流的末尾返回-1
int read(char[] buffer) throws IOException //读取length个字符,并存储到一个字符数组buffer,从length位置开始,返回实际读取的字符数,如果读取前已经到输入流的末尾返回-1
int read(char[] buffer, int offset, int length) throws IOException //关闭流释放内存资源
void close() throws IOException //跳过n个字符不读,返回实际跳过的字符数
long skip(long n) throws IOException

4.Writer

继承自writer的流都是用于程序中输出数据,且数据的单位为字符(16bit);下图中神色为节点流,浅色为处理流

Writer常用方法

//向输出流中写入一个字符数据,该字符数据为参数b的低16位
void write(int b) throws IOException //将一个字符类型的数组中的数据写入输出流
void write(char[] b) throws IOException //将一个字符型的数组中的从指定位置(off)开始的len个字符写入到输出流
void write(char[] b, int off, int len) throws IOException //将一个字符串中的字符写入到输出流
void wrete(String string) throws IOException //将一个字符串从offset开始的length个字符写入到输出流
void write(String string, int offset, int length) throws IOException //关闭流释放内存资源
void close() throws IOException //将输出流中还从的数据全部写入到目的地
void flush() throws IOException

四、常见的节点流和处理流

1.节点流类型:

2.处理流类型:

五、文件流

FileInputStream和FileOutputStream分别继承自InputStream和OutputStream用于向文件中输入和输出字节

FileInputStream和FileOutputStream常用构造方法:

FileInputStream(String name) throws FileNotFoundException
FileInputStream(File file) throws FileNotFoundException
FileOutputStream(String name) throws FileNotFoundException
FileOutputStream(File file) throws FileNotFoundException
FileOutputStream(File file,boolean append) throws FileNotFoundException

FileInputStream和FileOutputStream类支持其父类InputStream和OutputStream所提供的数据读写方法。

注意:

  • 在实例化FileInputStream和FileOutputStraeam流时要用try-catch语句来处理其可能抛出的FileNotFoundException
  • 在读写数据时也要用try-catch语句来处理可能抛出IOException
  • FileNotFoundException是IOException的子类

FileInputStream:

public class Test{
public static void main(String[] args) { int b = 0 ;
FileInputStream in = null;
//打开文件
try {
in = new FileInputStream("F:\\test.txt");//windows下路径分隔符是两个反斜杠,也可以直接使用正斜杠
} catch (FileNotFoundException e) {
System.out.println("找不到指定文件");
System.exit(-1);
}
//读取文件
try {
long num = 0;
while((b = in.read()) != -1) {
System.out.print((char)b);
num++;
}
in.close();
System.out.println();
System.out.print("共读取了 "+ num +" 个字节");
} catch (IOException e1) {
System.out.println("文件读取错误");
System.exit(-1);
} }
}

FileOutputStream:

public class Test{
public static void main(String[] args) { int b = 0 ;
FileInputStream in = null;
FileOutputStream out = null;
//打开文件
try {
in = new FileInputStream("F:\\test.txt");//windows下路径分隔符是两个反斜杠,也可以直接使用正斜杠
out = new FileOutputStream("F:/test1.txt");//如果目录下没有这个文件FileOutputStream会自动生成一个
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.print("复制成功");
}
}

FileReader:

public class Test{
public static void main(String[] args) { FileReader fr = null;
int c = 0;
try {
fr = new FileReader("f:/test.txt");
int in = 0;
while ((c = fr.read()) != -1) {
System.out.print((char)c);
}
} catch (FileNotFoundException e) {
System.out.print("找不到指定文件");
} catch (IOException e1) {
System.out.print("文件读取错误");
} }
}

FileWriter:

public class Test{
public static void main(String[] args) { FileReader fr = null;
FileWriter wr = null;
int c = 0;
try {
fr = new FileReader("f:/test.txt");
wr = new FileWriter("f:/test1.txt");
int in = 0;
while ((c = fr.read()) != -1) {
wr.write(c);
}
wr.close();
fr.close();
} catch (FileNotFoundException e) {
System.out.print("找不到指定文件");
} catch (IOException e1) {
System.out.print("文件写入错误");
}
}
}

六、缓冲流

缓冲流要”套接”在相应的节点流纸上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法

JDK提供了四种缓冲流,其常用的构造方法为:

BufferedReader(Reader in)
BufferedReader(Reader in,int sz)//sz为自定义缓冲区的大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int sz)
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int sz)
  • 缓冲流输入支持其父类的mark和reset方法
  • BufferedReader提供了readLine方法用于读取一行字符串(以\r 或\n分割)
  • BufferedWriter提供了newLine用于写入一个行分隔符
  • 对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会使内存中的数据立刻写出

BufferStream1:

public class Test{
public static void main(String[] args) { try {
FileInputStream fis = new FileInputStream("f:/test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);//相当于管道套管道,为了使用缓冲区的功能
int c = 0;
System.out.println((char)bis.read());
System.out.println((char)bis.read()); bis.mark(100);//从100个开始往外读
for(int i=0; i<10 && (c=bis.read()) != -1; i++) {
System.out.print((char)c + " ");
}
System.out.println();
bis.reset();//回到100的那个点上
for(int i=0; i<=10 && (c=bis.read()) != -1; i++) {
System.out.print((char)c + " ");
}
bis.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}

BufferStream2:

public class Test{
public static void main(String[] args) { try {
BufferedWriter bw = new BufferedWriter(new FileWriter("f:/test.txt"));//管道套接
BufferedReader br = new BufferedReader(new FileReader("f:/test.txt"));
//写入
String s = null;
for(int i=1; i<100; i++) {
s = String.valueOf(Math.random());//产生一个字符串的随机数
bw.write(s);//写一个字符串到缓冲区
bw.newLine();//写一个换行到缓冲区
}
bw.flush();//将缓存内存中的数据写出
//逐行读取
while((s=br.readLine()) != null) {
System.out.println(s);
} bw.close();
br.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}

七、数据流

  • DataInputStream和DataOutPutStream分别继承自InputStream和OutPutStream,它属于处理流,需要分别”套接”在InputStream和OutputStream类型的节点流上
  • DataInputStream和DataOutputStream提供了可以存取与机器无关的java原始类型数据(如:int,double等)的方法
  • DataInputStream和DataOutputStream的构造方法为:
DataInputStream(InputStream in)
DataOutputStream(OutputStream out)

看一个例子:

public class Test{
public static void main(String[] args) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();//在内存中分配字节数组
DataOutputStream dos = new DataOutputStream(baos);//套接 try {
dos.writeDouble(Math.random());//写一个double类型的随机数,double是8个字节
dos.writeBoolean(true);//写一个布尔值进去,布尔值在内存中只占一个字节
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//读数据,只能一个字节一个字节读
System.out.println(bais.available());//输出字节数 DataInputStream dis = new DataInputStream(bais);//套接
System.out.println(dis.readDouble());//输出数据1,注意,先写的先读
System.out.println(dis.readBoolean());//输出数据2
dos.close();
dis.close(); } catch(IOException e) {
e.printStackTrace();
}
}
}

八、转换流

  • InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
  • InputStreamReader需要和InputStream”套接”
  • OutputStreamWriter需要和OutputStream”套接”
  • 转换流在构造时可以指定其编码集合,例如:InputStream isr = new InputStreamReader(System.in, “ISO8859_1”)

OutputStreamWriter:

public class Test{
public static void main(String[] args) { try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("f:/test.txt"));
osw.write("aaa");
System.out.println(osw.getEncoding()); //获取osw的字符编码
osw.close();
//true表示在原文件的基础上追加,如果不加true,则会删除原文件的内容后再写入新的内容,ISO8859_1是一种字符编码,指定了要写入内容的编码格式
osw = new OutputStreamWriter(new FileOutputStream("f:/test.txt", true), "ISO8859_1");
osw.write("bbb");
System.out.println(osw.getEncoding());
osw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

InputStreamReader:

/*
* 这个程序相当于一直逐行读取键盘输入,直到输入exit为止,这是一种阻塞式的方法,程序运行起来后不输入exit程序就一直停在那,也可以理解为是同步式的
*/ public class Test{
public static void main(String[] args) {
InputStreamReader isr = new InputStreamReader(System.in);//System.in是接收的键盘输入
BufferedReader br = new BufferedReader(isr);
String s = null; try {
s = br.readLine();
//除非s="exit"否则就不停的读
while(s != null) {
if(s.equalsIgnoreCase("exit")) {
break;
} else {
System.out.println(s.toUpperCase());
s = br.readLine();
}
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

九、Print流

  • PrintWriter和PrintStream都属于输出流,分别针对与字符和字节
  • PrintWriter和PrintStream提供了重载的print
  • Println方法用于多种数据类型的输出
  • PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriter和PrintStream有子的佛那个flush功能
PrintWriter(Writer out)
PrinWriter(Writer out,boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(PutputStream out, boolean autoFlush)
PrintStream(OutputStream out)
PrintStream(OutputStream out, boolean autoFlush)

例子1:

public class Test{
public static void main(String[] args) {
PrintStream ps = null; try {
FileOutputStream fos = new FileOutputStream("f:/test.txt");
ps = new PrintStream(fos);//套接
} catch(IOException e) {
e.printStackTrace();
} if(ps != null) {
System.setOut(ps);//更改默认输出位置为ps,System.out默认指向的是控制台
} int ln = 0;
for(char c=0; c<=60000; c++) {
System.out.print(c+" ");
if(ln++ >= 100) {
System.out.println();
ln = 0;
}
}
}
}

例子2:

public class Test{
public static void main(String[] args) {
String filename = args[0];//外部传参
if(filename != null) {
list(filename,System.out);
}
}
public static void list(String f,PrintStream fs){
try {
BufferedReader br = new BufferedReader(new FileReader(f));
String s = null;
//按行读取
while((s=br.readLine()) != null) {
fs.println(s);
}
br.close();
} catch(IOException e) {
fs.println("无法读取文件");
}
}
}

例子3:

public class Test{
public static void main(String[] args) {
String s = null;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//System.in是键盘输入 try {
FileWriter fw = new FileWriter("f:/test.txt",true);//true追加在原文件后面
PrintWriter log = new PrintWriter(fw); while((s=br.readLine()) != null){
if(s.equalsIgnoreCase("exit")){
break;//如果键盘输入exit则停止运行
} System.out.println(s.toUpperCase());//控制台输出
log.println("----");
log.println(s.toUpperCase());//写入
log.flush();
}
log.println("==="+new Date()+"===");//new Date()指的是util里的date,也就是当前时间
log.flush();
log.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}

十、Ubject流

作用:直接将Object写入或读出

  • transient关键字
  • serializable接口      标记类里的对象可以序列化
  • externalizable接口    控制类的对象是怎么写出去的,也就是说可以自己控制序列化过程

看一个例子:

class T implements Serializable{//如果要写入或者读对象必须要实现Serializable接口,这是一个标记接口,所以不需要重写方法
int i = 0;
int j = 9;
double d = 2.3;
int k = 0;
}
public class Test{
public static void main(String[] args) throws Exception{
T t = new T();
t.k = 8;
FileOutputStream fos = new FileOutputStream("f:/test.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(t);//把t对象写入f:/test.txt
oos.flush();
oos.close(); FileInputStream fis = new FileInputStream("f:/test.txt");
ObjectInputStream ois = new ObjectInputStream(fis); T tReaded = (T)ois.readObject();//读对象
System.out.println(tReaded.i+" "+tReaded.j+" "+tReaded.d+" "+tReaded.k);
}
}

上面例子中的输出结果为:0    9    2.3    8

如果将T里的 int k = 0; 改为 transient int k = 0;

则输出结果应该是0    9    2.3    0

因为transient相当于把k变成了透明的,使用transient修饰的成员变量在序列化(操作对象)的时候不予考虑

十、java_IO的更多相关文章

  1. Java_io体系之BufferedWriter、BufferedReader简介、走进源码及示例——16

    Java_io体系之BufferedWriter.BufferedReader简介.走进源码及示例——16 一:BufferedWriter 1.类功能简介: BufferedWriter.缓存字符输 ...

  2. 前端开发中SEO的十二条总结

    一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...

  3. 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  4. 如何一步一步用DDD设计一个电商网站(十)—— 一个完整的购物车

     阅读目录 前言 回顾 梳理 实现 结语 一.前言 之前的文章中已经涉及到了购买商品加入购物车,购物车内购物项的金额计算等功能.本篇准备把剩下的购物车的基本概念一次处理完. 二.回顾 在动手之前我对之 ...

  5. CSS十问——好奇心+刨根问底=CSSer

    最近有时间,想把酝酿的几篇博客都写出来,今天前端小学生带着10个问题,跟大家分享一下学习CSS的一些体会,我觉得想学好CSS,必须保持一颗好奇心和刨根问底的劲头,而不是复制粘贴,得过且过.本人能力有限 ...

  6. WCF学习之旅—第三个示例之四(三十)

           上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九)   ...

  7. 谈谈一些有趣的CSS题目(十)-- 结构性伪类选择器

    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...

  8. CRL快速开发框架系列教程十二(MongoDB支持)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  9. CRL快速开发框架系列教程十(导出对象结构)

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

随机推荐

  1. linux-shell-引用-命令替换-命令退出状态-逻辑操作符

    命令替换:bash7步扩展的之一 嵌套  这里没什么意义 退出状态可以参与逻辑判断 表达式 算数表达式和条件表达式,逻辑表达式 查看passwd命令比,避免用户捕获输入密码的接口 这种方式就可以直接输 ...

  2. 个人博客作业-Week2 (代码规范, 代码复审)

    代码规范: 1.这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西. 编码规范它包含了代码格式,还包括了编码风格和其他规范,通常涉及:缩进.空格使用.Tab使用 注释. ...

  3. M2事后总结

    照片     设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? "北航"Clubs旨在于解决北航校内社团管理与学生参与社团活动的困难的 ...

  4. Java提高篇(1)封装

    三大特性之---封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能 ...

  5. 关于EA和ED的区别

    在申请美国大学本科的过程中,申请的截止时间往往分为两轮:提前申请(Early Decision/Action) 和常规申请 (Regular Decision).提前申请,顾名思义,截止时间会相对早一 ...

  6. jstack 使用一例

    31jstack -m -F 2340 >libra.log 2>&1 jstack -m -F 2340 >libra2.log 2&>1 jstack -m ...

  7. HTML 5 placeHolder

    <html> <body> <input type="text" id="idNum" placeholder="pla ...

  8. jquery的extend方法(源码解析)

    1.前段时间一直忙于研究数据可视化(d3.js,three.js) 以及 php的 laravel框架,生活上也遇到很多事情,这大概就是人生中的迷茫期吧. 回想起,刚出来工作的时候,目标很明确,要学习 ...

  9. 项目引入android-support-v7-appcompat遇到的问题,no resource found that matches the given name 'android:Theme.AppCompat.Light'

    一.问题 今天准备使用v7包中的ToolBar来用,但是在styles.xml中引入Theme.AppCompat.Light的时候,报错“no resource found that matches ...

  10. centos 7 修改系统屏幕分辨率

    centos 7 修改系统屏幕分辨率,命令方式和图形方式的修改方法. 命令:xrandr 通过命令 xrandr 修改系统的分辨率,输入xrandr: bash [admin@localhost ~] ...