黑马程序员-Java学习08-IO类1

来源:互联网 发布:c语言else与下一个if 编辑:程序博客网 时间:2024/05/10 03:21

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


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 stubFile 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); }}

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


0 0
原创粉丝点击