目录:

一、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. 【2016.3.19】作业 分析一个很有(wu)趣(liao)的小程序

    问题1:这个程序要找的是符合什么条件的数? 能够整除2-32中所有数仅除了在此之中的两个相邻的数,比如能整除2-29,且不能整除30,31.当然,这只是举个例子. 问题2:这样的数存在么?符合这一条件 ...

  2. 12.26daily_scrum

    尽管最近是众多大作业集中爆发deadline的紧要关头,队员们依旧热情高涨,投入良多,纷纷为产品发布出谋划策. 具体工作: 小组成员 今日任务 工作时间 李睿琦 软件调试过程总结 2 左少辉 滑锁密码 ...

  3. 2017-2018-2 1723《程序设计与数据结构》第八周作业 & 实验二 & 第一周结对编程 总结

    作业地址 第八周作业:https://edu.cnblogs.com/campus/besti/CS-IMIS-1723/homework/1847 (作业界面已评分,可随时查看,如果对自己的评分有意 ...

  4. guthub第一次作业连接及心得体会

    https://github.com/12wangmin/ GitHub的本意是旨在成为一种开放的软件协作平台,但它目前已成为一个巨大的综合性的平台,其作用远远超过单纯地开源代码.它现在在艺术家.建筑 ...

  5. 使用YII框架的migrate迁移数据库

    框架版本:2.0.13 官网手册说明:http://www.yiichina.com/doc/guide/2.0/db-migrations 创建迁移 命令的格式: php yii migrate/c ...

  6. [转]curl的详细使用

    转自:http://www.cnblogs.com/gbyukg/p/3326825.html 下载单个文件,默认将输出打印到标准输出中(STDOUT)中 curl http://www.centos ...

  7. Java之map使用方法

    package basic; import java.util.HashMap; import java.util.Map; //map使用方法 public class MapDemo { publ ...

  8. JSON:如果你愿意一层一层剥开我的心,你会发现...这里水很深——深入理解JSON

    我们先来看一个JS中常见的JS对象序列化成JSON字符串的问题,请问,以下JS对象通过JSON.stringify后的字符串是怎样的?先不要急着复制粘贴到控制台,先自己打开一个代码编辑器或者纸,写写看 ...

  9. bzoj 2212 : [Poi2011]Tree Rotations (线段树合并)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2212 思路:用线段树合并求出交换左右儿子之前之后逆序对的数量,如果数量变小则交换. 实现 ...

  10. Java11实战:模块化的 Netty RPC 服务项目

    Java11实战:模块化的 Netty RPC 服务项目 作者:枫叶lhz链接:https://www.jianshu.com/p/19b81178d8c1來源:简书简书著作权归作者所有,任何形式的转 ...