-------android培训、java培训、期待与您交流! ----------
流的概念:
数据流是一串连续不断的数据的集合,就像水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流.
数据写入程序可以使一段一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流.
Java中IO流:
1,在程序中所有的数据都是以流的方法进行传输和保存的。
2,Java 的IO是实现输入和输出的基础。
3,Java把所有传统的流类型(类或抽象类)都放在java.io包中,用以实现输入输出功能。
4,输入和输出是一个相对的概念,我们一般站在程序的角度来分析和处理问题的。
程序需要数据 --> 读进来 --> 输入
程序保存数据 --> 写出去 --> 输出
流的分类: 按流动方向的不同可以分为输入流和输出流;
按处理数据的单位不同分为字节流和字符流;
流的常用基类:
字节流的抽象基类:InputStream ,OutputStream。
字符流的抽象基类:Reader , Writer。
注:由这四个类派生出来的子类名称都是以其父类名作为子类名的后缀。
如:InputStream的子类FileInputStream。
如:Reader的子类FileReader。
操作流对象的步骤:
File类本身是与文件操作有关,但是如果要想操作内容则必须使用字节流或字符流完成,但是不管是使用何种的输入输出流,其基本的操作原理是一样的(以文件流为准):
1, 使用File类找到一个文件对象,得到IO操作的源或目标
2,通过字节流或字符流的子类创建对象,(得到IO操作的通道)
3,进行读或写的操作,(IO操作)
4,关闭输入/输出,(注意节约资源,关掉)
注意:由于流的操作属于资源操作,所以在操作的最后一定要关闭以释放资源。
1,用字符流创建文件:
创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("src\\IO\\tempfile\\demo.txt");
调用流对象的写入方法,将数据写入流
fw.write(“csdn-itcast”);
关闭流资源,并将流中的数据清空到文件中。
fw.close();
注意:1,定义文件路径时,可以用“/”或者“\\”。
2,在创建一个文件时,如果目录下有同名文件将被覆盖。
代码演示:
public static void writerMethd_1() throws IOException {
FileWriter fw = new FileWriter("src\\IO\\tempfile\\demo.txt");
//写入数据
fw.write("csdn-itcast");
// //必须刷新文件中才能显示数据,因为数据是写到了临时缓冲区中
// fw.flush();
//关闭资源,也有刷新的功能。
fw.close();
}
这里要区分flush()和close()的区别:
flush():仅将缓冲中的数据刷到目的地,流对象可以继续使用。
close():将缓冲区中的数据刷新到目的地后,关闭流资源,不可以再对流进行操作了。
2,用字符流读取文件:
建立一个流对象,和指定的文件数据关联。
FileReader fr = new FileReader(“Test.txt”);
创建一个临时存放数据的数组。
char[] buf = new char[1024];
调用流对象的读取方法将流中的数据读入到数组中。
fr.read(buf);
注意:在读取文件时,必须保证该文件已存在,否则出异常。
代码演示:
public static void readerMethod_2() throws IOException {
FileReader fr = new FileReader("src\\IO\\tempfile\\demo.txt");
char[] buf = new char[1024];
int len = 0 ;
while((len=fr.read(buf))!=-1){
System.out.println(new String(buf,0,len));
}
fr.close();//一定要关闭资源
}
字符流缓冲区:
好处:缓冲区的出现提高了对数据的读写效率。
相对应类:
BufferedWriter
BufferedReader
注意:缓冲区要结合流才可以使用。它是在流的基础上对流的功能进行了增强。
范例:通过缓冲区复制一个文本文件,代码如下
public static void copyByBufferedMethod() {
BufferedReader bufr = null ;
BufferedWriter bufw = null ;
try {
bufr = new BufferedReader(new FileReader("src\\IO\\tempfile\\demo1.txt"));
bufw = new BufferedWriter(new FileWriter("src\\IO\\tempfile\\copy_demo1.txt"));
String line = null;
while((line=bufr.readLine())!=null){
bufw.write(line);
}
} catch (IOException e) {
System.out.println(e.toString());
}finally{
if(bufw!=null)
try {
bufw.close();
} catch (IOException e) {
throw new RuntimeException("写入流关闭失败");
}
if(bufr!=null)
try {
bufr.close();
} catch (IOException e) {
throw new RuntimeException("读取流关闭失败");
}
}
}
所以有了缓冲区就不用再自己定义缓冲区了,可以减少代码的书写。不过为了更好的提高效率还是可以在缓冲区中自定义一个缓冲区。
装饰设计模式:
解决的问题:给已有的对象提供增强额外的功能。对原有类进行了功能的改变,增强。
与继承的区别:它比继承更加灵活
假如现有一个体系用于各种数据的写入。如,
Writer
|--TextWriter
|--MediaWriter
但是,发现写入效率有点低。想要对其进行效率的提高。 这时就可以使用缓冲技术来完成的。
对于已有对象中的写入方法,不够高效,可以通过派生子类的形式对其进行复写,定义高效的写入动作。如,
Writer
|--TextWriter
|--BufferTextWriter
|--MediaWriter
|--BufferMediaWriter
|--DataWriter
|--BufferDataWriter
这种方式其实是通过继承的方式提高了效率。但是对于扩展性是一个问题。而且所需的功能越多,子类就越多。
一旦加入新类,就需要为它提供高效。显得很麻烦!
这时我们可以将缓冲技术单独进行封装。哪个对象需要缓冲,就把哪个对象传递给缓冲对象即可。如,
class Buffer{
Buffer(TextWriter w){
}
Buffer(MediaWriter w){
}
}
为了便于扩展,可以对一组对象进行缓冲。
class BufferWriter extends Writer{
Buffer(Writer w){
}
public void write(){
}
}
这时体系就变成了这样:
Writer
|--TextWriter
|--MediaWriter
|--BufferWriter
BufferWriter的出现,增强了Writer体系中的功能,这种设计方式比原理更为灵活,避免了继承的臃肿。这种方式就称作装饰设计模式。
记住:装饰类和被装饰类都所属于同一个体系。
代码演示:
public class DecoratorDemo {
public static void main(String[] args) {
Person p = new Person();
SuperPerson sp = new SuperPerson(p);
sp.eat();
}
}
class Person{
public void eat(){
System.out.println("吃饭");
}
}
//对吃饭的功能进行增强
class SuperPerson{
private Person p ;
public SuperPerson(Person p) {
this.p = p ;
}
public void eat(){
System.out.println("开胃酒");
p.eat();
System.out.println("甜点");
}
}
字节流:InputStream,OutputStream
基本操作与字符流类相同
但它不仅可以操作字符,还可以操作其他媒体文件
字节流操作细节:
字节流的直接操作文件写入时,直接将数据写入到目的地不需要刷新。
字节流缓冲区:同样是提高了字节流的读写效率。
通过字节流缓冲区来复制一个mp3文件,代码演示:
public static void copyByStreamMethod() {
BufferedInputStream bufis = null ;
BufferedOutputStream bufos = null ;
try {
bufis = new BufferedInputStream(new FileInputStream("src\\IO\\tempfile\\Lonely.mp3")) ;
bufos = new BufferedOutputStream(new FileOutputStream("src\\IO\\tempfile\\copy_Lonely1.mp3")) ;
int len1 = 0 ;
while((len1=bufis.read())!=-1){
bufos.write(len1);
}
} catch (IOException e) {
System.out.println(e.toString());
}finally{
if(bufos!=null)
try {
bufos.close();
} catch (IOException e) {
throw new RuntimeException("输出关闭失败");
}
if(bufis!=null)
try {
bufis.close();
} catch (IOException e) {
throw new RuntimeException("输入关闭失败");
}
}
}
读取键盘录入:
也就是将数据源变成了键盘: InputStream in = System.in;
为了处理文字数据方便,将字节数据转成字符数据:InputStreamReader isr = new InputStreamReader(in);
为了提高了读取的效率,使用缓冲区:BufferedReader bufr = new BufferedReader(isr);
简化书写,键盘录入的代码就是:
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
注意:系统中获取的流对象都是唯一的,如果将其关闭,就不能在使用了。所以一般情况下,从System获取到的流对象,不需要关闭。它会随着程序的停止而结束。
将IO流中数据打印在显示器上:
也就是将数据目的变成了控制台:OutputStream out = System.out;
因为要打印到显示器上的数据都是文字数据,所以必须将这些文字数据转成字节数据,具备这个功能的对象是OutputStreamWriter: OutputStreamWriter osw = new OutputStreamWriter(out);
为了提高写入的效率,使用缓冲区:BufferedWriter bufw = new BufferedWriter(osw);
简化书写,输出到控制台的代码就是:
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
注意:一般读取键盘录入一定要定义一个结束标记。
读取键盘录入演示:
public static void methodDemo() throws IOException{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw =
new BufferedWriter(new OutputStreamWriter(System.out));
String line = null ;
while((line=bufr.readLine())!=null){
if("over".equals(line))//定义结束标记
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
//因为是从System获取的流可以不关闭,随着系统的结束而结束。
bufw.close();
bufr.close();
}
转换流:
字节流--->字符流的桥梁。InputStreamReader
字符流--->字节流的桥梁。OutputStreamWriter
转换流的由来:
字符流与字节流之间的桥梁
方便了字符流与字节流之间的操作
转换流的应用:
字节流中的数据都是字符时,转成字符流操作更高效。
其实在键盘录入和读取的时候我们已经用到了转换流,转换流代码演示:
public static void transStreamDemo() throws IOException{
/*
* 从键盘读取数据,转成大写,显示在屏幕上。
*/
InputStream in = System.in;
//为了处理文字数据方便。将字节数据转成字符数据.这个功能在转换流中。InputStreamReader
InputStreamReader isr = new InputStreamReader(in);
BufferedReader bufr = new BufferedReader(isr);
OutputStream out = System.out;
//因为要打印到显示器上的数据都是文字数据。所以必须将这些文字数据转成字节数据。具备这个功能的对象是OutputStreamWriter.
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);
}
流的基本应用小节:
1,流是用来处理数据的。
2,处理数据时,一定要先明确数据源,与数据目的地。
3,数据源可以是文件,可以是键盘。
4,数据目的地可以是文件、显示器或者其他设备。
5,而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理.转换处理等。
---------------------------------------------- android培训、java培训、期待与您交流! ------------------------------------------------