一.字节流
文件的续写:
利用构造方法的参数进行续写(布尔参数)
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.缓冲字节输入流