千家信息网

整理 JAVA中的IO流 (字符流和字节流两个大类)

发表于:2024-09-22 作者:千家信息网编辑
千家信息网最后更新 2024年09月22日,java中的io流分为两类,字符和字节:OutputStream和InputStream字节流的父类,抽象。OutputStream有两个提供了实现的接口closable和flushable。Writ
千家信息网最后更新 2024年09月22日整理 JAVA中的IO流 (字符流和字节流两个大类)

java中的io流分为两类,字符和字节:

  • OutputStream和InputStream字节流的父类,抽象。OutputStream有两个提供了实现的接口closable和flushable。
  • Writer和Reader字符流的父类,抽象。
    实际上在流的操作中,底层与文件进行读写的都是字节流,因为即使是字符流的对象,其最终实现读写的也是用的字节流。
  1. 操作文件的字节子类FileOutputStream和FileInputStream。
    记住,这里面写出和读入的都是字节。
class  useByteStream{       /**        * 使用文件输出字节流        *        */       public static void testFileOutputStream()       {              OutputStream out = null;              try              {                     File f = new File(".\\log\\test.txt");                     //out = new FileOutputStream(f);                     out = new FileOutputStream(f,true); //追加方式记录到文件                     String str = "Hello World!!!";                     byte b[] = str.getBytes();                     out.write(b);                     out.close();              }              catch(FileNotFoundException e)              {              }              catch(IOException e)              {              }       }       /**        * 使用文件输入字节流        */       public static void testFileInputStream()       {              InputStream out = null;              try              {                     File f = new File(".\\log\\test.txt");                     out = new FileInputStream(f);                     String str = "Hello World!!!";                     byte b[] = new byte[1000];                     int len = out.read(b);                     System.out.println(new String(b,0, len) );                     out.close();              }              catch(FileNotFoundException e)              {              }              catch(IOException e)              {              }       }};
  1. 操作文件的字符子类FileWriter和FileReader
class useCharStream{       /**        * 使用文件字符输出流        */       public static void testFileWriter()       {              Writer w = null;              try              {                     File f = new File(".\\log\\test2.txt");                     w = new FileWriter(f,true); //追加方式                     w.write("hello world\r\n");                     w.close();              }              catch(FileNotFoundException e)              {                     e.printStackTrace();              }              catch(IOException e)              {                     e.printStackTrace();              }       }       /**        * 使用文件字符输入流        */       public static void testFileReader()       {              Reader w = null;              try              {                     File f = new File(".\\log\\test2.txt");                     w = new FileReader(f);                     char c[] = new char[1024];                     w.read(c);                     System.out.println(c);                     w.close();              }              catch(FileNotFoundException e)              {                     e.printStackTrace();              }              catch(IOException e)              {                     e.printStackTrace();              }       }};
  1. 两个转换类,OutputStreamWriter,负责将写入字符流转为字节流,InputStreamReader,负责读取字节流转为字符流。
    FileWriter的直接父类是OutputStreamWriter,并非Writer。
    FileReader的直接父类是InputStreamReader,并非Reader。
    因此,最终写入文件和从文件读出的都是字节流。

    以上都是基于文件流操作,接下来是基于内存操作流,如果只是写业务代码应该很少会用到。

  2. 内存操作流
    ByteArrayInputStream\ByteArrayOutputStream。
class useMemoryStream{       /**        * 使用内存操作流,字节        */       public static void testByteArray()       {              String str = "Hello world";              ByteArrayInputStream bis = null;              ByteArrayOutputStream bos = null;              bis = new ByteArrayInputStream(str.getBytes());              bos = new ByteArrayOutputStream();              int temp =0;              while((temp=bis.read())!=-1)              {                     char c = (char)temp;                     bos.write(Character.toUpperCase(c));              }              String newStr = bos.toString();              try              {                     bis.close();                     bos.close();              }              catch(IOException e)              {                     e.printStackTrace();              }              System.out.println(newStr);       }};
  1. 另外,管道流可以实现两个线程之间的通信。
    PipedInputStream 和 PipedOutputStream。
    PipedOutputStream通过connect方法与PipedInputStream建立连接,后续PipedOutputStream.write的内容,就会PipedInputStream.read方法读取
class Send implements Runnable{       private PipedOutputStream pos  = null;       public Send()       {              this.pos = new PipedOutputStream();       }       public void run()       {              String str = "Hello world!!!";              try              {                     try                     {                           Thread.sleep(2000);                     }                     catch(InterruptedException e)                     {                           e.printStackTrace();                     }                     this.pos.write(str.getBytes());                     System.out.println("thread:"+Thread.currentThread().getId()+",Send  string:"+str);              }              catch(IOException e)              {                     e.printStackTrace();              }              try              {                     this.pos.close();              }              catch(IOException e)              {                     e.printStackTrace();              }       }       public PipedOutputStream getPos()       {              return this.pos;       }};class Receive implements Runnable{       private PipedInputStream pis = null;       public Receive()       {              this.pis = new PipedInputStream();       }       public void run()       {              byte b[] = new byte[1024];              int len =0;              try              {                     len = this.pis.read(b); //阻塞方式              }              catch(IOException e)              {                     e.printStackTrace();              }              try              {                     pis.close();              }              catch(IOException e)              {                     e.printStackTrace();              }              System.out.println("thread:"+Thread.currentThread().getId()+",receive:"+new  String(b,0,len));       }       public PipedInputStream getPis()       {              return this.pis;       }};class pipedTest{       public void pipedStream()       {              Send s = new Send();              Receive r = new Receive();              try {                     s.getPos().connect(r.getPis());              }              catch(IOException e)              {                     e.printStackTrace();              }              new Thread(r).start();              new Thread(s).start();       }};

以上都是无缓存的,考虑到一般场景下,提高使用性能,最好使用有缓存的字符流:BufferedReader和BufferedWriter。

  1. BufferedReader
    只能接受输入为字符流,不能为字节流。所以有时候会使用InputStreamReader来转换字节流给字符流使用。还有BufferedWriter

    class useBuffer{   public static void testBufferReader()   {          BufferedReader buf = null;          //此处用到了字节流转字符流的类InputStreamReader,这是因为BufferedReader只能接收字符流          buf = new BufferedReader(new InputStreamReader(System.in));          String str =null;          try          {                 str = buf.readLine();          }          catch(IOException e)          {                 e.printStackTrace();          }          System.out.println("输出的内容为:"+str);   }   public static void testBufferWriter()   {          File f = new File(".\\log\\test2.txt");          try {                //默认缓冲区大小 8K   可以通过 new BufferedWriter(new FileWriter(f),1024);指定大小为1K                 BufferedWriter out =new BufferedWriter(new FileWriter(f));                 out.write("123321123355555", 0, 10);                  out.write("\r\n");                  out.close();          } catch (IOException e) {                 e.printStackTrace();          }   }};
  2. SCanner类,输入数据类。
    使用方法和BufferedReader类类似,并且方便验证数据类型。

    class useScan{   public static void testScan()   {          Scanner scan = new Scanner(System.in);          //以回车作为输入的结束符号,否则默认是空格          scan.useDelimiter("\r\n");          if(scan.hasNextInt()==true)          {                 int str = scan.nextInt();                 System.out.println("int "+str);          }          else          {                 String str = scan.next();                 System.out.println("string "+str);          }   }};

    scan.hasNext支持正则表达式。比如 hasNext("^\\d{4}-\\d{2}-\\d{2}$") 就是日期格式yyyy-MM-dd的正则表达式,通过next("^\\d{4}-\\d{2}-\\d{2}$")

0