Java学习08-IO类1



1.IO总框架图


2.File类

在学习流之前,很有必要先写一下File类,因为大多数流都涉及到File.

File类常见方法:
1),创建。
 boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
      和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。

 boolean mkdir():创建文件夹。
 boolean mkdirs():创建多级文件夹。
2),删除。
 boolean delete(): 删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
 void deleteOnExit() ;在程序退出时删除指定文件。


3),判断。
 boolean exists() :文件是否存在.
 isFile():
 isDirectory();
 isHidden();
 isAbsolute();

4),获取信息。
 getName():
 getPath():
 getParent():

 getAbsolutePath()
 long lastModified()
 long length()

记住在判断文件对象是否是文件或者目的时,必须要先判断该文件对象封装的内容是否存在。
  //通过exists判断。

import java.io.*;

public class FileDemo  {
	public static void main(String[] args) throws IOException{
		File f = new File("d:\\java\\nuddles.txt");
		f.createNewFile();
		sop(f);
		sop(f.canExecute());
		sop(f.createNewFile());
		sop(f.exists());
		sop(f.delete());
		File p = new File("d:\\java\\com\\haha\\lala");
		sop(p.isFile());
		sop(p.isDirectory());
		sop(p.mkdirs());
		sop(f.getParent());
		sop(f.getAbsolutePath());
		sop(f.length());
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

练习:打印文件目录

/*
要求:打印一个目录,要求要有层次
*/
package nuddles.j2seDemo;

import java.io.File;

public class DirectoryPrint {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		File file = new File("d:\\javasf");
		filePrint(file,0);
	}
	
	public static String index(int level){
//		用此方法在目录前添加层次
		StringBuilder sb = new StringBuilder();
		sb.append("|--");
		for (int i = 0; i < level; i++) {
			sb.insert(0, "  ");
//			第往下一级目录就增加两个空格
		}
		return new String(sb);
	}
	public static void filePrint(File file,int level){
		if (!file.exists()) {
//			如果不存在直接提示返回
			System.out.println("你输入的文件名不存在");
			return;
		}
		if (file.isDirectory()) {
//			是目录则往下一级
			level++;
			System.out.println(file.getAbsolutePath());
			File[] files = file.listFiles();
			for (File file2 : files) {
//				递归调用
					filePrint(file2,level);
			}
		}else{
			System.out.println(index(level)+file.getName());
//			不是目录则打印文件名,前面加层次
		}
	}
}

删除目录


/*删除目录*/
import java.io.*;

public class FileDemo3  {
	public static void main(String[] args) {
		File file = new File("d:\\jiangxi");
		File[] p = file.listFiles();
		sop(p== null);
		fileRemove(file);
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void fileRemove(File file){
		if (file.exists()) {
				File[] file2 = file.listFiles();
				for(File f:file2){
					if (f.isDirectory()) {
						fileRemove(f);
					}else{
						f.delete();
					}
				}
		}else {
			System.exit(0);
		}
		file.delete();
	}
}


3..流的概念和作用
流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

4.IO流的分类
根据处理数据类型的不同分为:字符流和字节流
根据数据流向不同分为:输入流和输出流
 
字符流和字节流
字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。 本质其实就是基于字节流读取时,去查了指定的码表。 字节流和字符流的区别:
读写单位不同: 字节流以字节(8bit)为单位 ,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。 
处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。 字符类其实就是带有编码表的字节类
  输入流和输出流 
对输入流只能进行读操作,对输出流只能进行写操作,程序中需要根据待传输数据的不同特性而使用不同的流。 
字符流和字节流:
字节流两个 抽象基类:
InputStream   OutputStream
字符流两个 抽象基类:
Reader Writer
字符流在写入数据的时候会有缓冲期,要刷新flush()
先学习一下字符流的特点。
既然IO流是用于操作数据的,
那么数据的最常见体现形式是:文件。
那么先以操作文件为主来演示。
需求:在硬盘上,创建一个文件并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象。FileWriter。  后缀名是父类名。 前缀名是该流对象的功能。


import java.io.*;

public class FileWriterDemo {
	public static void main(String[] args){
		FileWriter  fw = null;
		try{
			fw = new FileWriter("whz.txt",true);
			fw.write("\r\nabcde");
			// 可以直接写入字符串
			fw.flush();
			// 写完后一定要刻刷新
		}catch(IOException e){
			sop("fail to write ");
		}finally{
			try{
				if (fw != null) {
					fw.close();
					// 为更好保护数据,关闭流
				}
				
			}catch(IOException e){
				sop("fail to close");
			}
		}
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}

FileReader类: 

注意:FileReader类没有readLine 的方法


import java.io.*;

public class FileReaderDemo  {
	public static void main(String[] args) throws IOException{
		FileReader fr = new FileReader("FileWriterDemo.java");
		char[] cha = new char[1024];
		int num = 0;
		while ((num=fr.read(cha)) != -1) {
			// 直接读一个字符数组,返回读到的长度
			sop(new String(cha,0,num));
		}
		fr.close();
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
}


练习复制文件

import java.io.*;

public class CopyDemo {
	public static void main(String[] args) {
		copy();
	}
	public static void sop(Object obj){
		System.out.println(obj);
	}
	public static void copy(){
		FileReader fr = null;
		FileWriter fw = null;
		try{
			fw = new FileWriter("SystemDemo_copy.txt");
			fr = new FileReader("SystemDemo.java");
			char[] cha = new char[1024];
			int num = 0;
			while ((num = fr.read(cha)) != -1) {
				fw.write(cha,0,num);
				// 直接写入一个数组的指定长度
				fw.flush();
			}
		}catch(IOException e){
				sop(e.toString());
			}finally{
				try{
					if(fw != null){
						fw.close();
					}
				}catch(IOException e){}
				try{
					if(fr != null){
						fr.close();
					}
				}catch(IOException e){}
			}

		}
}

3.字符流缓冲区:

缓冲区的出现提高了对数据的读写效率
对应类:
BUfferWriter
BufferedReader
特点:缓冲区要结合流才可以使用,在创建缓冲区之前,必须要有流对象。在流的基础上对流的功能进行了增强。
BufferWriter步骤:
1.创建一个字符写入流对象
FileWriter fw=new FileWriter("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
bufferedWriter bufw=new BufferedWriter(fw);
buff.write("asdasdas");
bufw.newLine();//换行符,跨平台的
3.将缓冲区刷新
bufw.flush;
4.关闭缓冲区,就是在关闭缓冲区中的流对象
bufw.close();


BufferedReader步骤
1.创建一个字符写入流对象
FileReader fr=new FileReader ("a.txt");
2.将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
BufferedReader bufr=new BufferedReader (fr);
3.读取流对象:该缓冲区提供了一个一次读取一行的方法。当返回null时表示,文件读到末尾
String line=null;
while((line=bufr.readLine())!=null)
{
String s=line;}
4.关闭
bufr.close();
readLine()方法的原理:
无论是读一行,获取多个字符,最终都是在硬盘上一个一个读取,最终使用额还是read方法一次读一个的方法。

该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。

当返回null时,表示读到文件末尾。

readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。


import java.io.*;
public class BufferedReaderDemo  {
         public static void main(String[] args)throws IOException {
                   FileReader fr = new FileReader("whz.java");
                   BufferedReader br = new BufferedReader(fr);
                   String line = null;
                   while((line=br.readLine())!=null){
                            sop(line);
                   }
                   br.close();
         }
         public static void sop(Object obj){
                   System.out.println(obj);
         }
}
扩展:自己写readLine方法

import java.io.*;
class MyBufferedReader extends Reader {
	private Reader reader;
	MyBufferedReader(Reader reader){
		this.reader =reader;
	}
	public String myReadLine()throws IOException{
		int num = 0;
		StringBuilder sb = new StringBuilder();
		while ((num =reader.read())!=-1) {
			
			if (num == '\r') {
				continue;
			}
			if(num == '\n'){
				// 边续两次判断,决定是不是换行
				return sb.toString();
			}else{
				// 不是就继续添加
				sb.append((char)num);
			}
		}
		if(sb.length()!=0)
			return sb.toString();
		return null;
	}
	public int read(char[] cbuf, int off, int len) throws IOException{
		// reader是抽象类,要覆写所有的抽象方法
		return reader.read(cbuf,off,len) ;
	}

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

}
public class MyBufferedReaderDemo  {
	public static void main(String[] args) throws IOException{
		FileReader fr = new FileReader("whz.java");

		MyBufferedReader myBuf = new MyBufferedReader(fr);

		String line = null;

		while((line=myBuf.myReadLine())!=null){
			System.out.println(line);
		}

		myBuf.myClose();
	}
}

4。装饰类设计思路

 
当想要对已有的独享进行功能增强时,可以定义类,将已有的对象传入,基于已经有的功能,
并提供加强功能,那么自定义的该类称为装饰类
装饰类通常会通过构造方法接收被装饰的对象,并基于被装饰的对象的功能,提供更强的功能。

以前是通过继承将每一个子类都具备缓冲功能。

那么继承体系会复杂,并不利于扩展。

现在优化思想。单独描述一下缓冲内容。

将需要被缓冲的对象。传递进来。也就是,谁需要被缓冲,谁就作为参数传递给缓冲区。

这样继承体系就变得很简单。优化了体系结构。

装饰模式比继承要灵活。避免了继承体系臃肿。

而且降低了类于类之间的关系。

装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。

所以装饰类和被装饰类通常是都属于一个体系中的。

上例中的MyBufferedReader就可以改写成一个装饰类

package com.io;
import java.io.*;
public class MyBufferedReader  {
		private Reader r;
    	public MyBufferedReader(Reader r) {
			super();
			this.r = r;
		}

		//可以一次读取一行的方法
	 	public String myReadLine() throws IOException
	 	{
	 		//定义一个临时容器。StringBulider容器,应用于存储字符数组
	 		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中的抽象方法
	 	//复写close方法
	 	public  void  close() throws IOException
	 	{
	 		r.close();
	 	}
	 	//复写read方法
	 	public int read (char[] c,int off,int len) throws IOException{
	 		
	 		return r.read(c, off, len);
	 	}
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值