• 深入分析Java中的I/O类的特征及适用场合


              Java中有40多个与输入输出有关的类。假设不理清它们之间的关系。就不能灵活地运用它们。

          假设从流的流向来分,可分为输入流和输出流,而输入流和输出流又都可分为字节流和字符流。因而可将Java中的I/O流下面图进行划分:


    注意上图并不是继承关系,而仅仅是一个示意图。

          Java中的其他与I/O流处理相关的类事实上都是从InputStream,Reader,OutputStream和Writer这4个基类继承而来。当中InputStream和OutputStream为字节流,Reader和Writer为字符流。

          之所以这样划分。是由于计算机中全部的数据都是二进制的,而字节流可处理全部的二进制文件,但假设使用字节流来处理文本文件,也不是不能够,可是会更麻烦。所以通常有例如以下一个规则:假设进行输入/输出的内容是文本文件,则应该考虑使用字符流。假设进行输入/输出的内容是二进制内容(如图片、音频文件),则应该考虑使用字节流。

         以下是从InputStream,Reader,OutputStream,Writer这4个基类出发,列出了经常使用的子类:






    以下对各个类的特点及适用场合进行说明:

    1.当中InputStreamReader和OutputStreamWriter是比較特殊的类。它们可将字节流转换为字符流,因而称为转换流。

    如InputStreamReader reader=new InputStreamReader(System.in);

    2.BufferedInputStream,BufferedOutputStream的使用方法尽管和FileInputStream,FileOutputStream的使用方法一样。可是效率却相差非常大,由于内存的效率比IO操作的效率要高得多。而BufferedInputStream,BufferedOutputStream会提前将文件里的内容读取(写入)到缓冲区。当读取(写入)时假设缓冲区存在就直接从缓冲区读,仅仅有缓冲区不存在对应内容时才会读取(写入)新的数据到缓冲区,并且一般会请求的数据要多。所以在读取(写入)文件,特别是较大的文件时,不要用最简单的FileInputStream和FileOutputStream,而要考虑使用BufferedInputStream,BufferedOutputStream.

    3.ObjectInputStream,ObjectOutputStream则各自是将序列化的对象(即实现了Serializable接口的对象)读取出来/写入到文件里,显然,这事实上是利用反射的原理。

    4.前面说过,Reader与InputStream的差别在于一个是字符输入流。一个是字节输入流。

    FileReader与FileInputStream相应,BufferedReader与BufferedInputStream相应,所以在读取文本文件时最好使用BufferedReader而不要使用FileReader.

    因为ByteArrayInputStream及PipedInputStream不经常使用,本文暂不讨论。

    以下是一些代码实例:

    首先是比較原始的读取文件的方法,即採用FileInputStream:

    //这是读取字节流的实例
    public class FileInputStreamSample {
    
    	public static void main(String[]args) throws IOException
    	{
    		FileInputStream fis=new FileInputStream("d://error.dat");
    		byte[]buff=new byte[1024];
    		int hasRead=0;
    		while((hasRead=fis.read(buff))>0)
    		{
    			System.out.println(new String(buff,0,hasRead));
    		}
            
    		fis.close();
    	
    	}
    }
    
    然后是利用FileOutputStream进行文件的写入:

    public class FileOutputStreamSample {
    
    	public static void main(String[]args)
    	{
    		String fileName="d://error.dat";
    		//注意:不必提前新建,由于假设没有新建的话,它自己会新建一个。

    String newFileName="d://error2.txt"; try (FileInputStream fis=new FileInputStream(fileName); FileOutputStream fos=new FileOutputStream(newFileName)) { byte[]buff=new byte[32]; int hasRead=0; while((hasRead=fis.read(buff))>0) { fos.write(buff,0,hasRead); } } catch(IOException ex) { ex.printStackTrace(); } } }

    比較高效的读取文件的方法。即採用BufferedInputStream:

    public class BufferedInputStreamSample {
    
    	public static void main(String[]args)
    	{
    		File file=new File("d://error.dat");
    		try
    		(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(file));)
    		{
    		    byte[]buff=new byte[1024];
    		    int hasRead=0;
    		    while((hasRead=bis.read(buff))>0)
    		    {
    		    	String content=new String(buff,0,hasRead);
    		    	System.out.println(content);
    		    }	
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    		
    	}
    }
    
    以下是比較高效的写入文件的方法。即採用BufferedOutputStream:

    public class BufferedOutputStreamSample {
    
    	public static void main(String[]args)
    	{
    		String content="I have a dream";
    		File file=new File("d://dream.dat");
    		
    		byte[]buff=content.getBytes();
    		
    		try
    		(BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(file));)
    		{	
    		    bos.write(buff);	
    		    //另外,bos另一个方法是bos.write(byte[],int arg1,int arg2);
    		}
    	    catch(IOException ex)
    	    {
    	    	ex.printStackTrace();
    	    }
    
    	}
    }
    
    以下是FileReader的使用方法,可是注意FileReader读取文本文件是比較低效的方法:

    public class FileReaderSample {
    
    	public static void main(String[]args)
    	{
    		try(
    				FileReader fr=new FileReader("d://error.dat")
    			)
    		{
    			char[]cbuff=new char[32];
    			int hasRead=0;
    			while((hasRead=fr.read(cbuff))>0)
    			{
    				System.out.println(new String(cbuff,0,hasRead));
    			}
    			
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    	}
    }
    
    类似地。FileWriter是比較低效的写入文本文件的方法:

    public class FileWriterSample {
    
    	public static void main(String[]args)
    	{
    		try
    		(FileWriter fw=new FileWriter("d://poem.txt"))
    		{
    			fw.write("I have a dream
    ");
    			fw.write("One day on the red hills of Georgia
    ");
    			fw.write("The sons of former slaves and the sons of  former slave owner will be able to sit down together at the table.
    ");
    			fw.write("My four little children will one day live in a nation where they will not be judged by the color of their skin but by the content of their character.
    ");
    			
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    	}
    }
    而BufferedReader是较高效的读取文本文件的方式。可是注意它的构造方法须要一个InputStreamReader,而InpuStreamReader又是包装FileInputStream而来,所以BufferedReader的用法例如以下:

    public class BufferedReaderSample {
    
    	public static void main(String[]args)
    	{
    		try
    		(
    				//假设是读取文件。则为InputStreamReader reader=new InputStreamReader(new InputStream("d://error.dat"));
    				//InputStreamReader reader=new InputStreamReader(new FileInputStream("d://error.dat"));
    				InputStreamReader reader=new InputStreamReader(System.in);
    				BufferedReader br=new BufferedReader(reader)			
    		)
    		{
    		      String buffer=null;
    		      while((buffer=br.readLine())!=null)
    		      {
    		    	  System.out.println(buffer.toUpperCase());
    		      }
    			
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    	}
    }
    

    显然。BufferedReader的优点是具有缓冲功能。它能够一次读取一行文本----以换行符为标志。上例是读取键盘输入后转换为大写并输出,当然,也能够读取文件后将各行转换为大写后输出。

    BufferedWriter使用方法较简单,可是值得注意的是它要flush:

    public class BufferedWriterSample {
    
    	public static void main(String[]args)
    	{
    		try
    		(
    		     //假设是写入到文件则为OutputStreamWriter writer=new OutputStreamWriter(new FileOutputStream("d://error.dat"));
    		     OutputStreamWriter writer=new OutputStreamWriter(System.out);
    			 BufferedWriter bw=new BufferedWriter(writer);
    		)
    		{
    			String content="Less is more
    Less is more is not a law
    Less is more is not always correct";
    			bw.write(content);	
    			bw.flush();
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    		
    	}
    }
    

    以下是PrintStream,PrintWriter,BufferedWriter这3个类的对照:

    首先是它们的共同点:都是处理流(包装流)而非节点流。因而能够更方便地使用,如PrintStream使用println(String)功能。BufferedWriter使用writer(String)功能;

    PrintStream与PrintWriter,BufferedWriter的差别在于前者是处理字节流,而后两者是处理字符流;而BufferedWriter与PrintWriter相比。因为缓冲区的作用,它的效率要比PrintWriter要高。

          以下是一个PrintStream的样例:

    class Student
    {
    	int id;
    	String name;
    	public Student()
    	{
    		id=0;
    		name="Jenny";
    	}
    	public String toString()
    	{
    		return "id="+id+" name="+name;
    	}
    }
    public class PrintStreamSample {
    
    	public static void main(String[]args)
    	{
    		String fileName="d://poem.txt";
    		try
    		(PrintStream ps=new PrintStream(new FileOutputStream(fileName)))
    		{
                //注意:这会把曾经的覆盖。要想不覆盖的话,就要使用ps.append的方法而不是println的方法。
    			ps.println("Less is more");
    			//直接使用println输出对象,这个在Socket编程时非常实用。
    			ps.println(new Student());
    		}
    		catch(IOException ex)
    		{
    			ex.printStackTrace();
    		}
    	}
    }
    
    以下是PrintWriter的一个样例:

    public class PrintWriterSample {
    
    	public static void main(String[]args)
    	{
    		try
    		(
    				PrintWriter writer=new PrintWriter(new OutputStreamWriter(System.out));				
    		)
    		{
    			writer.println("Less is more is a important rule.");
    			writer.println(true);		
    		}
    	 
    	}
    }

    最后是ObjectInputStream及ObjectOutputStream,利用这两个类来读写序列化对象特别方便。例如以下所看到的:

    public class ObjectOutputStreamSample {
    
    	public static void main(String[]args)
    	{
    		Student stu1=new Student(1,"Jack","NewYork");
    		Student stu2=new Student(2,"Rose","California");
    		
    		File file=new File("d://object.txt");
    		//由此可见,BufferedInputStream以及ObjectOutputStream事实上都是对FileOutputStream进行了包装。

    try (ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream(file))) { oos.writeObject(stu1); oos.writeObject(stu2); } catch(IOException ex) { ex.printStackTrace(); } } } class Student implements Serializable{ private int id; private String name; private String address; public Student(int id,String name,String address) { this.id=id; this.name=name; this.address=address; } @Override public String toString() { StringBuilder sb=new StringBuilder(); sb.append("id:"+id); sb.append(" "); sb.append("name:"+name); sb.append(" "); sb.append("address:"+address); return sb.toString(); } }

    public class ObjectInputStreamSample {
    
    	public static void main(String[]args)
    	{
    		File file=new File("d://object.txt");
    		try
    		(ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file)))
    		{
    			Student stu1=(Student)ois.readObject();
    			Student stu2=(Student)ois.readObject();
    		}
    		catch(Exception ex)
    		{
    			ex.printStackTrace();
    		}
    		
    	}
    }













           





  • 相关阅读:
    Python——五分钟带你弄懂迭代器与生成器,夯实代码能力
    LeetCode37 使用回溯算法实现解数独,详解剪枝优化
    LeetCode 33,在不满足二分的数组内使用二分的方法
    丰富图文详解B-树原理,从此面试再也不慌
    看完这篇让你高数不挂科之——泰勒公式
    数据结构——动手实战双向链表
    你听说过JMX么
    【网络安全】CSRF攻击详解
    【开发工具】本机安装的JDK8,启动IDEA2019没反应
    Java开发过程中的常用工具类库
  • 原文地址:https://www.cnblogs.com/lytwajue/p/7025802.html
Copyright © 2020-2023  润新知