【java基础】IO-Part3-字符流

1.字节流一般用于操作二进制文件,字符流一般用于汉字或者一些特殊符号的操作,可以防止乱码的出现.

2.一般能用记事本打开的都是文本文件,否则大多数情况都是二进制文件.

3.如果不清楚文件是哪种类型的,建议用字节流,字符流只是字节流的一种补充.

4.字符流读取文件内容的方法与字节流类似,也是分四步走,贴个小DEMO.

/**
 * 演示字符流的读取
 *
 */
public class FileReadDemo {

	public static void main(String[] args) throws Exception {
		//1.创建源 水井
		File file = new File("file/srcFile.txt");
		//2.创建流对象 水管
		FileReader fr = new FileReader(file);
		//3.具体操作
		int len = -1;
		char[] buffer = new char[1024];
		while((len = fr.read(buffer))!=-1) {
			System.out.println(new String(buffer,0,len));
		}
		//4.关闭资源
		fr.close();
	}

}

5.关于flush 简单提几点: 

6.编码和解码出现乱码的问题解决:

因为国籍的不同,加上服务器一般默认使用的是国外的编码方式,汉语比较容易出现乱码,为了解决这个问题,可以先将乱码的文件用国外的编码方式进行解码,解码后得到一个byte数组,再通过该byte数组队重新解码,解码时使用中文编码时的方式,即可还原数据,贴个小DEMO.

public class EncodingDemo {
	public static void main(String[] args) throws Exception {
		byte[] b = "老汉".getBytes("utf-8");//先用Utf-8编码
		System.out.println(Arrays.toString(b));
		System.out.println(new String(b,"GBK"));//用GBK去解码,会出现乱码.
		String lw = new String(b,"iso8859-1");//用老外的方式解码,出现乱码
		System.out.println(lw);
		byte[]b2 = lw.getBytes("iso8859-1");//可以先用老外的方式进行编码,恢复成byte数组
		System.out.println(Arrays.toString(b2));
		System.out.println(new String(b2,"utf-8"));//重新用utf-8去解码即可恢复
	}

}

6.字节缓冲流(BufferdInputStream/BufferedOutputStream)

字节缓冲流属于包装流,可以理解为在原来的水管上面又包装了一层,可以使原来的水管更粗,流量更大,更好用,关闭资源时只需要关闭包装流即可,既然是在原来的基础上做包装,所以在创建包装流对象时应先创建输入/输出流对象,在输入/输出流对象的基础上再创建缓冲流,贴个小Demo供参考:

/**
 * 演示输入输出包装流
 */
public class BufferdDemo {

	public static void main(String[] args) throws Exception {
		//输出
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("file/BufFile",true));
		bos.write("laohan".getBytes());
		bos.close();
		//输入
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("file/BufFile"));
		byte[] buffer = new byte[1024];
		int len = -1;
		while((len = bis.read(buffer)) != -1) {
			System.out.println(new String(buffer,0,len));
		}
	}

}

7.字符缓冲流(BufferedReader,BufferedWriter)

与字节缓冲流其实没啥大差别,就是把BufferedInputStream和BufferedOutputStream分别换成了BuffedReader和BufferedWriter而已,适用于读取字符,尤其是有中文的情况下,可以防止乱码.

8.字节缓冲流和普通字节流的性能对比(测试发现,使用缓冲流后性能碉堡了!!!贴个DEMO供大家欣赏)

/**
 * 演示字节输入输出流 与 它们对应的包装流的性能比较
 */
public class NodeStreamVsBufferedStream {

	public static void main(String[] args) throws Exception {
		File src = new File("file/1.课程介绍.mp4");//这个视频文件7MB左右
		File dest = new File("target/课程介绍.mp4");
//		test1(src,dest);
//		test2(src,dest);
		test3(src,dest);
		
	}

	private static void test3(File src, File dest) throws Exception {
		Long begin = System.currentTimeMillis();
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest));
		int len = -1;
		byte[] buffer = new byte[1024];//一般定义1024,可以根据业务场景去做调整,我换成8192,81920,1024000等都测过了,并非越大或者越小越快,一般情况下默认1024就好
		while((len = bis.read(buffer)) != -1) {
			bos.write(buffer, 0, len);
		}
//		while((len=bis.read())!=-1) {
//			bos.write(len);
//		}
		bis.close();
		bos.close();
		Long end = System.currentTimeMillis();
		System.out.println("总耗时:"+(end-begin)+"毫秒");//使用包装流后总耗时:2337毫秒,已经很快乐,然后对包装流的数据进行再次封装更牛逼 快的不行了总耗时:101毫秒
	}

	private static void test2(File src, File dest) throws Exception {
		Long begin = System.currentTimeMillis();
		InputStream in = new FileInputStream(src);
		OutputStream out = new FileOutputStream(dest,true);
		byte[] buffer = new byte[1024];
		int len = -1;
		while((len = in.read(buffer)) != -1) {
			out.write(buffer, 0, len);
		}
		Long end = System.currentTimeMillis();
		System.out.println("总耗时:"+(end-begin)+"毫秒");//快非常多 总耗时:272毫秒
	}

	private static void test1(File src, File dest) throws Exception {
		Long begin = System.currentTimeMillis();
		InputStream in = new FileInputStream(src);
		OutputStream out = new FileOutputStream(dest,true);
		int len = -1;
		while((len = in.read())!=-1) {
			out.write(len);
		}
		out.close();
		in.close();
		Long end = System.currentTimeMillis();
		System.out.println("总耗时:"+(end-begin)+"毫秒");//实在是太慢了,简直就是渣渣,等的我以为我代码写错了,总耗时:247154毫秒
	}
}

因此,在以后使用IO时,尽量使用包装流,提高IO性能.

9.字节流转成字符流,用的比较少,一般涉及到中文时会用到.只需要将FileInputStream转InputStreamReader,FileOutputStream转成OutputStreamWriter即可,其他操作与字节流类似,贴个小demo:

public static void main(String[] args) throws Exception {
		                //1.创建源/目的地(水井)
				File srcFile = new File("file/srcFile.txt");
				File destFile = new File("file/destFile.txt");
				Reader in = new InputStreamReader(new FileInputStream(srcFile),"GBK");
				Writer out = new OutputStreamWriter(new FileOutputStream(destFile),"GBK");
				//3.具体的IO操作
				char[] buffer = new char[1024];
				int len = -1;
				while((len = in.read(buffer)) != -1) {
					System.out.println(new String(buffer,0,len));
					out.write(buffer, 0, len);
				}
				//4.关闭资源
				in.close();
				out.close();
			}

10.字节数组缓冲流,字符数组缓冲流,字符串流(了解即可,安卓里会用到),本质是内存流,数据从内测->程序,从程序->内存.

ByteArrayInputStream,ByteArrayOutputStream,CharArrayInputStream,ByteArrayOutputStream,StringReader,StringWriter; 把数据临时存放在数组/字符串中,本质上是存在内存中.

11.合并流(当输入流有2个及两个以上时可以考虑合并流,合并后再传输),如图:我需要将文件1和文件2合并后再传输,而且保持顺序,这个时候就需要用SequenceInputStream(合并/顺序)流

贴个小DEMO给你们LOOK LOOK...

/**
 * 演示合并流
 */
public class SequenceIoDemo {

	public static void main(String[] args) throws Exception {
		SequenceInputStream in = new SequenceInputStream(new FileInputStream("file/writerFile"),new FileInputStream("file/writerFile2"));
		int len = -1;
		byte[] buffer = new byte[1024];
		while((len = in.read(buffer)) != -1) {
			System.out.println(new String(buffer,0,len));
		}
	}
}

猜你喜欢

转载自blog.csdn.net/lovexiaotaozi/article/details/81033068