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