您的位置:首页 > 编程语言 > Java开发

java关于流的学习笔记大全,包含全部流的概念及用法

2017-10-16 01:24 471 查看
I/O
 概念
 1、用来处理设备之间的数据传输       2、 Java对数据的操作时通过流的方式      3、 Java用于操作流的对象都在IO包装
      流操作的基本规律
1.明确源和目的地
            源:输入流 InputStream Reader
           目的: 输出流 OutputStream Writer

                 2.明确操作的数据是否是纯文本
     
4000
               是:字符流
                     否:字节流

                3.当体系明确后,再明确要使用哪个具体的对象
                    通过设备来进行划分
                    源设备:内存,硬盘,键盘
                   目的设备:内存,硬盘,控制台

装饰设计模式
概念
IO流部分

                               read()一次读一个

                              readLine()一次读一行 其实就是在增强了 read方法的功能

                              BufferedReader 就是 对 FileReader的增强

                                      这种模式 我们叫做 装饰设计模式
说明
装饰类 通常会通过构造方法 去接收被装饰对象

                       并给予被装饰类的功能 提供更强的功能

继承与装饰的区别
1.装饰

     优点:比继承要更灵活,避免了继承体系的臃肿,而且降低了类与类之间的关系

     缺点:如果再出现其他子类 又要给一个Buffered 体系臃肿且复杂 需要记忆的类太多了
2.继承

     优点:新的实现很容易,因为大部分是继承而来的很容易修改和扩展已有的实现

     缺点:打破了封装,因为基类向子类暴露了实现细节白盒重用,因为基类的内部细节                通常对子类是可见的当父类的实现改变时可能要相应的对子类做出改变不能在                运行时改变由父类继承来的实现 

IO的种类
1.流向分
输入流:从磁盘等物理介质到当前内存中    InputStream(字节流)     Reader(字符流)

输出流:将程序处理好的数据从内存中输出到磁盘等存储介质中     

                     OutputSteam(字节流)       Writer(字符流)

        2.数据类型不同分
字节流:流中的数据以字节为单位流动   InputStream     OutputStream
    InputStream  字节输入流  从磁盘到内存     FileInputStream
   根据内存大小做一个字节数组  byte[] arr = new byte[fis.available()];//弊端                                有可能会造成内存溢出
OutputStream    字节输出流  从内存到磁盘      FileOutputStream字节缓冲区
BufferedInputStream(InputStream in)
BufferedInputStream会一次性从文件中读取8192个 存在缓冲区中,返回给程序一个

程序再次读取的时候 就不用找文件了 直接从缓冲区中获取

         BufferedOutputStream(OutputStream in)   BufferedOutputStream程序向流中写出字节时,不会直接写到文件中,先写到缓冲区中直到缓冲区装满 才会把缓冲区中的数据异型性写到文件里
字节流一次读写一个数组的速度明显比一次读一个字节速度快

java本身在设计的时候 就加入了这样的功能 就是缓冲区数组的读写和带Buffered的读写

如果数组定义8192个字节大小和Buffered比较的话    数组会好一些  因为数组读和写  操作的都是同一个数组  而Buffered操作的是两个数组
字符流
流中的数据以字符为单位流动    Reader  Writer
可以读写字符的IO流    底层也是字节流   国际编码表 ---UTF-8                                 Writer     ------>
FileWriter

Reader    ------> FileReader
字符流缓冲区
作用
BufferedReader            BufferedWriter

            缓冲区的出现提高了对数据的读写效率
缓冲区要结合流才可以使用在流的基础上 对流的功能进行了增强
使用情况
文本文件 读取一段文本 或者是写出一段文本不可以拷贝非纯文本文件

因为在读的时候 会将字节转换成字符 在转换的过程中 可能找不到对应的字符

就会用?替代 写出的时候 将字符转换成字节写出 如果是? 直接写出 这样写出之后的文件就乱了
转换流
Reader 类 
字节转字符 输入流 InputStreamReader 是字节流通向字符流的桥梁:

InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader

InputStreamReader(InputStream in, Charset cs) 创建使用给定字符集的InputStreamReader

InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的InputStreamReader
Writer 类 
Writer 类 字节转字符 输出流 OutputStreamWriter 是字节流通向字符流的桥梁

OutputStreamWriter(OutputStream out) 创建使用默认字符编码的OutputStreamWriter

OutputStreamWriter(OutputStream in, Charset cs) 创建使用给定字符集的OutputStreamWriter

OutputStreamWriter(OutputStream in, String charsetName) 创建使用指定字符集的OutputStreamWriter
IO的种类
流向分
输入流
从磁盘等物理介质到当前内存中    InputStream(字节流)     Reader(字符流)
输出流
将程序处理好的数据从内存中输出到磁盘等存储介质中     OutputSteam(字节流)       Writer(字符流)
数据类型不同分
字节流
流中的数据以字节为单位流动   InputStream     OutputStream
InputStream  字节输入流  从磁盘到内存     FileInputStream
根据内存大小做一个字节数组  byte[] arr = new byte[fis.available()];//弊端 有可能会造成内存溢出
OutputStream    字节输出流  从内存到磁盘       FileOutputStream
字节缓冲区
BufferedInputStream(InputStream in)  BufferedInputStream会一次性从文件中读取8192个 存在缓冲区中,返回给程序一个

程序再次读取的时候 就不用找文件了 直接从缓冲区中获取
BufferedOutputStream(OutputStream in)
BufferedOutputStream程序向流中写出字节时,不会直接写到文件中,先写到缓冲区中直到缓冲区装满 才会把缓冲区中的数据异型性写到文件里字节流一次读写一个数组的速度明显比一次读一个字节速度快java本身在设计的时候 就加入了这样的功能 就是缓冲区数组的读写和带Buffered的读写,如果数组定义8192个字节大小和Buffered比较的话    数组会好一些  因为数组读和写  操作的都是同一个数组  而Buffered操作的是两个数组
字符流
流中的数据以字符为单位流动    Reader  Writer
可以读写字符的IO流    底层也是字节流   国际编码表 ---UTF-8                                 Writer     ------>
FileWriter

Reader    ------> FileReader
字符流缓冲区
作用
BufferedReader

BufferedWriter

缓冲区的出现提高了对数据的读写效率

缓冲区要结合流才可以使用

在流的基础上 对流的功能进行了增强
使用情况
文本文件 读取一段文本 或者是写出一段文本

不可以拷贝非纯文本文件

因为在读的时候 会将字节转换成字符 在转换的过程中 可能找不到对应的字符

就会用?替代 写出的时候 将字符转换成字节写出 如果是? 直接写出 这样写出之后的文件就乱了
转换流
Reader 类 
字节转字符 输入流 InputStreamReader 是字节流通向字符流的桥梁:

InputStreamReader(InputStream in) 创建一个使用默认字符集的InputStreamReader

InputStreamReader(InputStream in, Charset cs) 创建使用给定字符集的InputStreamReader

InputStreamReader(InputStream in, String charsetName) 创建使用指定字符集的InputStreamReader
Writer 类 
Writer 类 字节转字符 输出流 OutputStreamWriter 是字节流通向字符流的桥梁

OutputStreamWriter(OutputStream out) 创建使用默认字符编码的OutputStreamWriter

OutputStreamWriter(OutputStream in, Charset cs) 创建使用给定字符集的OutputStreamWriter

OutputStreamWriter(OutputStream in, String charsetName) 创建使用指定字符集的OutputStreamWriter
其他流
打印流
PrintStream(字节打印流)
构造函数接收的参数类型

1、file对象   2.字符串路径   3.字节输出流   OutputStream
PrintWriter(字符打印流)
在wed阶段 
用来将数据打到客户端  让客户端对他解析执行   B/S(从网页到服务器)   C/S(从客户端到网页)
构造函数接收类型
1.File对象     2.字符串路径    3.字节输出流(OutputStream)   4.字符输出流(Writer)
该流提供了打印方法  可以对基本数据类型进行直接操作  可以保持数据的原样性  打印出去  此类中不会抛出I/O异常
使用范例
PrintWriter writer= new PrintWriter(new FileWriter("f:\\aaa\\reade.txt"),true);
标准输入输出流
System.in
System.in是InputStream标准输入流  默认可以从键盘输入读取字节数据
System.out
System.out是PrintStream 标准输出流 默认可以向控制台中输出字符或字节数据
用法实例
System.setIn(new FileInputStream(file));
System.setOut(new PrintStream("f:\\aaa\\yy.txt"));
InputStream in=System.in;

                                                PrintStream xx=System.out;
   修改标准输入输出流  1.System.setIn(InputStream)        2.System.setOut(PrintStream)    修改标准输入输出流的员的 源 地和 目的地 这样可以实现拷贝的功能
序列流
概念:
序列流可以把多个字节输入流合成一个流   从序列流中读取数据时 将被整合的第一个流开始读 ,读完一个再读下一个 以此类推  把最后一个小流的-1做为大流的结束
SequenceInputStream( InputStream  s1,InputStream  s2)  将多个源合并   SequenceInputStream( Enumeration< ?   extends  InputStream>   e )
用法实例
多分一  1、两张图片和为一张      2、多个文件的内容填到一个文件中
FileInputStream stream=new FileInputStream("f:\\aaa\\11.jpg");

FileInputStream stream2=new FileInputStream("f:\\aaa\\22.jpg");

SequenceInputStream stream3=new SequenceInputStream(stream, stream2);

FileOutputStream wStream=new FileOutputStream("f:\\aaa\\33.png");

  int b;

  while ((b=stream3.read())!=-1) {

wStream.write(b);

}
Vector<FileInputStream> vector=new Vector<FileInputStream>();

try {
vector.add(new FileInputStream("f:\\aaa\\11.txt"));
vector.add(new FileInputStream("f:\\aaa\\22.txt"));

 Enumeration<FileInputStream> en=vector.elements();

 SequenceInputStream seq=new SequenceInputStream(en);

 FileOutputStream outputStream=new FileOutputStream("f:\\aaa\\55.txt");

  byte[] by=new byte[1024];

  int i=0;

  while ((i=seq.read(by))!=-1) {

  outputStream.write(by,0,i);
}
将一个文件按照大小分
try {

  FileInputStream stream=new FileInputStream("f:\\aaa\
b977
\11.mp3");

  FileOutputStream out=null; 

  byte[] by=new byte[1024*1024];

  int len=0;

  int cunt=1;

  while ((len=stream.read(by))!=-1) {

  out=new FileOutputStream("f:\\aaa\\"+(cunt++)+".mp3");

  out.write(by,0,len);

  out.close();
对象操作流
概念
该流可以将一个对象写出或者读取一个对象到程序中 也就是执行了序列化和反序列化的操作   1.ObjectInputStream          2.ObjectOutputStream
Serializable     ( 是一个借口  用implements实现   public static final long serialVersionUID = 42L; )
这种接口  没有方法  给类加载一  serialVersionUID 号  就证明你的类具备了序列化(持久化) ---->找一个介质 长期保存数据        对象存储在堆内存中  相要将对象存储在物理介质中  ------>对象的序列化/持久化(数据随着对象存入到硬盘上  如果下次想要使用  只要读取该文件 就可以再次使用)     序列化是将堆内存中的数据序列号  被static修饰的成员 无法序列化
transient    (transient String sex;)  想存放在堆内存中 不想要序列化 也不想是静态
当类实现了Serializable接口  那么类中属性就是默认能被序列化的  为了让某些数据既能使用 有不被序列化  用一次就消亡  就可以使用当前关键字
1.一旦被transient修饰  变量将不再是对象序列化的一部分  该变量内容在序列化后 无法获得访问        2.transient 关键字只能修饰的变量  不能修饰方法和类     3.被transient关键字修饰的变量不在被序列化  和static修饰的一样  但是在内存中存储区域不一样  不可混淆  被static 修饰的变量也不能被序列化的
注意事项
ObjectInputStream和ObjectOutputStream所读写的对象  必须实现Serializable 接口
对象中被static或者transient修饰的成员变量 不能被序列化  自己写serialVersionUID 号
数据输入输出流
DataInputStream       DataOutputStream
可以按照基本数据类型大小读写数据   例:按Long 大小写出一个数字  写出时该数据占8个字节  读取的时候也可以按照Long来读取  一次读8个    仅是了操作基本数据类型是流  和数据相结合的功能  分别存储对应的字节数
构造函数
DataOutputStream(OutputStream  out)     void   write(int   b)                  1int =4byte=32bit  将指定字节写入基础输出流(8个低位)
void  writeUTF( String  str )
以与机器无关方式使用UTF-8修改版编码将一个字符串写入基础输出流    gbk 一个中文2字节     utf-8一个中文3个字节   writeUTF  一个中文4个字节
DataOutputStream dos = new DataOutputStream

(new FileOutputStream("writeUTF.txt"));

dos.writeUTF("你好");
dos.close();

  }

public static void readUTFDemo() throws IOException{
DataInputStream dis = new DataInputStream(
new FileInputStream("writeUTF.txt"));
String s = dis.readUTF();
System.out.println(s);
内存流ByteArrayStream
可以直接操作字节数组中数据的流向         该输出流可以向内存中写数据  把内存当做一个缓冲区  写出之后可以一次性获取出所有数据
ByteArrayInputStream
在构造的时候  需要接收数据源  而且数据源是一个字节数组
ByteArrayOutputStream
在构造的时候  不用定义数据的目的地  因为该对象中已经内部封装了可变长度的字节数组  这就是目的地    因为两个流都操作的是数组  并没有使用系统资源  使用不用close关闭
使用方法
ByteArrayInputStream(byte[] buf) 

ByteArrayOutputStream() 

//写出到文件中

bos.writeTo(new FileOutputStream("x.txt"));

//将内存缓冲区中所有的字节存储到数组中

byte[] newArr = bos.toByteArray();
RandomAccessFile
概念
在Java io包中   类RandomAccessFile不属于流 是Object的子类   但是它融合了InputStream和OutputStream的功能     支持对随机访问文件的读取和写入  这个对象内部封装了一个byte数组 可以通过指针对数组元素进行操作    可以通过getFilePointer 方法获取指针位置       seek方法  改变指针的位置
构造函数
public  RandomAccessFile(File   file,String   mode)   mode 参数指定用以打开文件的访问模式       值:“r” 以只读方式打开,调用结果对象的任何write方法都将导致抛出IOException.     “ew”  打开以便读取和写入。如果该文件尚不存在  则尝试创建该文件。             “rws” 打开以便读取和写入,对于“rw”,还要求以便读取和写入到底层存储设备。
     “rwd” 打开以便读取和写入  对于“rw” 还要求对文件内容的每个更新都同步写入到底层存储设备
使用
void seek(long pos) 
例如:有一个文件 这个流可以分段写入数据
我们用一个线程负责文件的其中一段 多线程可以同时向文件中写入内容
互不冲突 这就是多线程下载
如果用其他的流 都是从头向后写 那么第一个线程写个数据 第二个线程接着写另一个数据
以此类推 虽然数据存完了 但是 这样会导致读出来的都是错误的 不是完整的文件 解码错误
io中 只有这个可以实现多线程下载 seek方法

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: