字符流读取流
1、IO流用来处理设备之间的数据传输。
2、Java对数据的操作是通过流的方式。
3、Java用于操作流的对象都封装在IO包中。
4、流按操作数据分为两种:字节流与字符流。
5、流按流向分为:输入流,输出流。
IO 字符流的抽象基类
Reader, Writer
字节流的抽象基类
InputStream, OutputStream
注意:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
既然IO流是用于操作数据的,
那么数据的最常见体现形式是:文件。
那么先以操作文件为主来演示。
IO流(文本写入)
writer抽象类
abstract void | close() |
abstract void | flush() |
void | write(char[] cbuf) |
abstract void | write(char[] cbuf, int off, int len) |
void | write(int c) |
void | write(String str) |
void | write(String str, int off, int len) |
FileWriter类
构造方法摘要 |
FileWriter(String fileName) |
/*
需求:在硬盘上,创建一个文件并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象。FileWriter。 后缀名是父类名。 前缀名是该流对象的功能。
*/
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;
public class Test{
public static void main(String...args)throws IOException{
/*创建一个FileWriter对象,该对象一被初始化,就必须要明确被操作的文件.
而且该文件会被创建到指定目录下,如果该目录下已有同名的文件,将被覆盖。
其实该步就是明确数据要存放的目的地*/
Writer w = new FileWriter("1.Java");
/*调用writer方法,将字符串写入到流中,会抛IO异常.*/
w.write("黑马程序员——戒风");
/*刷新该流的缓冲。将数据刷新到文件中*/
//w.flush();
/*关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
将数据刷到目的地中。
和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。*/
w.close();
}
}
IO流(IO异常处理方式)
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;
public class Test{
public static void main(String...args){
Writer w = null;
try{
w =new FileWriter("1.Java");
w.write("黑马程序员——戒风");
}
catch(IOException e){
System.out.println("写入失败"+e);
}
finally{
try{
if(w!=null)
w.close();
}
catch(IOException e){
System.out.println("关闭失败"+e);
}
}
}
}
文件的续写
FileWriter类
构造方法摘要 |
FileWriter(String fileName, boolean append) |
/*
Windows中,换行是 \r\n。
Linux 是\n。
*/
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;
public class Test{
public static void main(String...args){
Writer w = null;
try{
//为true表示不覆盖已有文件,并且续写
w = new FileWriter("1.Java",true);
w.write("黑马程序员——jiefeng");
w.write("\r\n换行");
}
catch(IOException e){
System.out.println(e);
}
finally{
try{
if(w!=null)
w.close();
}
catch(IOException e){
System.out.println(e);
}
}
}
}
IO流(文本文件读取方式一)
Reader抽象类
int | read() |
abstract void | close() |
构造方法摘要 | |
FileReader(String fileName) |
import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
public class Test{
public static void main(String...args) throws IOException{
/*
创建一个文件读取流对象,和指定名称的文件相关联。
要保证该文件是已经存在的,如果不存在,会发生异常 FileNotFoundException
*/
Reader r = new FileReader("C:\\1.Java");
int ch =0;
while((ch=r.read())!=-1){
System.out.print((char)ch);
}
}
}
IO流(文本文件读取方式二)
Reader抽象类
int | read(char[] cbuf) |
import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
public class Test{
public static void main(String...args) throws IOException{
Reader r = new FileReader("C:\\1.Java");
char[]buf = new char[1024];
int len =0;
while((len=r.read(buf))!=-1){
sop(new String(buf,0,len));
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
IO流(文本文件读取练习)
import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
public class Test{
public static void main(String...args) throws IOException{
Reader r = new FileReader("1.Java");
char []buf = new char[1024];
for(int len =0;(len=r.read(buf))!=-1;){
sop(new String(buf,0,len));
}
}
public static void sop(Object obj){
System.out.println(obj);
}
}
IO流(文本文件写入练习)
import java.io.Writer;
import java.io.FileWriter;
import java.io.IOException;
public class Test{
public static void main(String...args) throws IOException{
Writer r = new FileWriter("1.Java");
for(int x=1;x<=5;x++){
r.write("戒风"+x+"\r\n");
r.flush();
}
r.close();
System.out.println(“Good!”);
}
}
IO流(拷贝文本文件)
复制的原理,其实就是将一个文件的数据存储到另一个文件中
/*
1、在C盘创建一个文件,用于存储C盘文件中的数据
2、定义读取流和C盘文件关联
3、通过不断的读写完成数据存储
4、关闭资源
*/
import java.io.IOException;
import java.io.Writer;
import java.io.Reader;
import java.io.FileWriter;
import java.io.FileReader;
public class Test{
public static void main(String... args){
Reader r =null;
Writer w =null;
try{
r = new FileReader("C:\\1.Java");
w =new FileWriter("C:\\2.Java");
char[] buf =new char[1024];
for(int len=0;(len=r.read(buf))!=-1;){
w.write(new String(buf,0,len));
}
}
catch(IOException e){
System.out.println(e);
}
finally{
try{
if(r!=null)
r.close();
System.out.println(“Good!”);
}
catch(IOException e){
System.out.println(e);
}
finally{
try{
if(w!=null)
w.close();
}
catch(IOException e){
System.out.println(e);
}
}
}
}
}
字符流的缓冲区
1、缓冲区的出现提高了对数据的读写效率。
2、对应类。
(1)、BufferedWriter
(2)、BufferedReader
3、缓冲区要结合流才可以使用。
4、在流的基础上对流的功能进行了增强。
BufferWriter
void | newLine() |
/*
缓冲区的出现是为了提高流的操作效率而出现的
所以在创建缓冲区之前,必须要先有流对象。
*/
import java.io.IOException;
import java.io.Writer;
import java.io.FileWriter;
import java.io.BufferedWriter;
public class Test{
public static void main(String...args) throws IOException{
Writer w = new FileWriter("C:\\1.Java");
/*
为了提高字符写入流的效率,加入了缓冲技术,只要将需要被提高效率的流对象作为参数传递给缓冲区的构造函数即可
*/
BufferedWriter bw = newBufferedWriter(w);
bw.write("黑马程序员");
/*
当然如果要刷新的话,当然是要刷新缓存区的flush,
因为数据写到缓冲区里面去了。
如果刷新流对象是刷不出来东西的。关闭也一样
*/
bw.newLine();
bw.write("我来了");
bw.flush();
//bw.close();
/*其实这个流可以不用关闭也行。因为缓存区必须有流,而流对象关闭了。
缓存区对象也就自动释放了*/
w.close();
System.out.println("ok!!!");
}
}
IO流(BufferedReader)
BufferedReader
String | readLine() |
readLine() 读取一个文本行。返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null ,所有要手动写入换行.
/*
字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine ,方便于对文本数据的获取
当返回 null 时,表示读到文件的末尾
readLine() 方法返回的时候只返回回车符之前的数据内容,并不返回回车符
*/
import java.io.Reader;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;
public class Test{
public static void main(String...args) throws IOException{
Reader r = new FileReader("C:\\1.Java");
/*
为了提高效率,加入缓冲技术,将字符读取流对象作为参数传递给缓冲对象的构造函数
*/
BufferedReader br = newBufferedReader(r);
for(String line = null;(line=br.readLine())!=null;){
System.out.print(line);
System.out.println();
}
}
}
IO流(通过缓冲区复制文本文件)
/*
通过缓冲区复制一个 .Java 文件
*/
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
public class Test{
public static void main(String...args){
BufferedReader br = null;
BufferedWriter bw = null;
try{
br =new BufferedReader(new FileReader("C:\\1.Java"));
bw = new BufferedWriter(new FileWriter("C:\\2.Java"));
for(String line = null;(line=br.readLine())!=null;){
bw.write(line);
bw.newLine();
bw.flush();
}
}
catch(IOException e){
throw new RuntimeException("读写失败");
}
finally{
try{
if(br!=null)
br.close();
}
catch(IOException e){
throw new RuntimeException("读取关闭失败");
}
try{
if(bw!=null)
bw.close();
}
catch(IOException e){
throw new RuntimeException("写入关闭失败");
}
System.out.println("ok!!!");
}
}
}
IO流(readLine的原理)
不论是读一行,获取多个字符,其实最终都是在硬盘上一个一个读取,所以最终使用的还是 read() 方法一次读一个的方法。
因为跨平台性,换行符不一样,所以读取的时候缓存中不存入换行,让使用者自己输入换行。
IO流(MyBufferedReader)
明白了BufferedReader 类中特有方法 readLine 的原理后,
可以自定义一个类中包含一个功能和readLine一致的方法
来模拟一下BufferedReader的readLine方法。
import java.io.IOException;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
public class Test{
public static void main(String... args) throws IOException{
Reader r = new FileReader("C:\\1.Java");
MyBufferedReader br = newMyBufferedReader(r);
for(String line =null;(line=br.myReadLine())!=null;){
System.out.print(line);
System.out.println();
}
}
}
class MyBufferedReader{
private Reader r;
MyBufferedReader(Reader r){
this.r=r;
}
public String myReadLine() throws IOException{
/*
定义一个临时容器,原BufferedReader封装的是字符数组
为了方便,定义一个StringBuilder容器,因为最终还是要将数据变成字符串
*/
StringBuilder sb = newStringBuilder ();
int len = 0;
while((len = r.read())!=-1){
if(len=='\r')
continue;
if(len=='\n')
return sb.toString();
else
sb.append((char)len);
}
//防止最后一行没有换行的情况
if(sb.length()!=0)
return sb.toString();
else
return null;
}
public void myClose() throws IOException{
r.close();
}
}
IO流(装饰设计模式)
1、当想要对已有对象进行功能增强时,可以定义一个类,将已有对象传入,基于已有的功能,并提供加强功能,那么该自定义类称为装饰类。
2、装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的功能,提供更强的功能。
(可以理解为打扮,比如自己如果要去面试的化,咱们要把自己打扮一下,把自己搞上点新鲜的衣服,但是最后还是一个人,只是身上多个点东西,这就是装饰)
IO流(装饰和继承的区别)
以前是通过继承将每一个子类都具备父类的功能。
那么继承体系会复杂,并不利于扩展。
现在优化思想。单独描述一下装饰类的内容。
将需要被装饰的对象。传递进来。也就是,谁需要被装饰,谁就作为参数传递给装饰类。
这样继承体系就变得很简单。优化了体系结构。
装饰模式比继承要灵活。避免了继承体系臃肿。
而且降低了类于类之间的关系。
装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。
所以装饰类和被装饰类通常是都属于一个体系中的。
IO流(自定义装饰类)
abstract class Person{
public abstract void chifan();
}
class Qiongren extends Person{
public void chifan(){
System.out.println("吃饭");
}
}
class Furen extends Person{
private Person p;
Furen(Person p){
this.p=p;
}
public void chifan(){
System.out.println("开胃酒");
p.chifan();
System.out.println("甜点");
System.out.println("来一根,当然我不好这口");
}
}
public class Test{
public static void main(String...args){
Qiongren q =new Qiongren();
Furen f =new Furen(q);
f.chifan();
}
}
IO流(LineNumberReader)
LineNumberReader
int | getLineNumber() |
void | setLineNumber(int lineNumber) |
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.LineNumberReader;
import java.io.IOException;
public class Test{
public static void main(String... args) throws IOException{
BufferedReader br = newBufferedReader(new FileReader("C:\\1.Java"));
LineNumberReader lnr = new LineNumberReader(br);
lnr.setLineNumber(100);
for(String line =null;(line=lnr.readLine())!=null;){
System.out.println(lnr.getLineNumber()+":"+line);
}
lnr.close();
}
}
IO流(MyLineNumberReader)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
class MyLineNumberReader{
private BufferedReader br;
private int LineNumber;
MyLineNumberReader(BufferedReader br){
this.br=br;
}
public void setLineNumber(int LineNumber){
this.LineNumber = LineNumber;
}
public int getLineNumber(){
return++LineNumber;
}
public String readLine()throws IOException{
return br.readLine();
}
public void myClose() throws IOException{
br.close();
}
}
public class Test{
public static void main(String...args) throws IOException{
BufferedReader bfr = newBufferedReader(new FileReader("C:\\1.Java"));
MyLineNumberReader my = newMyLineNumberReader(bfr);
my.setLineNumber(100);
for(String line = null;(line=my.readLine())!=null;){
System.out.println(my.getLineNumber()+":"+line);
}
my.myClose();
}
}