IO流一

-------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培训、期待与您交流! ------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值