Java学习之 IO

摘要:IO无疑是学习每一门语言都要求掌握的编程知识点,一些大型项目都离不开IO的支持,因此掌握IO相关操作,对以后的学习和工作都是很有必要的。IO知识说难不难,但是每到用的时候,我们都需要查阅,本文从Java语言面向对象的特点出发,讲述Java IO的一些知识,仅供参考。

IO 基本知识

IO是以流的方式来组织和传播,与流水非常相似。从源头输出不断流淌输入到目的地,中间为了方便,可能还会加上水管来辅助输出,水量小的时候,一滴滴或者涓涓细流,这时候我们可以建筑水坝库存到一定量才释放,有的水流汇入江海,而有的则直接流入千家百户。

在Java IO体系中,

  1. 根据流的成分不同,可以分为字符流字节流两种;
  2. 根据流向不同,可以分为输入流输出流
  3. 根据源头不同,可以分为文件流和内存流
  4. 为了便于输出和通信,Java也提供了管道流缓存流
  5. 根据输出目的地不同,可以通过打印流来控制是输出到文件还是其他地方;
  6. 为了支持序列化,Java还提供了对象流
  7. 为了支持数据的访问和保存,Java提供了数据流
  8. 为了支持文件的压缩与解压缩,Java提供了文件压缩与解压缩流

以下关于各个流的几个注意点:

  1. 以内存为参照:流入内存为输入流,流出内存,汇入外地,为输出流。
  2. 字符流是以字符为单位,主要处理文本文件;字节流以字节为传输单位,可以处理文本,语音和图像等任何信息,字节流的应用范围更广。Java提供了InputStreamReader和OutputStreamWriter来实现字符流与字节流的转换。
  3. 管道流主要解决线程间通信,应用不多。
  4. 缓存流为了数据的传输提供了一种包装的形式,例如BufferedReader则提供了readLine()方法,可以更好地处理数据的流通。
  5. 打印流需要制定流向,可以流向屏幕,可以流向文件,在构造的时候进行装填即可。
  6. 对象流无疑是将数据以对象的形式保存到文件或其他地方,提供了一种数据持久化方案,配合实现对象序列化,在很多大型项目都有非常重要的使用。
  7. 数据流用于保存和读取数据,readInt或writeInt方法等。
  8. Scanner接收用户输入,更便捷的处理方式。
  9. 文件压缩和解压缩流,提供了文件压缩与解压缩方法,每个压缩文件都是一个ZipEntry实体对象。

程序代码示例

文件拷贝

该例子系统讲述了字符流、字节流、输入流、输出流、包装流、打印流的使用。需要注意的时候,在程序执行完,需要关闭打开的所有流。


class FileCopy{
 	public static void copyByChar(String srcFilePath, String desFilePath){
		File srcFile = null;
		File desFile = null;
        
	    BufferedReader br = null;
		PrintWriter pw = null;

		try{
			srcFile = new File(srcFilePath);
			desFile = new File(desFilePath);
            
			br = new BufferedReader(new FileReader(srcFile));
			pw = new PrintWriter(new FileWriter(desFile));
            
			String temp = null;
            
			while((temp = br.readLine()) != null){
			    pw.println(temp);
			    pw.flush();
			}
		}catch(Exception e){
		   	e.printStackTrace();
		}finally{
		   	try{
		    	pw.close();
		    	br.close();
		   	}catch(Exception e){
		    	e.printStackTrace();
		   	}
		}
		System.out.println("copy file by char done");
 	}

	public static void copyByByte(String srcFilePath, String desFilePath){
		File srcFile = null;
	  	File desFile = null;

	  	InputStream is = null;
	  	OutputStream os = null;

	  	try{
	   		srcFile = new File(srcFilePath);
	   		desFile = new File(desFilePath);
            
	   		is = new FileInputStream(srcFile);
	  		os = new FileOutputStream(desFile);
            
	   		byte buf[] = new byte[1024];
	   		int len = 0;

	   		while((len = is.read(buf)) != -1){
	    		os.write(buf,0,len);
	    		os.flush();
	   		}
	  	}catch(Exception e){
	   		e.printStackTrace();
	  	}finally{
	   		try{
	   	 		os.close();
	    		is.close();
	   		}catch(Exception e){         
	   		}
	  	}
	  	System.out.println("copy file by byte done");
	}
}

内存流的使用

public static void testByteArrayStream(String str){
  	ByteArrayInputStream bais = null;
  	ByteArrayOutputStream baos = null;

  	try{
   		bais = new ByteArrayInputStream(str.getBytes());
  		baos = new ByteArrayOutputStream();

   		for(int i=0;i<str.length();i++){
    		char c = (char)bais.read();
    		baos.write(Character.toUpperCase(c));
   		}
   		System.out.println(baos.toString());

	   /*
	   byte buf[] = new byte[1024];
	   int len = bais.read(buf);
	   baos.write(buf,0,len);
	   System.out.println(baos.toString().toUpperCase());
	   */
  	}catch(Exception e){
  		 e.printStackTrace();
  	}
}

管道流的使用

class Sender implements Runnable {
 	private PipedOutputStream out = null;

 	public Sender(){
  		out = new PipedOutputStream();
 	}

 	public PipedOutputStream getOut(){
  		return out;
 	}

 	public void run(){
  		String message = "hello, moto
        
  		try{
   			out.write(message.getBytes());
  		}catch(Exception e){
   			e.printStackTrace();
  		}finally{
   			try{
   		 		out.close();
   			}catch(Exception e){
   			}
  		}
 	}
}

class Receiver implements Runnable {
 	private PipedInputStream in = null;

 	public Receiver(){
  		in = new PipedInputStream();
 	}

 	public PipedInputStream getIn(){
  		return in;
 	}

 	public void run(){
  		byte buf[] = new byte[1024];
  		int len = 0;

  		try{
   			len = in.read(buf);
  		}catch(Exception e){
   			e.printStackTrace();
  		}finally{
   			try{
    			in.close();
   			}catch(Exception e){
   			}
  		}
  		System.out.println("recevied:" + new String(buf,0,len));
 	}
}

以上是发送线程和接收线程,为了支持线程通信,需要使用PipedOutpuStream的connect方法连接PipedInputStream。

public static void testPipedStream(){
	Sender sender = new Sender();
	Receiver receiver = new Receiver();

	try{
 		sender.getOut().connect(receiver.getIn());
	}catch(Exception e){
 		e.printStackTrace();
	}
    
	new Thread(sender).start();
	new Thread(receiver).start();
}

Scanner 接收用户输入

public static void testScaner(){
	Scanner sc = new Scanner(System.in);
	String name = sc.next();
	int age = sc.nextInt();
	System.out.println("name="+name+" age="+age);
}

文件压缩流

public static void testFileZip(String srcFilePath, String zipFilePath){
  	File file = null;
  	InputStream in = null;
  	ZipOutputStream zipOut = null;
  	try{
   		file = new File(srcFilePath);
   		in = new FileInputStream(file);
        
   		zipOut = new ZipOutputStream(new FileOutputStream(zipFilePath));
   		zipOut.putNextEntry(new ZipEntry(file.getName()));
   		zipOut.setComment("hello world");
        
   		int temp = 0;
   		while((temp = in.read()) != -1){
    		zipOut.write(temp);
   		}
  	}catch(Exception e){
   		e.printStackTrace();
  	}finally{
   		try{
    		zipOut.close();
    		in.close();
   		}catch(Exception e){
    		e.printStackTrace();
   		}
  	}
  	System.out.println("zip done");
}

文件解压缩流

public static void testFileUnZip(String zipFilePath){
  	File file = null;
   	File outFile = null;
   	ZipFile zipFile = null;
    
   	ZipInputStream zipIn = null;
   	ZipEntry entry = null;

   	InputStream in = null;
   	OutputStream out = null;
    
   	try{
   		file = new File(zipFilePath);
   		zipFile = new ZipFile(file);
   		zipIn = new ZipInputStream(new FileInputStream(file));

   		while((entry = zipIn.getNextEntry()) != null){
    		System.out.println("un zip " +entry.getName());
    		outFile = new File("./unzip/" + entry.getName());
    		if(!outFile.getParentFile().exists()){
     			outFile.getParentFile().mkdir();
    		}
    		if(!outFile.exists()){
     			outFile.createNewFile();
    		}
    		in = zipFile.getInputStream(entry);
    		out = new FileOutputStream(outFile);
            
    		int temp = 0;
    		while((temp = in.read()) != -1){
     			out.write(temp);
    		}
   		}
  	}catch(Exception e){
   		e.printStackTrace();
  	}finally{
   		try{
    		out.close();
    		in.close();
    		zipIn.close();
   		}catch(Exception e){
    		e.printStackTrace();
   		}
  	}
  	System.out.println("un zip done");
}

以上几乎包含了所有Java Io流的操作,关于对象流及其支持的序列化与反序列化特性将在后面介绍。