[Java] I/O基础理解

本文详细介绍了 Java 中的 I/O 流概念,包括字符流和字节流的区别及应用场景。并通过实例演示了如何使用字节流和字符流进行文件复制,并探讨了缓冲流的应用及其对性能的影响。

  Java的I/O,按照数据传输单位大小可以分为字符流和字节流。字符流名副其实,每次仅仅传输一个字符。字节流,每次传输8bits一个字符。 他们通过与文件建立管道进行连接。每次分别传输一个字符或着字节。 这样,在小批量处理数据中,看不出什么效果,如果数据惊人,就会效率低下。并且对频繁读写硬盘,减少硬盘使用寿命。

字节流Stream 

java语言中字符流都有共性是方法名有Stream 他们都继承了InputStream 和OutPutStream 两个抽象类并实现其中的抽象方法(常用的Read方法和Close方法)。下面以InputStream为例。 每一个inputStream 都有与之相对应的OutputStream

154744_VpCo_1772665.jpg

//通过字节流将一个文本a.txt复制到另一个文档b.txt里面去
import java.io.*;
public class TestCopyTXT {
    public void CopyByStream()throws Exception
    {
       FileInputStream fis=new FileInputStream("a.txt");//注意这个FileInputStream 在构造的时候,如果没有发现a.txt文件,他判处找不到文件的异常FileNotFoundException
       FileOutputStream fos=new FileOutputStream("b.txt",true);//这个对象如果在创建的时候 没有发现b.txt的话,会自动创建,而且后面有可选参数布尔值。表面是否可以添加,还是重新覆盖填写。此处为在最后添加。
       int b=0;
       while((b=fis.read())!=-1){
          fos.write(b);
          //如果要打印输出的话,则必须把字节数强制类型转换成char型的。
          //System.out.print((char)b); 此处如果输出有中文的话,则会出现乱码。
       }
       fis.close();// 流使用过后要记得关闭。    
       fos.flush();
       fos.close();
     }
}

以上就是字节流的打印方法。但是如果sysout输出中文的话,会出现???。因为中文是两个字节,所以会出现乱码。要解决这个输出的问题,就必须采用字符流。字符流的类关系示意图如下,每个Reader也都分别对应的Writer

164556_jBNn_1772665.jpg

//和上段代码实现一样的过程  用Reader来实现这个过程。
import java.io.*;
public class TestCopyTxt{
    public void CopyByReader() throws Exception{
      FileReader fr=new FileReader("a.txt");
      FileWriter fw=new FileWrite("b.txt",true);//可以发现他们和字节流的处理过程,和方法名称是一样一样的。
      int b=0;
      while((b=fr.read())!=-1){
       System.out.print((char)b);
       fw.write(b);
      }      
      fr.close();
      fw.flush();
      fw.close();
    }

}

通过以上两个例子可以看出来java中 字节流和字符流处理流程是一模一样的,和方法名都是一模一样的,只不过一个是以字节为单位8bit 一个是以字符为单位的16bit。在使用的时候建议是采用字符流,兼容性好些。

但是如果不论是字节流还是字符流,都是数以节点流。这些流每次从硬盘上都是读取一个基本数据单位。如果长时间使用势必造成效率的低效和系统资源的浪费。因此我们在此,考虑使用缓冲队列。来降低硬盘读写带来

的压力。因此我们在此考虑用缓冲来解决这个问题。如下图所示:

165251_ndXb_1772665.jpg

这也叫处理流。与节点流最大不同就是处理的是批量的数据。可以更灵活。可以指定缓冲区大小,但默认已经足够大了。

public class TestBuffered{
  public void ReadTxt() throws Exception{
   FileReader fr=new FileReader("a.txt");
   BufferedFileReader bfr=new BufferedFileReader(fr);
   String  s;
   while((s=bfr.readLine())!=null){  //readLine 方法返回的是当前读取到的字符串,并不是一切的字节了。
      System.out.println(s);
   }
    fr.close();  //由内到外进行关闭,先将内管道关闭后。然后在关闭外缓冲
    bfr.close();
  }
}

由上面的例子可以看到java中的处理流把节点流的基础上封装了一层Buffered。这样再访问的时候,使得访问效率更加高,每次访问硬盘的数据更多。使访问效率得到提升,需要注意的是BufferedReader中和BufferedWriter中几个方法

170745_MU7g_1772665.jpg

170745_mMlc_1772665.jpg

最后一点就是字节流输入向字符输入流的转化过程。

        @Test
	public void TransformRead() throws Exception
	{        //通过把FileInputStream封装起来放入FileInputStreamReader中,完成转换字符流,最后使用buffered方法输出,其中StreamReader后面可以跟上编码格式。
		InputStreamReader a=new InputStreamReader(new FileInputStream("G:/JavaTest/练习代码/PrintUnicode.java"),"gbk");
		BufferedReader br=new BufferedReader(a);
		String s;
		while((s=br.readLine())!=null)
		{
			System.out.print(s);
		}
		a.close();
		br.close();
	}

上面的程序中对流进行了两次封装。第一次封装为转换流的格式。第二次封装改变流处理的方式。因此如下图所示。采用处理流方式可以提高效率。并且更好的复合人机交互。

173010_5O2e_1772665.jpg



转载于:https://my.oschina.net/anyyang/blog/342429

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值