今日内容:字符流,转换流,输出流
字符流
原理:字节流+编码表。当用字符流操作字符数据时,会根据当前系统默认的码表,找到字符对应的整数形式,最终转为二进制数据,使用字节流将字节数据进行读写操作。
Reader:用于读取字符流的抽象类。子类有转换流(InputStreamReader)和字符输入流(FileReader)。方法和字节输入流相似。
Writer:写入字符流的抽象类。子类有转换流(OutputStreamWriter)和字符输出流(FileWriter),方法和字节输出流相似。
import java.io.FileWriter;
import java.io.IOException;
public class Demo5 {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("D:\\aaaa.txt", true);// 添加,不删除原内容
fw.write("\r\nabc");// "\r\n"为换行标志
fw.close();//一定要关闭输出流
System.out.println("Done!");
}
}
读取字符流数据:
import java.io.FileReader;
import java.io.IOException;
public class Demo1 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("D:\\aa.txt");// 字符输入流
char[] ch = new char[1024];
int len = 0;
while ((len = fr.read(ch)) != -1) {
System.out.println(new String(ch, 0, len));//转换为字符串输出
}
fr.close();//闭流
}
}
对比字符流和字符缓冲流的效率:
//对比FileReader和BufferedFileReader的效率问题
public class Demo2 {
public static void main(String[] args) throws IOException {
long start=System.currentTimeMillis();
FileReader fr=new FileReader("D:\\i have a dream.txt");//读取文件
FileWriter fw=new FileWriter("D:\\aa.txt");
char[] ch=new char[1024];
int len=0;//读取的字符个数
while((len=fr.read(ch))!=-1){
fw.write(ch, 0, len);
}
long end=System.currentTimeMillis();
long time=end-start;
fr.close();
fw.close();
System.out.println("本次复制共花了"+time+"毫秒");
}
}
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//BufferedReader的效率
public class Demo3 {
public static void main(String[] args) throws IOException {
long start=System.currentTimeMillis();
BufferedReader br=new BufferedReader(new FileReader("D:\\i have a dream.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\abc.txt"));
char[] ch=new char[1024];
int len=0;
while((len=br.read(ch))!=-1){
bw.write(ch,0,len);
}
// String len=null;
// while((len=br.readLine())!=null){
// bw.write(len);
// bw.newLine();
// }
br.close();
bw.close();
long end=System.currentTimeMillis();
long time=end-start;
System.out.println("本次复制花了"+time+"毫秒");
}
}
同样的,他也有缓冲流:
BufferedReader:字符缓冲输入流。特有方法:readLine():返回值为String,读取一行数据,返回一行内容中不包括行终止符,辅导末尾返回null
BufferedWriter:字符缓冲输入流。特有方法:newLine():跨平台的换行符,可以实现换行操作;
转换流:
进行读写操作,两边编码不一样是使用。
InputStreamReader(InputStream , String CharSetName):输入字符转换流。括号内必须有两个参数,一个是输入流对象(字符或字节都可以),一个是要转换的编码集。
outputStreamWriter(outputStream , String CharSetName):输出字符转换流。括号内必须有两个参数,一个是输出流对象(字符或字节都可以),一个是要转换的编码集。
//import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
//import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
//输入转换流
public class Demo4 {
public static void main(String[] args) throws IOException {
// FileInputStream fis=new FileInputStream("D:\\ii.txt");
FileReader fr=new FileReader("D:\\ii.txt");//字符输入流
FileOutputStream fos=new FileOutputStream("D:\\ATT.txt");//字节输出流
//转换成utf-8+bom格式
// InputStreamReader isr=new InputStreamReader(fis);
OutputStreamWriter osw=new OutputStreamWriter(fos, "utf-8");//指定编码表
//读取
char[] ch=new char[1024];
int len=0;//每次读取的字符数
while((len=fr.read(ch))!=-1){
osw.write(ch,0,len);
}
osw.close();
fr.close();
System.out.println("----");
}
}
输出流练习
需求:将指定目录和子目录下的指定扩展名(.txt)的文件所在路径写到一个文件中,形成一个文件清单。
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
/*将指定目录及其子目录下的文件按照扩展名筛选,将其路径写到一个文件中,形成一个文件清单。涉及知识点:
集合,输入输出流*/
public class Demo10 {
public static void main(String[] args) throws IOException {
File file=new File("D:\\test1");//文件源
/*输出源,OutputStream是个抽象类必须用他的子类方法创建对象,同时我们操作的字符输出流Writer是个抽象类,所以我们用他的
子类OutputStreamWriter,而他创建对象的时候构造方法需要一个输出流对象,这就是我们创建fos的原因*/
FileOutputStream fos=new FileOutputStream("D:\\abc.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos, "utf-8");
/*这里我们需要用到BufferedWriter中的换行方法,所以此处声明一个bw的对象,同样的,他需要一个writer(字符输出流)对象,
所以fos是不能用的,这就是我们要创建osw的原因*/
BufferedWriter bw=new BufferedWriter(osw);
/*创建Demo10的匿名对象调用它的非静态方法,尽量不用静态,这里传入的list不用再定义,因为已经定义了一个静态的了,
可以被公用,list仅仅是一个容器,作用没有file大*/
new Demo10().print(file,list);
for(String s:list){//遍历数组,输出的都是字符串,正好我们可以直接拿这些字符串写入文件中
bw.write(s);//字符串可以直接写,不用再转换成字符数组啦!
bw.newLine();//这是我们为什么用bw方法的原因-换行,否则osw就够用了
}
bw.close();//记住一定要关流
System.out.println("Done!");
}
//定义一个数组用来接收返回的文件夹名字,定义成成员变量,这样递归的时候就不会再创建一次了,要创建成静态的
static ArrayList<String> list=new ArrayList<>();
public ArrayList<String> print(File file,ArrayList<String> list){
File[] files=file.listFiles();//定义一个File数组用来获取所有的文件夹和文件名
for (int i = 0; i < files.length; i++) {
if(files[i].isDirectory()){
print(files[i],list);
}else{
String path=files[i].getPath();
list.add(path);
}
}
return list;
}
}
过滤器方法:
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
class MyF implements FileFilter{//自定义过滤器
@Override
public boolean accept(File pathname) {//pathname:要测试的路径名
// System.out.println(pathname);
return pathname.getName().endsWith("txt");//判断是否符合条件,传入listFiles的重载方法中
}
}
public class Demo5 {
public static void main(String[] args) throws IOException {
File dir=new File("d:\\test1");
FileOutputStream fos=new FileOutputStream("D:\\文件清单.txt");
getListFile(dir,fos);
fos.close();
/*返回抽象路径名数组,这些路径名表示此抽象路径名表示的目录中满足指定过滤器的文件和目录。除了返回数组中的路径名必须满足
过滤器外,此方法的行为与 listFiles() 方法相同。如果给定 filter 为 null,则接受所有路径名。否则,当且仅当在路径名上
调用过滤器的 FileFilter.accept(java.io.File) 方法返回 true 时,该路径名才满足过滤器。*/
File[] files = dir.listFiles(new MyF());//listFiles的重载形式,传入过滤器,符合条件的进入遍历环节
for (File file : files) {
System.out.println(file+"----");
}
}
public static void getListFile(File dir,FileOutputStream fos)throws IOException{
File[] files=dir.listFiles(new FileFilter(){//匿名内部类,传入一个过滤器,将符合条件的数据存入File数组
public boolean accept(File pathname){//pathname传入的路径名,具体看上面
return (pathname.isDirectory()) || ((pathname.isFile())
&& pathname.getName().endsWith(".txt"));
}
});
if(files!=null){
for(File file:files){
if(file.isDirectory()){
getListFile(file,fos);
}else{
System.out.println(file);
String path=file.getAbsolutePath()+System.getProperty("line.separator");
fos.write(path.getBytes());
}
}
}
}
}