黑马程序员--IO流

--------------android培训java培训、学习型技术博客、期待与您交流! --------------

IO流的四个基类

   A:字节流
   输入流
InputStream
|--FileInputStream
  输出流
OutputStream
|--FileOutputStream
   B:字符流
  输入流
 Reader
|--FileReader

  输出流
  Writer
|--FileWriter
为了提高读写效率,加入了缓冲技术
字符流:(BufferedReader和BufferedWriter)
字节流:(BufferedInputStream和BufferedOutputStream)

 复制文本代码

package Demo;

/*需求:复制文本文件

 分析:源:用Reader或者InputStream    
          操作的是硬盘上的纯文本数据用Reader           
          加入缓冲技术用BufferedReader   

     目的:用Writer或者OutputStream  
          操作的是硬盘上的纯文本数据用Writer             
          加入缓冲技术用BufferedWriter

 */

import java.io.*;

public class CopyTxt {
	public static void main(String[] args) {
		BufferedReader bur = null;
		BufferedWriter buw = null;
		try {
			bur = new BufferedReader(new FileReader("D:\\work.txt")); // 提高效率,定义读取流缓冲区
			buw = new BufferedWriter(new FileWriter("C:\\123.txt")); // 提高效率,定义写入流缓冲区
			String line = null;
			while ((line = bur.readLine()) != null) { // 读取一行数据
				buw.write(line);
				buw.newLine(); // 换行
				buw.flush(); // 刷新,将缓冲区的数据保存到文件里。使用缓冲区一定记着刷新
			}
			System.out.println("复制成功");
		} catch (Exception e) {
			throw new RuntimeException("复制失败");

		} finally {
			try {
				if (bur != null)
					bur.close(); // 关闭读取流
			} catch (Exception e) {
				throw new RuntimeException("读取流关闭失败");
			}
			try {
				if (buw != null)
					buw.close(); // 关闭写入流
			} catch (Exception e) {
				throw new RuntimeException("写入流关闭失败");
			}
		}
	}
}


 

需求:复制一张图片

分析:

源:用Reader或者InputStream    

       操作的是硬盘上的非纯文本数据用InputStream         

        加入缓冲技术用BufferedInputStream   

目的:用Writer或者OutputStream 

      操作的是硬盘上的纯文本数据用OutputStream            

      加入缓冲技术用BufferedOutputStream

package Demo;

import java.io.*;

public class CopyPic {
	public static void main(String[] args) {
		BufferedInputStream br = null;
		BufferedOutputStream bw = null;
		try {
			bw = new BufferedOutputStream(new FileOutputStream("D:\\123.jpg"));
			br = new BufferedInputStream(new FileInputStream("C:\\abc.jpg"));
			int len = 0;
			while ((len = br.read()) != -1) { // 从输入流中读取下一个字节
				bw.write(len);
				bw.flush();
			}
		} catch (Exception e) {
			throw new RuntimeException("复制失败");
		} finally {
			try {
				if (br != null) {
					br.close();
				}
			} catch (Exception e) {
				throw new RuntimeException("读取流关闭失败");
			}
			try {
				if (bw != null) {
					bw.close();
				}
			} catch (Exception e) {
				throw new RuntimeException("写入流关闭失败");
			}
		}
		System.out.println("复制成功");
	}
}


装饰模式

               装饰模式比继承要灵活,而且降低了类于类之间的关系。避免了继承体系臃肿。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能,所以装饰类和被装饰类通常是都属于一个体系中的。
          给已有的对象提供增强额外的功能。还不用对原有对象进行修改

             装饰模式在IO中的应用,写入文件用的FileWriter,发现这个类的功能不够强大装饰类出现了BufferedWriter,增强原有FileWriter的功能,在原有FileWriter的基础上,增加了一个新的方法newLine(),但是BufferedWriter写一行的方法,底层用的还是FileWriter的方法BufferedWriter构造方法  BufferedWriter(Writer out)

Writer
       |--TestWriter
       |--MediaWriter

现有一个体系用于各种数据的写入。

但是,防线写入效率有点低。想要对其进行效率的提高。
可以使用缓冲技术来完成的。


以后对象的写入方法,不够高效,可以通过派生子类的形式对齐进行复写,定义高效的写入动作。
Writer
        |--TestWriter
        |--BufferTextWriter
        |--MediaWriter
         |--BufferMediaWriter
通过继承的方式提高了效率。
但是对于扩展性是一个问题。而且所需的功能越多,子类就越多。
一旦加入新类,就需要为它提供高效。麻烦!


如何解决这个问题呢?优化!
既然都需要缓冲,对数据写入的效率进行提高。
可以转变一下思想,这样来做,将缓冲技术单独进行封装。
哪个对象需要缓冲,就把哪个对象传递给缓冲对象即可。

class Buffer {

	Buffer(TestWriter w) {
	}

	Buffer(MediaWriter w) {
	}
}


为了便于扩展,可以对一组对象进行缓冲。

class BufferWriter extends Writer{
	Buffer(Writer w){
	}
	Public void write(){
	}
}

 

体系就变成了这样:
Writer
         |--TextWriter
         |--MediaWriter
         |--BufferWriter
BufferWriter的出现,增强了Writer体系中的功能。
这种设计方式比原来更为灵活,避免了继承的臃肿。
将这样解决方式就定义了一个名称方便于后人使用:装饰设计模式。

装饰设计代码

/*
 模拟一下BufferedReader
 */
import java.io.*;

class MyBufferedReader extends Reader {

	private Reader r;

	MyBufferedReader(Reader r) {
		this.r = r;
	}

	// 可以一次读一行数据的方法。
	public String myReadLine() throws IOException {
		// 定义一个临时容器。原BufferReader封装的是字符数组。
		// 为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。
		StringBuilder sb = new StringBuilder();
		int ch = 0;
		while ((ch = r.read()) != -1) {
			if (ch == '\r')
				continue;
			if (ch == '\n')
				return sb.toString();
			else
				sb.append((char) ch);
		}

		if (sb.length() != 0)
			return sb.toString();
		return null;
	}

	/*
	 * 覆盖Reader类中的抽象方法。
	 */
	public int read(char[] cbuf, int off, int len) throws IOException {
		return r.read(cbuf, off, len);
	}

	public void close() throws IOException {
		r.close();
	}

	public void myClose() throws IOException {
		r.close();
	}
}

class MyBufferedReaderDemo {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("buf.txt");
		MyBufferedReader myBuf = new MyBufferedReader(fr);
		String line = null;
		while ((line = myBuf.myReadLine()) != null) {
			System.out.println(line);
		}
		myBuf.myClose();
	}
}

需求:读取键盘录入,将键盘录入转换成大写存放在文件中

分析:

        源:用InputStream或Reader   

               操作的数据是纯文本用Reader  加入缓冲技术BufferedReader  

       设备:键盘,对应的对象是System.in   所以要用转换流 InputStreamReader
 
    目的:用Writer或OutputStream 

          操作的数据是文本数据用Writer  

          加入缓冲技术BufferedWriter 

    设备:硬盘   硬盘上的一个文本文件


 

package Demo;

import java.io.*;

public class ReadSystemIn {
	public static void main(String[] args) throws Exception {

		BufferedReader bur = null;
		BufferedWriter buw = null;
		try {
			bur = new BufferedReader(new InputStreamReader(System.in));
			buw = new BufferedWriter(new FileWriter("D:\\abc.java"));
			String line = null;
			while ((line = bur.readLine()) != null) { // 一次读一行的数据
				if (line.equals("over"))
					break;
				buw.write(line.toUpperCase()); // 把读取的字符串转换成大写并写入
				buw.newLine(); // 换行
				buw.flush();
			}
		} catch (Exception e) {
			throw new RuntimeException("失败");
		} finally {
			try {
				if (bur != null)
					bur.close(); // 关闭读取流
			} catch (Exception e) {
				throw new RuntimeException("读取流关闭失败");
			}
			try {
				if (buw != null)
					buw.close(); // 关闭写入流
			} catch (Exception e) {
				throw new RuntimeException("写入流关闭失败");
			}
		}
	}
}

File类

         

1)创建功能:

A:创建文件

public boolean createNewFile():如果文件不存在,就会创建一个文件。

B:创建文件夹(目录)

public boolean mkdir():创建单级文件夹,要求父文件夹先存在

public boolean mkdirs():直接创建多级文件夹

2)删除功能:

public boolean delete()     不管的是删除文件还是文件夹,都是采用同一种功能。

注意事项:如果是删除文件夹,请保证文件夹内没有内容。 如果有内容,必须把内容删除完毕才能删除文件夹。

3)判断功能:

           boolean exists() :文件是否存在.
         boolean  isFile(): 判断是否是文件

           boolean isDirectory();是否是文件夹
         boolean  isHidden(); 是否隐藏
         boolean   isAbsolute(); 是否是绝对路径,文件不存在的情况也能判断。

4)获取信息:

         String   getAbsolutePath():  获取抽象路径

需求: 将一个指定目录下的class文件的绝对路径,存储到一个文本文件中。

分析:列出指定目录下文件的绝对路径,就是包含子目录中的内容,也就是列出指定目录下所有class文件的绝对路径。 在列出过程中因为是目录中还有目录,所以还可以调用本功能,也就是递归。
在使用递归的时候要注意:(1)递归一定要有出口,否则就是死递归。

                        (2)递归的次数不能过多,否则内存溢出。

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class ListDir {
	public static void main(String[] args) {
		File dir = new File("C:\\work2");
		List<File> list = new ArrayList<File>();
		getPath(dir, list);
		// System.out.println(list);
		writeToFile(list, "D:\\abc.txt");

	}

	// 定义一个获取文件绝对路径,把绝对路径对象存入到集合中的方法
	public static void getPath(File dir, List<File> list) {
		File[] file = dir.listFiles();
		for (File f : file) {
			if (f.isDirectory()) { // 遍历到的f,如果是目录就进行递归
				getPath(f, list);
			} else {
				if (f.getName().endsWith(".class"))
					list.add(f);
			}
		}
	}

	// 定义一个得到集合里面的绝对路径,把绝对路径存储到指定的文本文件的方法
	public static void writeToFile(List<File> list, String javaListFile) {
		BufferedWriter buw = null;
		try {
			buw = new BufferedWriter(new FileWriter(javaListFile));
			for (File file : list) {
				buw.write(file.getAbsolutePath()); // 得到绝对路径,并且写入到流中
				buw.newLine();
				buw.flush();
			}
		} catch (IOException e) {
			throw new RuntimeException();
		} finally {
			try {
				if (buw != null)
					buw.close();
			} catch (IOException e) {
				throw new RuntimeException("写入流关闭失败");
			}
		}
	}
}


 


 

 

发布了23 篇原创文章 · 获赞 2 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章