超牛牪犇Java之IO流(后篇)字节流&字符流&转换流&缓冲流

时间:2022-01-30 20:33:11

一.字节流

文件的续写:

利用构造方法的参数进行续写(布尔参数)

true 表示续写

FileOutputStream fos = new FileOutputStream(file, true);
fos.write("hello\n".getBytes());
fos.write("TaylorSwift\n".getBytes());

mac的换行是加 "\n"

windows的换行是加 "\r\n"

exercise1:

使用字节流 进行文件的复制(需要异常处理 并计算两种读写方式的时间)

对文件进行读写(一边读一边写)

long start = System.currentTimeMillis();
File file1 = new File("/Users/Commander/Desktop/test/123.doc");
File file2 = new File("/Users/Commander/Desktop/test/321.doc");
FileInputStream fis = null;
FileOutputStream fos = null;
try {
	fis = new FileInputStream(file1);
	fos = new FileOutputStream(file2);
	int len = 0;
	byte[] bs = new byte[1024];
	while ((len = fis.read()) != -1) {
		fos.write(bs, 0, len);
	}			
} catch (FileNotFoundException e) {
	throw new RuntimeException("文件找不到");
} catch (IOException e) {
	throw new RuntimeException("读写失败");
} finally {
	// 进行流的关闭 先关哪个都行()已经读写完毕
	if (fis != null) {
		try {
			fis.close();
		} catch (IOException e) {
			throw new RuntimeException("关闭失败");
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭失败");
				}
			}
		}
	}
}
long stop = System.currentTimeMillis();
System.out.println(stop - start);

exercise2:

将一个文件夹复制到另一个文件夹下

提示:

需要两个参数:

1.(源文件) 要被复制的文件

2.目标文件 复制到哪个文件夹下

	public static void getFile(File file1,File file2) throws IOException {
		//新文件夹的名字是源文件的名字
		//路径是目标文件的路径
		File newFile = new File(file2,file1.getName());
		newFile.mkdir();
		File[] listFiles = file1.listFiles();
		
		for (File file : listFiles) {
				if (file.isFile()) {
					//复制文件
					int num = 0;
					byte[] bs = new byte[1024];
					FileInputStream fis = new FileInputStream(file);
					//创建一个要写入的文件(拼接文件名字)
					File tempFile = new File(newFile,file.getName());
					FileOutputStream fos = new FileOutputStream(tempFile);
				while ((num = fis.read()) != -1) {
					fos.write(bs,0,num);
				}	
				fis.close();
				fos.close();
			}else {
				//文件夹 继续遍历
				getFile(file, newFile);
			}
		}
	}

exercise3:

将一个文件夹下的所有txt文件 复制到另一个文件夹下并且保存为.java文件

先写个过滤器 获取txt文件

class getTxt implements FileFilter {
        @Override
	public boolean accept(File pathname) {
		if (pathname.isDirectory()) {
			return true;
		}
		return pathname.getName().endsWith("txt");
	}	
}

写方法:

	public static void copyTxt(File src,File dest) throws IOException {
		// 遍历源文件
		//File newFile = new File(dest, src.getName());
		File[] files = src.listFiles(new getTxt());
		for (File subFile : files) {
			if (subFile.isFile()) {
				FileInputStream fis = new FileInputStream(subFile);
				// 构建写的路径
				String name = subFile.getName();
				String[] split = name.split("\\.");
				// 构建写入的文件
				File temp = new File(dest, split[0]+".java");
				FileOutputStream fos = new FileOutputStream(temp);  // 创建写的输出流
				// 读
				int len = 0;
				byte[] b = new byte[1024];
				while ((len = fis.read(b)) != -1) {
					fos.write(b, 0, len);
				}
				fis.close();
				fos.close();		
			} else {
				// 继续遍历
				copyTxt(subFile, dest);
			}
		}
	}

基本的编码格式:

mac默认使用UTF-8格式(通用编码格式)

一个中文字符 占三个字节

windows GBK格式(简体中文格式)

一个中文字符 占两个字节

二.字符流

writer(写文件) 字符输出流

reader(读文件) 字符输入流

是所有字符流的父类(抽象类)

一些方法:

//创建一个文件字符输出流
File file = new File("/Users/Commander/Desktop/test/taylor.txt");
FileWriter fw = new FileWriter(file);
//写
fw.write(65);
//刷新
//相当于写入的时候有一个缓冲区
//写的字符实际上是先写入到缓冲区
//刷新的时候才会将写的字符全部写入到文件中
//建议:写一次刷新一次
fw.flush();
//利用字符数组写入
char[] c = {'a','b','c','d'};
fw.write(c);
fw.flush();
//用字符串写入
fw.write("身无彩凤双飞翼\n");
fw.write("心有灵犀一点通\n");
fw.flush();
//关闭流资源
//关闭流资源之前 会自动刷新缓冲区
fw.close();

exercise:

利用字符流 复制文件(带异常处理)

字符流 只支持文档类

FileReader fr = null;
FileWriter fw = null;
try {
	fr = new FileReader("/Users/Commander/Desktop/test/taylor.txt");
	fw = new FileWriter("/Users/Commander/Desktop/test/swift.txt");
	//读写
	int len = 0;
	char[] c = new char[1024];
	while ((len = fr.read(c)) != -1) {
		//写
		fw.write(c, 0, len);
		//刷新
		fw.flush();
	}
} catch (FileNotFoundException e) {
	throw new RuntimeException("文件找不到");
} catch (IOException e) {
	throw new RuntimeException("读写失败");
}
finally {
	if (fr != null) {
		try {
			fr.close();
		} catch (IOException e) {
			throw new RuntimeException("关闭失败");
		}finally {
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					throw new RuntimeException("关闭失败");
				}
			}
		}
	}
}

三.转换流

 转换流

 OutputStreamWrite(字符流通向字节流的桥梁)

 1.程序中写入字符时 先使用转换流 根据转换流想查询的码表格式去查询

 2.如果查的是GBK的格式 那么一个中文字符就查到了两个字节的字节编码

 3.这个字节编码最后给到了构建转换流时 传入的字节流

 4.通过这个字节流 按字节写入到文件中

 转换流:可以查询对应的编码表

 

 转换流可以根据你想要的编码格式进行读写

 读写时可以设置编码格式

 

 构造方法(不传编码格式 默认使用的是系统的编码格式)

 1.需要字节输出流

 2.编码格式的名字(UTF-8,GBK  不区分大小写)

 

 InputStreamReader (读取文件 字节流通向字符流的桥梁)

 1.按字节读取文件 将字节编码给到转换流

 2.如果是UTF-8需要三个字节

 3.使用字符流读取到程序中


按操作系统默认格式写一个文件:

public static void getUTF8() throws IOException {
        //创建一个字节输出流
	FileOutputStream fos = new FileOutputStream("/Users/Commander/Desktop/test/UTF8.txt");
	//创建一个转换流
	OutputStreamWriter osw = new OutputStreamWriter(fos);
	//写文件
	osw.write("Taylor");
	//注意:
	//1.一般只关外层的流
	//2.自己创建的流自己关 获取系统的流不用管
	osw.close();
}

按GBK格式写入文件:

public static void getGBK() throws IOException {
	FileOutputStream fos = new FileOutputStream("/Users/Commander/Desktop/test/GBK.txt");
	OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
	osw.write("Taylor");
	osw.close();
}

按默认的UTF-8格式读文件:

public static void readByUTF8() throws IOException {
	FileInputStream fis = new FileInputStream("/Users/Commander/Desktop/test/UTF8.txt");
	InputStreamReader isr = new InputStreamReader(fis);
	int num = 0;
	char[] c = new char[1024];
	while ((num = isr.read(c)) != -1) {
		System.out.println(new String(c, 0, num));
	}
	isr.close();
}

按GBK格式读文件:

public static void readByGBK() throws IOException {
	FileInputStream fis = new FileInputStream("/Users/Commander/Desktop/test/GBK.txt");
	InputStreamReader isr = new InputStreamReader(fis,"GBK");
	int num = 0;
	char[] c = new char[1024];
	while ((num = isr.read(c)) != -1) {
		System.out.println(new String(c, 0, num));
	}
	isr.close();
}

四.缓冲流

流:就是用来读写文件的  所以就牵扯到了效率的问题

缓冲流(高效流)

  内部自带了一个缓冲区(字节数组)

  BufferedOutputStream(写文件)  缓冲字节输出流

  BufferedInputStream(读文件)  缓冲字节输入流

  

  测试缓冲流的高效

  读取同一个大文件 查看读取的时间

  模板设计模式

  1.字节输入流

   一个字节一个字节读

   使用缓冲数组来读

  2.缓冲字节输入流