• Java:IO流之字节流InputStream、OutputStream详解


    字节流:
    (抽象基类)InputStream类(读):
    (抽象基类)OutputStream类(写):
     
    InputStream:
    构造方法摘要
    InputStream() 
                
     方法摘要 
    int available() 
     返回此输入流下一个方法调用可以不受阻塞地从此输入流读取(或跳过)的估计字节数。 
    void close() 
     关闭此输入流并释放与该流关联的所有系统资源。 
    void mark(int readlimit) 
     在此输入流中标记当前的位置。 
    boolean markSupported() 
     测试此输入流是否支持 mark 和 reset 方法。 
    abstract  int read() 
     从输入流中读取数据的下一个字节。 
    int read(byte[] b) 
     从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。 
    int read(byte[] b, int off, int len) 
     将输入流中最多 len 个数据字节读入 byte 数组。 
    void reset() 
     将此流重新定位到最后一次对此输入流调用 mark 方法时的位置。 
    long skip(long n) 
     跳过和丢弃此输入流中数据的 n 个字节。
    //例子1:
    import java.io.*;
    class FileInputStreamDemo
    {
        public static void main(String[] args)throws IOException
        {
            //读取该文件中的数据
            FileInputStream fis = new FileInputStream("f:\myfile\fos.txt");
            int b = 0;
            while((b = fis.read())!=-1)
            {
                System.out.print((char)b);
            }
            
            //此处不适用于刷新,而是用于关闭资源
            fis.close();
        }
    }
    OutputStream:  
    构造方法摘要 
    OutputStream() 
     
    方法摘要 
    void close() 
     关闭此输出流并释放与此流有关的所有系统资源。 
    void flush() 
     刷新此输出流并强制写出所有缓冲的输出字节。 
    void write(byte[] b) 
     将 b.length 个字节从指定的 byte 数组写入此输出流。 
    void write(byte[] b, int off, int len) 
     将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。 
    abstract  void write(int b) 
     将指定的字节写入此输出流。  
     
    //例子2:需求:想要操作图片数据,这时就要用到字节流。
    import java.io.*;
    class FileOutputStreamDemo
    {
        public static void main(String[] args)throws IOException
        {
            //创建字节流文件并写入数据
            FileOutputStream fos = new FileOutputStream("f:\myfile\fos.txt");
            String str = "abcde";
            byte b[] = str.getBytes();
            fos.write(b);
            
            //此处不适用于刷新,而是用于关闭资源
            fos.close();
        }
    }
    使用字节流读取文件中的数据有三种方式:
    方法一:一个一个字节的读取;
    方法二:先指定长度的数组,再将数据读读入数组,最后从数组中读出数据内容;
    方法三:通过available()方法可以获取文件中数据的总个数,以此个数设置为数组长度刚刚好,剩下步骤与方法二相等。
    //例子3:
    import java.io.*;
    class FileStream
    {
        public static void main(String[] args)throws IOException
        {
         //WriteFile();
         ReadFile1();
         ReadFile2();
         ReadFile3();
        }
        public static void WriteFile()throws IOException
        {
            //创建字节流文件并写入数据
            FileOutputStream fos = new FileOutputStream("f:\myfile\fs.txt");
            String str = "xyzabcd123";
            byte b[] = str.getBytes();
            fos.write(b);
            
            //此处不适用于刷新,而是用于关闭资源
            fos.close();
        }
        
        //方法一:一个一个字节的读取
        public static void ReadFile1()throws IOException
        {
            //读取该文件中的数据
            FileInputStream fis = new FileInputStream("f:\myfile\fs.txt");
            int b = 0;
            while((b = fis.read())!=-1)
            {
                System.out.println((char)b);
            }
            
            //此处不适用于刷新,而是用于关闭资源
            fis.close();        
        }
        
        //方法二:先指定长度的数组,再将数据读读入数组,最后从数组中读出数据内容。
        public static void ReadFile2()throws IOException
        {
            //读取该文件中的数据
            FileInputStream fis = new FileInputStream("f:\myfile\fs.txt");
            byte[] buf = new byte[1024];
            int num = 0;
            while((num = fis.read(buf))!=-1)
            {
                System.out.println(new String(buf,0,num));
            }
     
            //此处不适用于刷新,而是用于关闭资源
            fis.close();     
        }
    
       //方法三:通过available()方法可以获取文件中数据的总个数,以此个数设置为数组长度刚刚好,剩下步骤与方法二相同。
        public static void ReadFile3()throws IOException
        {
            //读取该文件中的数据
            FileInputStream fis = new FileInputStream("f:\myfile\fs.txt");
            byte[] buf = new byte[fis.available()];
            fis.read(buf);
            System.out.println(new String(buf));
            //此处不适用于刷新,而是用于关闭资源
            fis.close();     
        }   
    }
    复制和读取二进制文件,必须使用字节流,下面进行具体的应用实例举例:
    //复制图片:
    思路:
     1、用字节读取流对象和图片关联;
     2、用字节写入流对象创建一个图片文件,用于存储获取到的数据;
     3、通过循环读写,完成数据的存储;
     4、关闭资源。
    import java.io.*;
    class CopyPicture
    {
        public static void main(String[] args)
        {
          FileOutputStream fos = null;
          FileInputStream fis = null;
          try
          {
              fos = new FileOutputStream("F:\myfile\2.jpg");
              fis = new FileInputStream("F:\myfile\1.jpg");
              byte[] buf = new byte[1024];
              int len = 0;
              while((len = fis.read(buf))!=-1)
              {
                   fos.write(buf,0,len);
              }
          }
          catch(IOException e)
          {
              throw new RuntimeException("文件复制失败!");
          }
          finally
          {
              try
              {
                  if(fis!=null)
                     fis.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("读取流关闭异常!");
              }
              try
              {
                  if(fos!=null)
                     fos.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("写入流关闭异常!");
              }          
          }
        }
    }
    //复制MP3:
    复制一个音频。(通过Buffered缓冲空间)
    BufferedInputStream 
    BufferedOutputStream 
    思路:
     1、用字节读取流对象和音频关联;
     2、用字节写入流对象创建一个音频文件,用于存储获取到的数据;
     3、通过循环读写,完成数据的存储;
     4、关闭资源。
    import java.io.*;
    class CopyMp3
    {
        public static void main(String[] args)
        {
          long start = System.currentTimeMillis();
          copy();
          long end = System.currentTimeMillis();
          System.out.println((end-start)+"毫秒");
        }
        
        //通过字节流缓冲区完成复制
        public static void copy()
        {
          BufferedInputStream bufis = null;
          BufferedOutputStream bufos = null;
          try
          {
              bufis = new BufferedInputStream(new FileInputStream("F:\myfile\b01.mp3"));
              bufos = new BufferedOutputStream(new FileOutputStream("F:\myfile\b02.mp3"));
              int by = 0;
              while((by = bufis.read())!=-1)
              {
                   bufos.write(by);
              }
          }
          catch(IOException e)
          {
              throw new RuntimeException("文件复制失败!");
          }
          finally
          {
              try
              {
                  if(bufis!=null)
                     bufis.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("读取流关闭异常!");
              }
              try
              {
                  if(bufos!=null)
                     bufos.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("写入流关闭异常!");
              }          
          }        
        }
    }
    //复制视频avi:
    复制一个视频。(通过自定义的数组缓冲空间)
    思路:
     1、用字节读取流对象和视频关联;
     2、用字节写入流对象创建一个视频文件,用于存储获取到的数据;
     3、通过循环读写,完成数据的存储;
     4、关闭资源。
    import java.io.*;
    class CopyAvi
    {
        public static void main(String[] args)
        {
          FileOutputStream fos = null;
          FileInputStream fis = null;
          try
          {
              fos = new FileOutputStream("F:\myfile\a02.avi");
              fis = new FileInputStream("F:\myfile\a01.avi");
              byte[] buf = new byte[4096];
              int len = 0;
              while((len = fis.read(buf))!=-1)
              {
                   fos.write(buf,0,len);
              }
          }
          catch(IOException e)
          {
              throw new RuntimeException("文件复制失败!");
          }
          finally
          {
              try
              {
                  if(fis!=null)
                     fis.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("读取流关闭异常!");
              }
              try
              {
                  if(fos!=null)
                     fos.close();
              }
              catch(IOException e)
              {
                  throw new RuntimeException("写入流关闭异常!");
              }          
          }
        }
    }
     
    最后再提一下,使用api中的字节流是很好的,当然,用户也可以自定义一个字节流缓冲区。下面就给一个具体的实例:
    //演示mp3的复制,自定义一个字节流缓冲区
    import java.io.*;
    class MyBufferedStream
    {
        private InputStream in;
        private byte[] buf = new byte[1024];
        private int pos = 0,count = 0;
        MyBufferedStream(InputStream in)
        {
            this.in = in;
        }
        //一次读一个字节,从缓冲区(字节数组)获取
        public int myread() throws IOException
        {
            //通过in对象来读取硬盘上的字节数据,存放在字节数组中。
            if(count==0)
            {
              count  = in.read(buf);
              if(count<0)
                  return -1;
              pos=0;
              byte b = buf[pos];
              count--;
              pos++;
              return b&255;//byte字节提升为整型int型             
            } 
            else if(count>0)
            {
              byte b = buf[pos];
              count--;
              pos++;
              return b&0xff;//byte字节提升为整型int型+-++++            
            }
            return -1;
        }
        public void myclose()throws IOException
        {
            in.close();
        }
    }
    class MyBufferedStreamDemo
    {
        public static void main(String[] args)throws IOException
        {
          long start = System.currentTimeMillis();
          copymp3();
          long end = System.currentTimeMillis();
          System.out.println((end-start)+"毫秒");
        }
        public static void copymp3()throws IOException
        {
          MyBufferedStream mys  = new MyBufferedStream(new FileInputStream("F:\myfile\b01.mp3"));
          BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("F:\myfile\b03.mp3"));
          int num = 0;
          //System.out.println("第一个字节是:"+mys.myread());
          while((mys.myread())!=-1)//要区别开-1是数据读完时的-1,还是读取的字节数据内容为-1,所以要用&操作.
          {
              bufos.write(num);
          }
          mys.myclose();
          bufos.close();        
        }
    }
    提升
    byte:-1    ------->    int:-1
    11111111               11111111-11111111-11111111-111111111
    11111111---->提升了一个int类型,那不还是-1吗?是-1的原因是是因为在8个1前面补的1导致的。
    那么,我只要在8个1的前面补充0,即可以保持原字节数不变,又可以避免-1的出现。
      11111111-11111111-11111111-11111111
    & 00000000-00000000-00000000-11111111
    ------------------------------------
      00000000-00000000-00000000-11111111
     
  • 相关阅读:
    Linux vim的四中模式
    Linux 打包压缩解压缩
    Linux 写入查看文本
    Linux 文件复制和移动
    Linux 创建删除目录
    Linux cd命令
    vim 文本替换
    linux工作中使用命令
    is 和 == 的区别
    再次复习python
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4917818.html
Copyright © 2020-2023  润新知