黑马程序员:Java基础总结----字节流&InputStream &OutputStream

时间:2022-03-19 11:37:05
黑马程序员:Java基础总结



字节流&InputStream &OutputStream

  ASP.Net+Android+IO开发 .Net培训 、期待与您交流!



字节流

字节流两个基类:
InputStream , OutputStream

类 OutputStream方法

输出流接受输出字节并将这些字节发送到某个接收器。 

 void write(byte[] b)
          将 b.length 个字节从指定的 byte 数组写入此输出流。
 void write(byte[] b, int off, int len)
          将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
abstract void write(int b)
          将指定的字节写入此输出流。

类 FileOutputStream

FileOutputStream(String name, boolean append)
          创建一个向具有指定 name 的文件中写入数据的输出文件流。

复制一个图片
            FileOutputStream fos =  null ;
            FileInputStream fis =  null ;
              try
            {
                  fos =  new  FileOutputStream( "c:\\2.bmp"  );
                  fis =  new  FileInputStream( "c:\\1.bmp"  );

                    byte [] buf =  new  byte [1024];

                    int  len = 0;

                    while ((len=fis.read(buf))!=-1)
                  {
                        fos.write(buf,0,len);
                  }
             }

类 BufferedOutputStream

BufferedOutputStream(OutputStream out)
          创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

通过字节流的缓冲区完成复制mp3

            BufferedInputStream bufis =  new  BufferedInputStream( new  FileInputStream( "c:\\0.mp3"  ));
            BufferedOutputStream bufos =  new  BufferedOutputStream( new  FileOutputStream( "c:\\1.mp3"  ));
            
              int  by = 0;

              while ((by=bufis.read())!=-1)
            {
                  bufos.write(by);
            }

            bufos.close();
            bufis.close();

类 ObjectOutputStream

ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。

        public  static  void  writeObj() throws  IOException
      {
            ObjectOutputStream oos =
                    new  ObjectOutputStream( new  FileOutputStream( "obj.txt"  ));

            oos.writeObject(  new  Person( "lisi0"  ,399, "kr" ));

            oos.close();
      }

类 PipedOutputStream

可以将管道输出流连接到管道输入流来创建通信管道。管道输出流是管道的发送端。通常,数据由某个线程写入 PipedOutputStream 对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。

PipedOutputStream()
          创建尚未连接到管道输入流的管道输出流。
PipedOutputStream(PipedInputStream snk)
          创建连接到指定管道输入流的管道输出流。
必须使用多线程:
            PipedInputStream in =  new  PipedInputStream();
            PipedOutputStream out =  new  PipedOutputStream();
            in.connect(out);

             Read r =  new  Read(in);
             Write w =  new  Write(out);
              new  Thread(r).start();
              new  Thread(w).start();

类 DataOutputStream

可以用于操作基本数据类型的数据的流对象
void writeInt(int v)
          将一个 int 值以 4-byte 值形式写入基础输出流中,先写入高字节。

        public  static  void  readData() throws  IOException
      {
            DataInputStream dis =  new  DataInputStream( new  FileInputStream( "data.txt"  ));

              int  num = dis.readInt();
              boolean  b = dis.readBoolean();
              double  d = dis.readDouble();

            System.  out .println( "num="  +num);
            System.  out .println( "b="  +b);
            System.  out .println( "d="  +d);

            dis.close();
      }
        public  static  void  writeData() throws  IOException
      {
            DataOutputStream dos =  new  DataOutputStream( new  FileOutputStream( "data.txt"  ));

            dos.writeInt(234);
            dos.writeBoolean(  true );
            dos.writeDouble(9887.543);

            dos.close();

            ObjectOutputStream oos =  null ;
            oos.writeObject(  new  O());

            
      }


类 ByteArrayOutputStream

用于操作字节数组的流对象
ByteArrayInputStream :在构造的时候,需要接收数据源,。而且数据源是一个字节数组。
ByteArrayOutputStream: 在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组。
这就是数据目的地。
因为这两个流对象都操作的数组,并没有使用系统资源。
所以,不用进行close关闭

源设备,
     键盘 System.in,硬盘 FileStream,内存 ArrayStream。
目的设备:
     控制台 System.out,硬盘FileStream,内存 ArrayStream

byte[] toByteArray()
          创建一个新分配的 byte 数组。
 String toString()
          使用平台默认的字符集,通过解码字节将缓冲区内容转换为字符串。

        //数据源。
      ByteArrayInputStream  bis  =  new  ByteArrayInputStream( "ABCDEFD"  .getBytes());

        //数据目的
      ByteArrayOutputStream  bos  =  new  ByteArrayOutputStream();

        int  by = 0;

        while ((by=bis.read())!=-1)
      {
              bos .write( by  );
      }



      System.out.println(bos.size());
      System.out.println(bos.toString());

//    bos.writeTo(new FileOutputStream("a.txt"))





类 InputStream方法

 int available()
          返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。
(!多线程时读取或跳过的字节数可能小于该数,试图使用此方法的返回值分配缓冲区来实现读取和跳过是不正确的)
返回:可以不受阻塞地从此输入流读取(或跳过)的估计字节数;如果到达输入流末尾,则返回 0
abstract
  int
read()
          从输入流中读取数据的下一个字节。
 int read(byte[] b)
          从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。

            FileInputStream fis = new FileInputStream("fos.txt" );
            
//           int num = fis.available();
             byte[] buf = new byte[fis.available()]; //定义一个刚刚好的缓冲区。不用在循环了。

            fis.read(buf);

            System. out.println(new String(buf));

            fis.close();

类 FileInputStream

和InputStream相似

类 BufferedInputStream

字段摘要
protected byte[] buf
          存储数据的内部缓冲区数组。
protected int count
          比缓冲区中最后一个有效字节的索引大 1 的索引。 buf[0] 到 buf[count-1] 的元素包含从底层输入流中获取的缓冲输入数据
protected int marklimit
          调用 mark 方法后,在后续调用 reset 方法失败之前所允许的最大提前读取量。
protected int markpos
          最后一次调用 mark 方法时 pos 字段的值。
protected int pos
          缓冲区中的当前位置。

以下是JDK读取文件的过程

  private  void  fill()  throws  IOException {
      byte [] buffer = getBufIfOpen();
      if  (markpos < 0)
         pos = 0;             /* no mark: throw away the buffer */
      else  if  (pos >= buffer.length)   /* no room left in buffer */
          if  (markpos > 0) {   /* can throw away early part of the buffer */
              int  sz = pos - markpos;
             System.arraycopy(buffer, markpos, buffer, 0, sz);
             pos = sz;
             markpos = 0;
         }  else  if  (buffer.length >= marklimit) {
             markpos = -1;    /* buffer got too big, invalidate mark */
             pos = 0;         /* drop buffer contents */
         }  else  {             /* grow buffer */
              int  nsz = pos * 2;
              if  (nsz > marklimit)
                 nsz = marklimit;
              byte  nbuf[] =  new  byte [nsz];
             System.arraycopy(buffer, 0, nbuf, 0, pos);
              if  (!bufUpdater.compareAndSet( this , buffer, nbuf)) {
                  // Can't replace buf if there was an async close.
                  // Note: This would need to be changed if fill()
                  // is ever made accessible to multiple threads.
                  // But for now, the only way CAS can fail is via close.
                  // assert buf == null;
                  throw  new  IOException( "Stream closed" );
             }
             buffer = nbuf;
         }
     count = pos;
      int  n = getInIfOpen().read(buffer, pos, buffer.length - pos);
      if  (n > 0)
         count = n + pos;
 }
  public  synchronized  int  read()  throws  IOException {
      if  (pos >= count) {
         fill();
          if  (pos >= count)
              return  -1;
     }
      return  getBufIfOpen()[pos++] & 0xff;
 }

结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。

而在写入数据时,只写该int类型数据的最低8位。


类 ObjectInputStream

ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化

ObjectOutputStream 和 ObjectInputStream 分别与 FileOutputStream 和 FileInputStream 一起使用时,可以为应用程序提供对对象图形的持久存储。ObjectInputStream 用于恢复那些以前序列化的对象。其他用途包括使用套接字流在主机之间传递对象,或者用于编组和解组远程通信系统中的实参和形参。

类 PipedInputStream

管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从  PipedInputStream 对象读取,并由其他线程将其写入到相应的  PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道 已损坏
PipedInputStream(PipedOutputStream src)
          创建 PipedInputStream,使其连接到管道输出流 src

类 DataInputStream

 int readInt()
          参见 DataInput 的 readInt 方法的常规协定。可见有两个大接口DataInput,和DataOutput


类 ByteArrayOutputStream

参见ByteArraysInputStream相似







  ASP.Net+Android+IO开发 .Net培训 、期待与您交流!