第六节 IO流

  • 一、IO流概述
  • 二、管道流
  • 三、编码表:
  • 四、其它:


一、IO流概述

  1. IO流:对数据进行持久化的存储。(Input Output输入输出流。)
注:C++等语言中也有对数据的输入输出。
  1. 字节输入流:读取文件(InputStream)。
例1:
import java.io.*;		//导入IO流的包,*号表示遍历IO下所有包以供使用
public class Exam01 {
	public static void main(String[] args) throws IOException{	//IO流需要异常处理
		// 创建一个文件字节输入流
		FileInputStream in = new FileInputStream("test.txt");	//java文件夹需有此名的txt文件
		int b = 0;    	// 定义一个int类型的变量b。记住每次读取的一个字节
//		while ( (b = in.read() ) != -1){
//			// 变量b记住读取的一个字节。如果读取的字节为-1时,跳出while循环,输出
//			System.out.print((char)b); // 将b写出,数字、英文正常
//		}	//这种方法虽然也能输出,但文字这种两个字节的字符会分成一个解析(文字乱码)
		byte[] byt = new byte[1024];//字节缓冲流用法,以数组形式让数据积累一定字节,再继续传递
//		int b = 0;
		while ((b = in.read()) != -1){
			System.out.print(new String(byt,0,b)); // 将b写出,汉字也正常
		}	//使用数组进行处理后(长度将会足够),文字虽然仍分成两个字节解析,但之后会将解析合并回汉字字符
		in.close();		//结束,释放资源
	}
}
//	注:文本足够大,数组定义不够时,仍会出现乱码问题,此时需要别的方法(流)解决。
  1. 字节输出流:写入文件(OutputStream)。
例2:
import java.io.*;		//导入IO流的包,*号表示遍历IO下所有包以供使用
public class Exam02 {
	public static void main(String[] args) throws IOException{	//IO流需要异常处理
		// 创建一个文件字节输入流
		FileOutputStream on = new FileOutputStream("test.txt");	//java文件夹需有此名的txt文件
		on.write(97);		//向test.txt写入97这个字符——该字符代表编码位为a,所以添加a。
//		Byte[] bys = "abcd" .getBytes();		//abcd转换类型Byte
//		on.write(bys);
//		on.write(bys,0,2);		//从第一个开始(0角标,代表1),写入2个字节
		} 
		in.close();		//结束,释放资源
	}
}
//	注:当文本足够大,数组定义不够时,仍会出现乱码问题,此时需要别的方法(流)解决。
  1. 字节输入输出流综合运用
例3:
import java.io.*;
public class Exam02 {
   public static void main(String[] args) throws IOException {
   // 将it文本中的数据传到on本文文件中
   	File src=new File("tempfile\\it.txt");
   	File dest=new File("tempfile\\on.txt");
   	
   	FileInputStream fos=new FileInputStream(src);
   	FileOutputStream fis=new FileOutputStream(dest);
   	
   	int ch=0;
   	while((ch=fos.read())!= -1){
   		fis.write(ch);
   	}
   	fos.close();
   	fis.close();		
   }
}
  1. 字节缓冲流:提高读取效率。(BufferedInputStream、BufferedOutputStream)
    传递数据时,将数据放到一个数组中,再继续传递,而非一个数据一个数据传递。(略)
例如:
BufferedInputStream fis=new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream fos=new BufferedOutputStream(new FileOutputStream(des));
  1. 字符输入流:(Reader)
    LineNumberReader(显示行号)
    InputReader。
  2. 字符输出流:(Writer)
    OutputReader。
  3. 序列化及反序列化:ObjectInputStream(序列化)、ObjectOutputStream(反序列化)。[略]
  4. DataOutputStream、DataInputStream:使基本数值原类型,保持不变。(基本类型数据保持字节原样性。)
  5. 输出方法:
    ps.write(94); //写入最低字节
    ps.print(94); //将数据转换为字符串再写入,保持数据值形式。

二、管道流

  1. PipedInputStream和PipeOutputStream:输入输出可直接连接,配合线程使用。
  2. ByteArrayInputStream和ByteArrayOutputStream:用于操作字节数据数组流对象,它们是对应设备为内存的流对象。(注:不用定义数组(缓冲区),其自带一个数组缓冲区。)
  3. CharArrayInputStream和CharArrayOnputStream:用于操作字符数据数组流对象,它们是对应设备为内存的流对象。(释:文本文件数据读取到字符数组缓冲区,然后再将数据从字符数组缓冲区读出。)
  4. SequenceInputStream:当文件个数、对象(碎片)过多时,会产生过多的调用,导致效率下降。因此需要该容器,将流对象和(碎片)文件关联存储到容器中,再遍历容器获取流对象及读写操作。
例4:
import java.io.*;
import java.util.*;

public class Exam04 {
	public static void main(String[] args) throws IOException {
		List<FileInputStream> list = new ArrayList<FileInputStream>();
		
		for(int i=1;i<6;i++){
			list.add(new FileInputStream("D:\\" + i + ".part"));
		}
		FileOutputStream fos = new FileOutputStream("D:\\0.mp3");
		byte[] buf = new byte[1024 * 1024];
		//遍历集合,获取流对象
		for(FileInputStream fis : list){
			int len = fis.read(buf);
			fos.write(buf,0,len);
		}
		fos.close();
		//关闭所有流
		for(FileInputStream fis : list){
			fis.close();
		}
	}
//	public static void mergerFile(File partsDir) throws IOException{
//		//使用IO包的SequenceInputStream,对碎片文件合并,将对个读取流合并成一个读取流。
//		List<FileInputStream> list = new ArrayList<FileInputStream>();
//		
//		for(int i=1;i<6;i++){
//			list.add(new FileInputStream(new File("D:\\" + i + ".part")));
//		}	//获取枚举对象?
//		Enumeration<FileInputStream> en = Collections.enumeration(list);
//		//源
//		SequenceInputStream sis = new SequenceInputStream(en);
//		//目的
//		FileOutputStream fos = new FileOutputStream(new File(partsDir,"0.mp3"));
//		//不断的读写
//		byte[] buf= new byte[4096];
//		int len = 0;
//		for((len = sis.read(buf))!=-1){
//			fos.write(buf,0,len);
//		}
//		fos.close();
//		sis.close();
//	}
}
  1. 遍历指定目录下文件:
例5:
import java.io.File;
public class Exam07 {
	public static void main(String[] args) {
		//获取指定目录下内部内容
		File dir = new File("D:");
		String[] names = dir.list();
		for(String name : names){
//			System.out.println(name);
		}
//获取文件目录:	
		File[] files =  dir.listFiles();	//获取当前文件夹文件对象
		for(File file : files){
			System.out.println(file.getName());
		}
//删除文件目录:
		File dir1 = new File("D:\\删除目录");	//该方法无法删除文件夹中有内容的。
	//计算机删除可以实现是因为,计算机简化操作,找到最内部文件,由内而外进行删除。
		boolean b1 = dir1.mkdirs();		//创建多级目录
		System.out.println("b1="+b1);
	}
}
  1. RandomAccessFile:封装很多字节流工具。[略]

三、编码表:

  1. ascii:一个字节中的7位就可以表示。对应字节为正数。
  2. iso8859-1:拉丁码表(欧洲),用一个字节的8位。
  3. GB2312:简体中文码表。有六七千中文和符号。两个字节表示;
    GBK:常用中文码表,两万中文及符号。
  4. unicode:国际标准码表
  5. utf-8:基于unicode,一个字节就可以存储数据。更加标准化。

四、其它:

  1. flush:刷新资源,流还可以继续使用。close:关闭资源,流不可使用。
  2. InputStream、OutputStream、Reader、Writer都是抽象类,不能直接new。
  3. 实际操作中,字节流较为常用,但因生活中文本数据常见,因此常转为字符流操作,因而开发中常有汉字问题。
  4. 字节流、字符流两者之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String关联。
  5. 但凡键盘录入:(使用)
    BufferedInputStream fis=new BufferedInputStream(new FileInputStream(src));

End.