FileWriter
/**
*输入流和输出流是相对于内存设备而言
*
* 字符流的由来:
* 字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字。
* 再对这个文字进行操作,简单说:字节流+编码表
* --------------------------------------
* 字节流的两个顶层父类:
* 1.InputStream 2.OutputStream
* 这些体系的子类都以父类名作为后缀。
* 而且子类名的前缀就是该对象的功能。
*
* 字符流的两个顶层父类:
* 1.Reader 2.Writer
*/
//需求:将一些文字存储到硬盘
//记住:
public static void demo_1() throws IOException{
//创建一个可以往文件中写入字符数据的字符输出流对象
/**
* 既然是往一个文件中写入文字数据,那么在创建对象时,就必须明确该文件(用于存储数据的目的地)
* 如果文件不存在,则会自动创建。
* 如果文件存在,则会被覆盖。
*
* 如果构造函数中加入true,可以实现对文件进行续写
*/
FileWriter fw = new FileWriter("E:/1.txt",true);
/**
* 调用Writer对象中的write(String)方法,写入数据
* 其实数据写入到临时存储缓冲区中
*/
String LINE_SEPARATOR = System.getProperty("line.separator");
fw.write("hello"+LINE_SEPARATOR+"world");
/**
* 进行刷新,将目标写入到目的地中
*/
// fw.flush();
/**
* 关闭流,关闭资源 在关闭前会调用flush刷新缓存中的数据到目的地
*/
fw.close();
}
FileWriter–IO异常处理
//IO异常处理
public static void demo_2() throws IOException{
FileWriter fw = null;
try{
fw = new FileWriter("K:/1.txt",true);
String LINE_SEPARATOR = System.getProperty("line.separator");
fw.write("hello"+LINE_SEPARATOR+"world");
}
catch(IOException e){
System.out.println(e.toString()+"error");
}
finally{
if(fw!=null)
try{
fw.close();
}catch(IOException e){
throw new RuntimeException("关闭失败");
}
}
}
读取方式一
//需求:读取一个文本文件,将读取到的字符打印到控制台
//同上,找到FileReader
public static void demo_3() throws IOException{
//1.创建读取字符流对象
/**
* 在创建读取流对象时,必须要明确被读取的文件。一定要确定该文件是存在的
* 用一个读取流关联一个已存在的文件。
*/
FileReader fr = new FileReader("E:/1.txt");
//用Reader中的read方法读取字符
int ch = 0;
while((ch=fr.read())!=-1){
System.out.println((char)ch);
}
fr.close();
}
读取方式二
public static void demo_4() throws IOException{
FileReader fr = new FileReader("E:/1.txt");
/**
* 使用read(char[])读取文本文件数据
*/
char[] buf = new char[3];
// int num = fr.read(buf);//将读到的char字符存储到数组中
// System.out.println(num+":"+new String(buf));
// fr.close();
int len = 0;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fr.close();
}
将盘一个文件复制到d盘中
//作用:将盘一个文件复制到d盘中
public static void demo_1() throws IOException{
//1.读取一个已有的文本文件,使用字符读取流和文件相关联
FileReader fr = new FileReader("E:/1.txt");
//2.创建一个目的,用于存储读到数据。
FileWriter fw = new FileWriter("E:/2.txt");
//3.频繁的读写操作。
int ch = 0;
while((ch=fr.read())!=-1){
fw.write((char)ch);
}
//4.关闭流资源。
fw.close();
fr.close();
}
复制文本文件
//复制文本文件
public static void demo_2(){
FileReader fr = null;
FileWriter fw = null;
try{
fr = new FileReader("E:/1.txt");
fw = new FileWriter("E:/3.txt");
//创建一个临时容器,用于缓存读取到的字符。
char[] buf = new char[1024];
//定义一个变量记录读取到的字符数,其实就是往数组里装的字符个数
int len = 0;
while((len=fr.read(buf))!=-1){
fw.write(buf,0,len);
}
}
catch(Exception e){
System.out.println("读写失败");
}
finally{
//关闭流
if(fr!=null){
try{
fr.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(fw!=null){
try{
fw.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
字符流缓冲区BufferedWriter
//字符流缓冲区BufferedWriter
// bufw.newLine();
public static void demo_3() throws IOException{
//缓冲区的出现提高了对数据的读写效率
//对应类
//BufferedWriter :将文本写入字符输出流,缓冲各个字符,从而提供单个字符,数组和字符串的高效写入。
//可指定缓冲区的大小,也可默认
//BufferedReader :从字符输入流中读取文本,缓冲各个字符,从而实现字符,数组和行(文本特有的单位)的高效读取
//缓冲区要结合流才能使用
FileWriter fw = new FileWriter("F:/buf.txt");
//为了提高写入效率,使用了字符流缓冲区。
//创建了一个字符写入流的缓冲区对象,并和指定要被缓冲的流对象相关联
BufferedWriter bufw = new BufferedWriter(fw);
//使用缓冲区的写入方法将数据先写入到缓冲区中。
bufw.write("hello buff");
bufw.newLine();//bufw.write(System.lineSeparator());
bufw.write("xixixi");
///fw.write("hello demo");
for(int i=0;i<=4;i++){
bufw.write("abcde"+i);
bufw.newLine();
bufw.flush();
}
//使用缓冲区的刷新方法将数据刷到目的地中
// bufw.flush();
//关闭缓冲区
///fw.close();
bufw.close();//这时fw流也被关闭了
}
字符流缓冲区BufferedReader
//字符流缓冲区BufferedReader
// bufr.readLine();使用了读取缓冲区的read()方法,将读取到的字符进行缓冲并判断换行标记,将标记前的缓冲数据变成字符串返回。
public static void demo_4() throws IOException,FileNotFoundException{
FileReader fr = new FileReader("F:/buf.txt");
BufferedReader bufr = new BufferedReader(fr);
String line = null;
while((line=bufr.readLine())!=null){
System.out.println(line);
}
// char[] buf = new char[1024];
// int len = 0;
// while((len=fr.read(buf))!=-1){
// System.out.println(new String(buf,0,len));
// }
fr.close();
bufr.close();
}
字符流-缓冲区-复制文本文件
//字符流-缓冲区-复制文本文件
public static void demo_5() throws IOException{
FileReader fr = new FileReader("F:/buf.txt");
BufferedReader bufr = new BufferedReader(fr);
FileWriter fw = new FileWriter("F:/buf_copy.txt");
BufferedWriter bufw = new BufferedWriter(fw);
/*
int ch = 0;
while((ch=bufr.read())!=-1){
bufw.write(ch);
}
*/
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);//line不带换行符
bufw.newLine();
bufw.flush();
}
bufw.close();
bufr.close();
}
根据readLine()原理模拟readLine()方法
//根据readLine()原理模拟readLine()方法
//自定义读取缓冲区
/*
分析:
缓冲区中无非就是封装一个数组。
并对外提供了更多的方法对数组进行访问。
其实这些方法最终操作的都是数组的指针
缓冲的原理:从源中获取一批数据装入缓冲区中,再从缓冲区中不断取出一个一个数据,
当此次取完后,再从源中继续取一批数据进入缓冲区。
当源中的数据被取光时,用-1进行标记。
*/
class myBufferReader{
private FileReader r;
//定义一个数组作为缓冲区
private char[] buf = new char[1024];
//定义一个指针操作数组中的元素.当操作到最后一个元素后,指针应该归零。
private int pos = 0;
//定义一个计数器,用于记录缓冲区中的数据个数,当该数据减到零,就从源中继续获取数据到缓冲区中。
private int count = 0;
myBufferReader(FileReader r){
this.r = r;
}
//该方法一次从缓冲区中获取一个字符
public int myRead() throws IOException{
/*
1.从源中获取一批数据到缓冲区中.需要先做判断,计数器是不是为0
*/
if(count==0){
count = r.read(buf);
//每次获取数据到缓冲区后,角标归0
pos = 0;
}
if(count<0){
return -1;
}
char ch = buf[pos];
pos++;
count--;
return ch;
}
public String myReadLine() throws IOException{
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = myRead())!=-1){
if(ch=='\r')
continue;
//将从缓冲区读到的字符存储到缓存行数据的缓冲区中
else if(ch=='\n')
return sb.toString();
sb.append((char)ch);
}
return null;
}
public void myclose() throws IOException{
r.close();
}
}
试用myBufferReader
//试用myBufferReader
public static void demo_6() throws IOException{
FileReader fr = new FileReader("F:/buf.txt");
myBufferReader bufr = new myBufferReader(fr);
String line = null;
while((line=bufr.myReadLine())!=null){
System.out.println(line);
}
// char[] buf = new char[1024];
// int len = 0;
// while((len=fr.read(buf))!=-1){
// System.out.println(new String(buf,0,len));
// }
//fr.close();
bufr.myclose();
}
字符流-缓冲区-装饰设计模式
什么是装饰
//类
class Person{
Person(){}
public void eat(){
System.out.println("eat!");
}
}
//这个类的出现是为了增强Person
class newPerson{
private Person p;
newPerson(Person p){
this.p = p;
}
public void eat(){
System.out.println("dessert");
System.out.println("eat!");
}
}
//字符流-缓冲区-装饰设计模式
/**
* 对一组对象功能进行增强时,就可以使用该模式进行问题的解决。
*/
/*
装饰和继承都能实现一样的特点:进行功能的扩展增强。
区别:
首先有一个继承体系。
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
想要对操作动作进行效率上的提高。
按照面向对象,可以通过继承对具体的进行功能的扩展。
效率提高需要加入缓冲技术。
Writer
|--TextWriter:用于操作文本
|--BufferTextWriter:加入了缓冲技术的操作文本对象
|--MediaWriter:用于操作媒体
|--BufferMediaWriter:
这样就加入了缓冲技术,但是这样做并不理想。
如果这个体系进行功能扩展,又多了流对象,这个流要提高效率也要产生子类,
子类为提高功能进行的继承导致继承体系越来越臃肿,不够灵活。
重新思考这个问题,
既然加入都是同一种技术--缓冲,
前一种是让缓冲和具体的技术相结合。
可不可以让缓冲进行单独的封装,哪个对象需要缓冲就将哪个对象和缓冲相关联。
class Buffer{
Buffer(TextWriter w){}
Buffer(MediaWriter w){}
}
class BufferWriter extends Writer{
BufferWriter(Writer w){}
}
体系变为这样:
Writer
|--TextWriter:用于操作文本
|--MediaWriter:用于操作媒体
|--BufferWriter:用于提高效率
所以,装饰比继承灵活
特点:装饰类和被装饰类都必须所属同一个接口或者父类。
*/
public static void demo_7(){
Person p = new Person();
p.eat();
newPerson p1 = new newPerson(p);
p1.eat();
}
字符流-缓冲区-LineNumberReader
//字符流-缓冲区-LineNumberReader
public static void LineNumberReaderDemo() throws IOException{
FileReader fr = new FileReader("F:/buf.txt");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
while((line=lnr.readLine())!=null){
System.out.println(lnr.getLineNumber()+"::"+line);
}
}
字节流-操作文件基本演示
//字节流-操作文件基本演示
public static void demo_write() throws IOException{
//1.创建字节输出流对象。用于操作文件
FileOutputStream fos = new FileOutputStream("F:/buf.txt");
//2.写数据
fos.write("hello".getBytes());
fos.close();//关闭资源动作要完成
}
public static void demo_read() throws IOException{
//创建一个读取流对象。和指定文件相关联
FileInputStream fis = new FileInputStream("F:/buf.txt");
System.out.println(fis.available());
byte[] buf = new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));//这个慎用
//读数据建议使用这一种
/*
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
*/
/*
int ch;//一次读取一个字节
while((ch = fis.read())!=-1){
System.out.print((char)ch);
}
*/
}
字节流复制MP3
//字节流复制MP3
public static void demo_mp3() throws IOException{
FileInputStream fis = new FileInputStream("F:/mp.avi");
FileOutputStream fos = new FileOutputStream("F:/mp_copy.avi");
/*
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
*/
//千万别用下面这一种,效率太慢
/*
int ch;
while((ch=fis.read())!=-1){
fos.write(ch);
}
*/
fos.close();
fis.close();
}
public static void demo_mp3_2() throws IOException{
FileInputStream fis = new FileInputStream("F:/mp.avi");
BufferedInputStream bufis = new BufferedInputStream(fis);
FileOutputStream fos = new FileOutputStream("F:/mp_copy.avi");
BufferedOutputStream bufos = new BufferedOutputStream(fos);
byte[] buf = new byte[1024];
int len = 0;
while((len=bufis.read(buf))!=-1){
bufos.write(buf,0,len);
bufos.flush();
}
bufos.close();
bufis.close();
}