欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-03-06 10:40:55
...

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 简单提几点: 

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

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(合并/顺序)流

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

贴个小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));
		}
	}
}