java什么是输出流_Java输入输出流

相关概念

流的概念:

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。流的源端和目的端可简单地看成是数据的生产者和消费者,对输入流,可不必关心它的源端是什么,只要简单地从流中读数据,而对输出流,也可不知道它的目的端,只是简单地往流中写数据。

流的划分:

按照流向划分数据流可分为输入流和输出流。

输入流:从磁盘,光盘,网络,键盘输入数据到内存。io包中的输入流都继承自InputStream或Reader。

输出流:从内存输出数据到磁盘,磁带,显示器等地。io包中的输出流都继承自OutputStream或Writer。

按照数据组织形式划分数据流可分为字节流和字符流。

字节流:byte为数据的最小单位。io包中的输入流都继承自InputStream或OutputStream。

字符流:char为数据的最小单位。io包中的输入流都继承自Reader或Writer。

按照功能划分数据流可分为低级流(节点流)和高级流(处理流)。

低级流(节点流):节点流是可以直接从/向一个特定的数据源(例如磁盘、内存、网络)读/写数据的流。

高级流(处理流):高级流不可直接从数据源读/写数据,而是连接在已存在的流(可以是低级流或高级流)之上,为流添加额外的扩展功能。

输入输出流总体划分

31c4eb9741dc155d1d40fec85f9a5b06.png

字节流分类及其作用

c0af4d5ffe096c3bc3437dd7eecc3a49.png

字符流分类及其作用

56c12f6450c3c4d699876b38f765d4bf.png

通用API(黑体为常用API)

OutputStream

public abstract void write(int b)              //向输出流写入单个字节

public void write(byte[] data)          //将字节数组data中数据写入到输出流中

public void write(byte[] data, int offset, int length)     //将字节数组data中“offset开始,共length长“的数据写入到输出流中

public void flush()        //刷新该输出流,强制数据写入到输出流

void close()     //关闭输出流并释放与该流关联的所有系统资源

InputStream

int available()      //可以不受阻塞地从此输入流读取(或跳过)的估计字节数

void close()     //关闭此输入流并释放与该流关联的所有系统资源

void mark(int readlimit)     //在此输入流中标记当前的位置,如果读取字节数超过readlimit,则不标记任何字节

boolean markSupported()     //测试此输入流是否支持 mark 和 reset 方法

abstract int read()     //从输入流中读取数据的下一个字节

int read(byte[] b)     //从输入流中读取一定数量的字节,并将其存储在字节数组 b 中

int read(byte[] b, int off, int len)     //将输入流中从"off开始的最多 len字节数据"读入 byte 数组

void reset()     //将此流重新定位到最后一次对此输入流调用 mark 方法时的位置

long skip(long n)     //跳过和丢弃此输入流中数据的 n 个字节

Reader

abstract  void  close()   //关闭该流并释放与之关联的所有资源

void  mark(int readAheadLimit)     //标记流中的当前位置

boolean  markSupported()     //判断此流是否支持 mark() 操作

int  read()     //读取单个字符

int  read(char[] cbuf)     //将字符读入数组

abstract  int  read(char[] cbuf, int off, int len)     //将字符读入数组的“offset开始,共length长”的部分

int  read(CharBuffer target)     //试图将字符读入指定的字符缓冲区

boolean  ready()     //判断是否准备读取此流

void  reset()     //将此流重新定位到最后一次对此输入流调用 mark 方法时的位置

long  skip(long n)     //跳过个字符

Writer

Writer  append(char c)     //将单个字符添加到输出流                追加模式

Writer  append(CharSequence csq)     //将指定字符序列添加到输出

Writer  append(CharSequence csq, int start, int end)     //将指定字符序列的子序列添加到输出流

abstract  void  close()     //关闭此流

abstract  void  flush()     //刷新该流的缓冲

void  write(char[] cbuf)     //写入字符数组

abstract  void  write(char[] cbuf, int off, int len)     //写入字符数组的某一部分

void  write(int c)     //写入单个字符

void  write(String str)     //写入字符串

void  write(String str, int off, int len)     //写入字符串的某一部分

部分流的特点

ByteArrayOutputStream:写入ByteArrayOutputStream的数据被写入到一个byte数组,缓冲区会随着数据的不断写入而自动增长;可使用toByteArray()和toString()获取数据;无法关闭,调用close方法仍然可以之后向该流写入数据。(ByteArrayInputStream类似)

public static void main(String args[]) throwsIOException {

ByteArrayOutputStream baos= new ByteArrayOutputStream(1); //缓冲区长度为4

baos.write("helloworld".getBytes()); //可写入超过1字节数据

byte b[] =baos.toByteArray();

String str= baos.toString(); //toByteArray和toString方法

baos.close(); //尝试关闭

baos.write("!".getBytes()); //仍可写入

baos.writeTo(System.out); //写到特定输出流中//结果:helloworld!

}

FileoutputStream:用于向文件进行写入操作,getFD方法可获取文件描述符,getChannel方法可获取文件通道。

FileOutputStream fos = new FileOutputStream("fa.txt");

FileChannel fc=fos.getChannel();

FileDescriptor fd= fos.getFD();

ObjectOutputStream:组合ObjectInputStream来进行对基本数据或者对象的持久存储。

PipedOutputStream:和PipedInputStream一起使用,能实现多线程间的管道通信。

DataOutputStream:装饰其他的输出流,允许应用程序以与机器无关方式向底层写入基本Java数据类型。(DataInputStream类似效果)

DataOutputStream dos = new DataOutputStream(newByteArrayOutputStream());

dos.writeDouble(3.14); //写入double类型

dos.writeBoolean(true); //写入布尔类型

dos.writeChar(97); //写入char类型

BufferedOutputStream:为另一个输出流添加缓冲功能,BufferedInputStream类似效果。

PrintStream:装饰其他输出流,为其他输出流添加功能,方便的打印各种数据值。

ByteArrayOutputStream baos = newByteArrayOutputStream();

PrintStream ps= newPrintStream(baos);

ps.format("%-3.2f",3.1415926);

baos.writeTo(System.out);//结果:3.14

PushbackInputStream:允许从流中读取数据,然后在需要时推回该流。

byte[] b = "heo".getBytes();

PushbackInputStream pis= new PushbackInputStream(newByteArrayInputStream(b),3); //回推缓存三字节

byte[] bb = new byte[5];

pis.read(bb,0,2); //将b中数据he读入输入流中

pis.unread("ll".getBytes()); //将ll放入回推缓存

pis.read(bb,2,3); //读取回推缓存数据后再读取b中数据

System.out.println(newString(bb));//结果//hello

OutputStreamWriter:从字符流到字节流的桥接,自动将要写入流中的字符编码成字节。

ByteArrayOutputStream baos = newByteArrayOutputStream();

OutputStreamWriter osw= new OutputStreamWriter(baos,"utf-8"); //指定编码

osw.write("Sakura\n");

osw.write("最好了");

osw.flush();

baos.writeTo(System.out);//结果//Sakura//最好了

各种流的使用场景

一,数据输入还是输出

1)输入:使用Reader、InputStream 类型的子类。

2)输出:使用Writer、OutputStream 类型的子类。

二,数据格式

1) 二进制格式:使用InputStream、OutputStream 及其所有带 Stream结尾的子类。

2)纯文本格式:使用Reader、Writer 及其所有带 Reader、Writer 的子类。

三,数据源

1) 文件:字节流使用FileInputStream和FileOutputStream;对于字符流使用FileReader和 FileWriter。

2) 字节数组:则使用ByteArrayInputStream和ByteArrayOutputStream。

3) 字符数组:则使用CharArrayReader和CharArrayWriter。

4) String对象:字节流使用StringBufferInputStream和StringBufferOuputStream;字符流使用StringReader和StringWriter。

六、特殊需要

1) 转换流:InputStreamReader、OutputStreamWriter。

2) 对象输入输出:ObjectInputStream、ObjectOutputStream。

3)线程间通信:PipeInputStream、PipeOutputStream、PipeReader、PipeWriter。

4)合并输入:SequenceInputStream。

5)格式化输出,则使用PrintStream或PrintWriter。

6)更特殊的需要:PushbackInputStream、PushbackReader、LineNumberInputStream、LineNumberReader。

七、缓冲

字节流使用BufferedInputStream和BufferedOutputStream;字节流使用BufferedReader和BufferedWriter。

一个实例

复制文件夹的类

import java.io.*;public classTest{public static voidmain(String[] args) {

copyClass cc= new copyClass("src\\old","src\\new");try{long start =System.currentTimeMillis();

cc.copyDir(cc.getSource(),cc.getDestination(),false);long end =System.currentTimeMillis();

System.out.println(end-start);

}catch(IOException e){

e.printStackTrace();

}

}

}classcopyClass{privateFile source;privateFile destination;

copyClass(String source, String destination){this.source = newFile(source);this.destination = newFile(destination);

}void copyContent(File source,File destination,boolean byByte) throwsIOException {if(byByte){ //字节数组复制

BufferedInputStream bis = new BufferedInputStream(newFileInputStream(source));

BufferedOutputStream bos= new BufferedOutputStream(newFileOutputStream(destination));byte[] b = new byte[1024];while (bis.available()!= 0){

bis.read(b);

bos.write(b);

bos.flush();

}

bis.close();

bos.close();

}else { //单个字节复制

FileInputStream fis = newFileInputStream(source);

FileOutputStream fos= newFileOutputStream(destination);while (fis.available()!=0){int i =fis.read();

fos.write(i);

}

fis.close();

fos.close();

}

}void copyDir(File source, File destination,boolean byBytes) throwsIOException{if (!source.isDirectory()){ //是文件则复制其内容

copyContent(source,destination,byBytes);

}else{if (destination.mkdirs()){ //是文件夹则递归复制

File[] fs =source.listFiles();for (int i = 0; i < fs.length; i++) {

String fileName=fs[i].getName();

File newDestination= new File(destination.getPath() + File.separator +fileName);

copyDir(fs[i], newDestination,byBytes);

}

}else{

System.out.print("Creat dirs failed!");

}

}

}publicFile getSource() {returnsource;

}public voidsetSource(File source) {this.source =source;

}publicFile getDestination() {returndestination;

}public voidsetDestination(File destination) {this.destination =destination;

}

}

结果

//采用单个字节复制方法耗时

1317

//采用缓冲区字节数组复制方法耗时

52

//减少了超过95%的时间

至关重要的是:除非数据流非常小,否则都应该使用数组来进行流的处理,必要时可用BufferedInputStream或BufferedOutputStream或BufferedWriter/BufferedReader来进行缓冲处理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值