天天看点

J2SE(5)之IO流(字符流、缓冲流、转换流)1、字符流2、缓冲流3、中文乱码的原因

1、字符流

字符流只能用来操作纯文本,否则会破坏文件;

字符流的两个接口:Reader和Writer,对应的实现类是:FileReader和FileWriter,它们都是属于节点流。

1.1 字符流读纯文本文件

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

/**
 * 纯文本读取
 */
public class Demo01 {
	public static void main(String[] args) {
		//创建源
		File src =new File("E:/xp/test/a.txt");
		//选择流
		Reader reader =null;
		try {
			reader =new FileReader(src);
			//读取操作
			char[] flush =new char[1024];
			int len =0;
			while(-1!=(len=reader.read(flush))){
				//字符数组转成 字符串
				String str =new String(flush,0,len);
				System.out.println(str);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("源文件不存在");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("文件读取失败");
		}finally{
			try {
				if (null != reader) {
					reader.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

1.2 字符流写纯文本文件

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

/**
 * 写出文件
 */
public class Demo02 {
	public static void main(String[] args) {
		//创建源
		File dest =new File("e:/xp/test/char.txt");
		//选择流
		Writer wr =null;
		try {
			//追加文件,而不是覆盖文件
			wr =new FileWriter(dest);
			//写出
			String msg ="锄禾日当午\r\n码农真辛苦\r\n一本小破书\r\n一读一上午";
			wr.write(msg);
			wr.append("倒萨发了看电视剧 ");
			
			wr.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				if (null != wr) {
					wr.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

2、缓冲流

缓冲流也称之为处理流,用来增强功能、提供性能,包装了节点流(使用了装饰者设计模式)。

1、字节缓冲流:BufferedInputStream和BufferedOutputStream;

2、字符缓冲流:BufferedReader(它有新方法;readLine() )和BufferedWriter(它有新方法:newLine() )。

2.1 字节缓冲流拷贝文件

使用方式:new 缓冲流(new 节点流);

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
 * 字节流文件拷贝+缓冲流 ,提高性能
 * 缓冲流(节点流)
 */
public class BufferedByteDemo {
	public static void main(String[] args) {
		
	}
	/**
	 * 文件的拷贝
	 * @param  源文件路径
	 * @param  目录文件路径
	 * @throws FileNotFoundException,IOException
	 * @return 
	 */
		public static void copyFile(String srcPath,String destPath) throws FileNotFoundException,IOException {
			//1、建立联系 源(存在且为文件) +目的地(文件可以不存在)  
			File src =new File(srcPath);
			File dest =new File(destPath);
			if(! src.isFile()){ //不是文件或者为null
				System.out.println("只能拷贝文件");
				throw new IOException("只能拷贝文件");
			}
			//2、选择流
			InputStream is =new BufferedInputStream(new FileInputStream(src));
			OutputStream os =new BufferedOutputStream( new FileOutputStream(dest));
			//3、文件拷贝   循环+读取+写出
			byte[] flush =new byte[1024];
			int len =0;
			//读取
			while(-1!=(len=is.read(flush))){
				//写出
				os.write(flush, 0, len);
			}
			os.flush(); //强制刷出
			
			//关闭流
			os.close();
			is.close();
		}
}
           

2.2 字符缓冲流拷贝文件

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
 * 字符缓冲流 +新增方法(不能发生多态)
    拷贝的时候可能出现中文乱码,乱码的原因:文件的编码和我们当前的eclipse使用的编码方式不同。
 */
public class BufferedCharDemo {
	public static void main(String[] args) {
		//创建源 仅限于 字符的纯文本
		File src =new File("E:/xp/test/Demo03.java");
		File dest =new File("e:/xp/test/char.txt");
		//选择流
		BufferedReader reader =null;	//因为要使用处理流的readLine方法,所以不能多态	
		BufferedWriter wr =null; //因为要使用处理流的newLine方法,所以不能多态	
		try {
			reader =new BufferedReader(new FileReader(src));
			wr =new BufferedWriter(new FileWriter(dest));
			//读取操作
			/*
			char[] flush =new char[1024];
			int len =0;
			while(-1!=(len=reader.read(flush))){
				wr.write(flush, 0, len);
			}*/
			//新增方法的操作
			String line =null;
			while(null!=(line=reader.readLine())){
				wr.write(line);
			//wr.append("\r\n");
				wr.newLine(); //换行符号
			}
			wr.flush();//强制刷出
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			System.out.println("源文件不存在");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("文件读取失败");
		}finally{
			try {
				if (null != wr) {
					wr.close();
				}
			} catch (Exception e2) {
			}
			try {
				if (null != reader) {
					reader.close();
				}
			} catch (Exception e2) {
			}
		}
	}
}
           

3、中文乱码的原因

编码:字符——》字节,这个过程就是编码,编成程序可以读懂的

解码:字节——》字符,这个过程就是解码,解成我们能读懂的。

那么乱码的原因是什么呢?

1、编解码的字符集不统一会造成中文乱码,比如:文件的字符集是gbk,而eclipse的字符集是utf-8,那么通过流把文件的内容读取并打印到控制台,就会出现乱码。

2、字节缺少,长度丢失,导致乱码,比如:文件中本来有“中国”两个汉字,应该是4个字节,而我们读取的时候只读取了3个字节,那么 国 就会出现乱码。

public class ConverDemo01 {

	/**
	 * @param args
	 * @throws UnsupportedEncodingException 
	 */
	public static void main(String[] args) throws UnsupportedEncodingException {
		String str ="中国";
		byte[] data =str.getBytes();
		//字节数不完整
		System.out.println(new String(data,0,3));	
	}
	/**
	 * 编码与解码字符集必须相同,否则乱码
	 * @throws UnsupportedEncodingException 
	 */
	public static void test1() throws UnsupportedEncodingException{
		//解码 byte -->char
		String str ="中国"; //假设eclipse默认字符集是gbk 
		//编码 char -->byte
		byte[] data =str.getBytes();
		//编码与解码字符集同一
		System.out.println(new String(data));
		data =str.getBytes("utf-8"); //设定编码字符集
		//编解码字符集不统一出现乱码
		System.out.println(new String(data));
				
		//编码
		byte[] data2 = "中国".getBytes("utf-8");
		//解码
		str=new String(data2,"utf-8");
		System.out.println(str);
	}
}
           

4、转换流

转换流的作用:把字节流转成字符流;

因为我们在用字符流进行文件读取写出的时候,当字符集不一致就会出现中文乱码,所以我们引入转换流,它可以指定编解码的字符集。

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

/**
 * 转换流: 字节转为字符
 * 1、输出流 OutputStreamWriter 编码
 * 2、输入流 InputStreamReader  解码
 * 
 * 确保源不能为乱码
 */
public class ConverDemo02 {
	public static void main(String[] args) throws IOException {
		//指定解码字符集
		BufferedReader br =new BufferedReader(
				new InputStreamReader(
					new BufferedInputStream(
							new FileInputStream( 
									new File("E:/xp/test/Demo03.java"))),"UTF-8")
				);
		//写出文件 编码
		BufferedWriter bw =new BufferedWriter(
				new OutputStreamWriter(
					new BufferedOutputStream(	
					new FileOutputStream(new File("E:/xp/test/encode.java")))));				
		String info =null;
		while(null!=(info=br.readLine())){
			//System.out.println(info);
			bw.write(info);
			bw.newLine();
		}
		bw.flush();
		bw.close();
		br.close();
	}
}