【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));
}
}
}