黑马程序员--【学习日记八】——IO流

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

知识列表

  • IO概述
  • 字符流
  • IO异常
  • FileReader
  • 复制文本文件
  • BufferedWriter
  • BufferedReader
  • InputStream和OutputStream
  • 复制图片文件
  • 转换流,读取键盘录入
  • 流对象操作规律
  • 改变标准输入输出设备
  • File类
  • Properties
  • 打印流
  • 合并流

1)IO概述

字符流和字节流。

字节流两个基类: 
InputStream?? OutputStream

字符流两个基类: 
Reader Writer

2)字符流

IO流是用于操作数据的,数据最常见形式是文件。

例如:在硬盘上创建一个文件并写入一些文字数据。

FileWriter:

是一个专门用于操作文件的Writer子类对象

  1: class  FileWriterDemo
  2: {
  3: public static void main(String[] args) throws IOException
  4: {
  5: //创建一个FileWriter对象,该对象初始化时就要明确被操作的文件。
  6: //在制定目录上创建一个demo.txt的文件,如果该目录下存在同名文件,旧文件将被覆盖。
  8: FileWriter fw = new FileWriter("demo.txt");
  9: //调用write方法,将字符串写入到流中。
 10: fw.write("abcde");
 11: //刷新流对象中的缓冲中的数据,将数据写入文件中。
 13: //fw.flush();
 14: //关闭流资源
 17: fw.close();
 18: }
 19: }

?

fw.close()用于关闭流资源,关闭之前会自动刷新缓冲区中的数据,与flush()的区别:flush只刷新不关闭资源,close既刷新又关闭资源。

如果要续写文件内容,而不是覆盖同名文件,就给FileWriter传递一个true参数,表示续写不覆盖。

  1: class  FileWriterDemo3
  2: {
  3:   public static void main(String[] args) throws IOException
  4:   {
  5:     //传递true参数,表示续写demo.txt文件,不覆盖旧文件。
  6:     FileWriter fw = new FileWriter("demo.txt",true);
  8:     fw.write("hello world!");
 10:     fw.close();
 11:   }
 12: }
 13: 

3)IO异常

IO异常的处理方式

finally中定义关闭资源的动作,关闭之前要先判断。

  1: 
  2: class  FileWriterDemo2
  3: {
  4:   public static void main(String[] args) 
  5:   {
  6:     FileWriter fw = null;
  7:     try
  8:     {
  9:       fw = new FileWriter("demo.txt");
 10:       fw.write("abcdefg");
 11:     }
 12:     catch (IOException e)
 13:     {
 14:       System.out.println("catch:"+e.toString());
 15:     }
 16:     finally
 17:     {
 18:       try
 19:       {
 20:         if(fw!=null)
 21:           fw.close();        
 22:       }
 23:       catch (IOException e)
 24:       {
 25:         System.out.println(e.toString());
 26:       }
 27:       
 28:     }    
 29: 
 30:   }
 31: }

4)FileReader :

读取文件有两种方式:

第一种是每次读取一个字符:

  1: class  FileReaderDemo
  2: {
  3:   public static void main(String[] args) throws IOException
  4:   {
  5:     //创建一个文件读取流对象,和指定名称的文件相关联。
  6:     //要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
  7:     FileReader fr = new FileReader("demo.txt");
  8:     //调用读取流对象的read方法。
  9:     //read():一次读一个字符。而且会自动往下读。
 10:     int ch = 0;
 11:     while((ch=fr.read())!=-1)
 12:     {
 13:       System.out.println((char)ch);
 14:     }
 15:     fr.close();
 16:   }
 17: }

 

第二种是每次读取到字符数组中:

  1: class FileReaderDemo2 
  2: {
  3:   public static void main(String[] args) throws IOException
  4:   {
  5:     FileReader fr = new FileReader("demo.txt");
  6:     //定义一个字符数组。用于存储读到字符。
  7:     //read(char[])返回的是读到字符个数。
  8:     char[] buf = new char[1024];
  9:     int num = 0;
 10:     while((num=fr.read(buf))!=-1)
 11:     {
 12:       System.out.println(new String(buf,0,num));
 13:     }
 15:     fr.close();
 16:   }
 17: }

 

5)复制文本文件

原理:就是将一个文件中的数据存储到另一个文件中。

步骤: 
1,在d盘创建一个文件,用于存储c盘文件中的数据。 
2,定义读取流和源文件相关联。 
3,通过不断的读写完成数据存储。 
4,关闭资源。

  1: class CopyDemo 
  2: {
  3:   public static void main(String[] args) throws IOException
  4:   {
  5:     copy();
  6:   }
  7:   public static void copy()throws IOException//为了简化书写,没有处理异常
  8:   {
  9:     //创建目标文件。
 10:     FileWriter fw = new FileWriter("demoCopy.txt");
 11: 
 12:     //与源文件相关联。
 13:     FileReader fr = new FileReader("demo.txt");
 14:     int ch = 0;
 15:     while((ch=fr.read())!=-1)
 16:     {
 17:       fw.write(ch);
 18:     }
 19:     fw.close();
 20:     fr.close();
 21:   }
 22: }

 

6)BufferdWriter:

BufferdWriter是字符写入流,可以提高写入效率

BufferdWriter中的方法newLine()是以个跨平台的换行符。

  2: FileWriter fw = new FileWriter("buf.txt");
  5: //将需要被提高效率的流对象作为参数传递给缓冲区的构造函数
  6: BufferedWriter bufw = new BufferedWriter(fw);
  7: for(int x=1; x<5; x++)
  8: {
  9: bufw.write("abcd"+x);
 10: bufw.newLine();
 11: bufw.flush();
 12: }
 13: //只要用到缓冲区,就要刷新。
 14: //bufw.flush();
 15: //关闭缓冲区,就是在关闭缓冲区中的流对象。
 16: bufw.close();

 

7)BufferedReader:

BufferedReader是字符读取流缓冲区: 
BufferedReader中方法 readLine(),每次读取一整行,是读取文件更加方便。当返回null时,表示读到文件末尾。

readLine方法只返回回车符之前的内容,不返回回车符。

  1:   //创建一个读取流对象和文件相关联。
  2:     FileReader fr = new FileReader("buf.txt");
  3:     //BufferedReader可以提高读取效率,将fr作为参数传递给BufferedReader的对象即可。
  4:     BufferedReader bufr = new BufferedReader(fr);
  5:     String line = null;
  6:     while((line=bufr.readLine())!=null)
  7:     {
  8:       System.out.print(line);
  9:     }
 10:     bufr.close();

 

8)InputStream和OutputStream:

InputStream和OutputStream和字符流的使用方法差不多。

OutputStream,字节写入流

  1: FileOutputStream fos = new FileOutputStream("fos.txt");
  2: fos.write("abcde".getBytes());
  3: fos.close();

初始化时就需要和存储文件相关联。

同样需要关闭资源

InputStream,字节读取流:

读取时可以定义好一个刚刚好的缓冲区,或者定义一个数组[1024*x],x表示长度是1024的整数倍的数组,一般使用后者,防止文件过大时造成内存溢出。

  1: FileInputStream fis = new FileInputStream("fos.txt");
  3: byte[] buf = new byte[1024];
  4: int len = 0;
  5: while((len=fis.read(buf))!=-1)
  6: {
  7: System.out.println(new String(buf,0,len));
  8: }
 10: fis.close();

初始化时需要和源文件相关联

读取完成以后同样也需要关闭资源

9)复制图片文件

大致步骤:

1,字节读取流对象和图片关联。 
2,字节写入流对象创建一个图片文件存储读取到的数据。 
3,循环读写。 
4,关闭资源。

  1: FileOutputStream fos = null;
  2:     FileInputStream fis = null;
  3:     try
  4:     {
  5:       fos = new FileOutputStream("c:\\1copy.jpg");
  6:       fis = new FileInputStream("c:\\1.jpg");
 10:       int len = 0;
 12:       while((len=fis.read(buf))!=-1)
 13:       {
 14:         fos.write(buf,0,len);
 15:       }
 16:     }
 17:     catch (IOException e)
 18:     {
 19:       throw new RuntimeException("复制文件失败");
 20:     }
 21:     finally
 22:     {
 23:       try
 24:       {
 25:         if(fis!=null)
 26:           fis.close();
 27:       }
 28:       catch (IOException e)
 29:       {
 30:         throw new RuntimeException("读取关闭失败");
 31:       }
 32:       try
 33:       {
 34:         if(fos!=null)
 35:           fos.close();
 36:       }
 37:       catch (IOException e)
 38:       {
 39:         throw new RuntimeException("写入关闭失败");
 40:       }
 41:     }

分别关闭读取流和写入流。

10)转换流,读取键盘录入

读取键盘录入时,需要每次读取一行,readLine方法是字符流BufferedReader类中的方法方法,而键盘录入的read方法是字节流InputStream的方法,此时就需要转换流:

InputStreamReader

 12:     //获取键盘录入
 13:     BufferedReader bufr = 
 14:         new BufferedReader(new InputStreamReader(System.in));

 

如果不定义结束标记,键盘录入就结束不了。

将键盘录入的数据打印在控制台并转换为大写,将over作为结束标记:

  1: //获取键盘录入对象。
  2:     //InputStream in = System.in;
  3: 
  4:     //将字节流对象转成字符流对象,使用转换流。InputStreamReader
  5:     //InputStreamReader isr = new InputStreamReader(in);
  6: 
  7:     //为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
  8:     //BufferedReader bufr = new BufferedReader(isr);
  9:     //键盘的最常见写法。
 10:     BufferedReader bufr = 
 11:         new BufferedReader(new InputStreamReader(System.in));
 12:     BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
 13:     String line = null;
 14: 
 15:     while((line=bufr.readLine())!=null)
 16:     {
 17:       if("over".equals(line))
 18:         break;
 19:       bufw.write(line.toUpperCase());
 20:       bufw.newLine();
 21:       bufw.flush();
 22:     }
 23: 
 24:     bufr.close();

 

11)流对象操作规律

通过键盘录入的例子分析出流操作的大致规律:

1,需求:将键盘录入打印在控制台上 
源:键盘录入。 
目的:控制台。

2,需求:想把键盘录入的数据存储到一个文件中。 
源:键盘。 
目的:文件。

3,需求:想要将一个文件的数据打印在控制台上。 
源:文件。 
目的:控制台。

因为流对象很多,为了便于选取合适的流对象进行操作,分析出流操作的基本规律:

通过三个明确来完成。

1,明确源和目的。 
源:输入流。InputStream? Reader 
目的:输出流。OutputStream? Writer。 
2,操作的数据是否是纯文本。 
是:字符流。 
不是:字节流。

3,当体系明确后,在明确要使用哪个具体的对象。 
通过设备来进行区分: 
源设备:内存,硬盘。键盘 
目的设备:内存,硬盘,控制台。

举例说明:

1,复制文本文件。 
源:是读取流,选择InputStream或Reader? 
是否纯文本:是,选择Reader

设备:硬盘。

Reader体系中可以操作文件的对象是 FileReader

需要提高效率,加入Reader体系中缓冲区 BufferedReader.? 
BufferedReader bufr = new BufferedReader(new FileReader("1.txt"));

目的:写入流,选择OutputStream或者Writer 
是纯文本,选择Writer

设备:硬盘

Writer体系中可以操作文件的对象FileWriter。 
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter 
BufferedWriter bufw = new BufferedWriter(new FileWriter("1copy.txt"));

2,需求:将键盘录入的数据保存到一个文件中。 
源:InputStream Reader 
是不是纯文本?是!Reader 
设备:键盘。对应的对象是System.in. 
System.in对应的是字节流吗,为了操作键盘的文本数据方便,转成字符流

用了Reader体系中转换流,InputStreamReader

InputStreamReader isr = new InputStreamReader(System.in);

需要提高效率,使用BufferedReader

BufferedReader bufr = new BufferedReader(isr);

目的:OutputStream? Writer

是否是存文本?是!Writer。 
设备:硬盘。一个文件。使用 FileWriter。 
FileWriter fw = new FileWriter("SystemIn.txt"); 
需要提高效率,使用BufferedWriter bufw = new BufferedWriter(fw);

指定编码表进行存储:

*OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");*

常用编码表:UTF-8;GBK

按照“三个明确”完成获取键盘录入并打印在控制台:

  1:     System.setIn(new FileInputStream("PersonDemo.java"));
  2:     System.setOut(new PrintStream("zzz.txt"));
  3:     //键盘的最常见写法。
  4:     BufferedReader bufr = 
  5:         new BufferedReader(new InputStreamReader(System.in));
  6:     BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
  7:     String line = null;
  8: 
  9:     while((line=bufr.readLine())!=null)
 10:     {
 11:       if("over".equals(line))
 12:         break;
 13:       bufw.write(line.toUpperCase());
 14:       bufw.newLine();
 15:       bufw.flush();
 16:     }
 17:     bufr.close();

12)改变标准输入输出设备

System.setIn(new FileInputStream(“D:\\1.txt”));//改变标准输出设备,读取

System.setOut(new FileOutputStream(“D:\\2.txt”));//改变标准输入设备,写入

如果把标准输入输出设备都改成文件,就相当于复制文件。

通过改变标准输出流,将异常信息写入日志文件中,并且加入日志创建的时间等信息:

  1: try
  2:       {
  3:         Date d = new Date();
  4:         SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
  5:         String s = sdf.format(d);
  7:         PrintStream ps = new PrintStream("exeception.log");
  8:         ps.println(s);
  9:         System.setOut(ps);
 12:       }
 13:       catch (IOException ex)
 14:       {
 15:         throw new RuntimeException("日志文件创建失败");
 16:       }
 17:       e.printStackTrace(System.out);

 

*有专门便于建立日志信息的工具,log4j*

改变输出设备还有一个应用,就是记录系统信息,Properties与流相结合。

Properties p = System.getProperties();

打印系统信息可以通过遍历p.keySet()集合来获取,也可以通过p.list(PrintStream p)方法改变输入设备,将系统信息写入日志文件存入硬盘中。

  1:     Properties p = System.getProperties();
  2:     /*for(Object obj:p.keySet()){//通过遍历的方式也能获取系统信息
  3:       System.out.println(obj+":"+p.get(obj));
  4:     }*/
  5:     System.out.println(p.getProperty("os.name"));
  6:     p.list(System.out);
  7:     p.list(new PrintStream("d:\\SystemIn.log"));
  8:     Runtime r = Runtime.getRuntime();
  9:     r.exec("notepad d:\\SystemIn.log");

13)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()

列出目录:

  1: File dir = new File("c:\\");
  2: File[] files = dir.listFiles(); 
  3:  for(File f : files)
  4: {
  5:      System.out.println(f.getName()+"::"+f.length());
  6: }
  7: 
  1: public static void showDir(File dir,int level)
  2:   {
  3:     System.out.println(getLevel(level)+dir.getName());
  4: 
  5:     level++;
  6:     File[] files = dir.listFiles();
  7:     for(int x=0; x<files.length; x++)
  8:     {
  9:       if(files[x].isDirectory())
 10:         showDir(files[x],level);//递归,无条件的递归就相当于无限循环
 11:       else
 12:         System.out.println(getLevel(level)+files[x]);
 13:     }
 14:   }

函数自己调用自己,称为递归。

通过list(FilenameFilter filter)列出过滤后的目录:

  1: public static void listDemo_2()
  2: {
  3:         File dir = new File("d:\\java"); 
  5:         String[] arr = dir.list(new FilenameFilter()
  6:         {
  7:             public boolean accept(File dir,String name)
  8:             { 
  9:                 return name.endsWith(".java"); 
 10:             }
 11:         });
 12: }

 

删除带内容的目录:

在windows中,目录的删除时由里到外的,先删除里面的文件,再删除外面的目录。

这样就需要用到递归。

  1: File[] files = dir.listFiles();
  3:   for(int x=0; x<files.length; x++)
  4:   {
  5:    if(files[x].isDirectory())//递归应该有条件,否则就是无限循环
  6:     removeDir(files[x]);
  7:    else
  8:     System.out.println(files[x].toString()+":-file-:"+files[x].delete());
  9:   }

14)Properties:

Properties是HashTable的子类,具有Map集合的特点,存储的是键值对。是集合中和IO相结合的容器。

Properties对象可以用作存储键值对形式的配置文件。

Properties prop = new Properties();

设置和获取元素:prop.setProperty("abc","10");prop.getProperty("abc");

15)打印流:

打印流: 
能将各种类型的数据原样打印。

PrintStream: 
构造函数可以接收的参数类型: 
1,File对象 
2,字符串路径:String 
3,字节输出流:OutputStream 
PrintWriter: 
构造函数可以接收的参数类型: 
1,File对象 
2,字符串路径:String 
3,字节输出流:OutputStream 
4,字符输出流:Writer。

PrintWriter,将键盘录入数据转换为大写打印在控制台上:

  1: BufferedReader bufr = 
  2:             new BufferedReader(new InputStreamReader(System.in)); 
  3: PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true); 
  4: String line = null; 
  5: while((line=bufr.readLine())!=null)
  6:  {
  7:    if("over".equals(line))
  8:        break;
  9:        out.println(line.toUpperCase());
 10:        //out.flush();
 11: } 
 12: out.close();
 13: bufr.close();

16)合并流:

SequenceInputStream:可以将多个流对象合并成一个流对象。

将1.txt、2.txt、3.txt这三个文件中的内容复制到4.txt这一个文件中:

  1: Vector<FileInputStream> v = new Vector<FileInputStream>();
  2:   v.add(new FileInputStream("c:\\1.txt"));
  3:   v.add(new FileInputStream("c:\\2.txt"));
  4:   v.add(new FileInputStream("c:\\3.txt"));
  5:   Enumeration<FileInputStream> en = v.elements();//SequenceInputStream接受的枚举对象,集合中只有Vector有这个方法获取枚举对象
  6:   SequenceInputStream sis = new SequenceInputStream(en);//将枚举对象作为参数传递给SequenceInputStream
  7:   FileOutputStream fos = new FileOutputStream("c:\\4.txt");
  8:   byte[] buf = new byte[1024];
  9:   int len =0;
 10:   while((len=sis.read(buf))!=-1)
 11:   {
 12:    fos.write(buf,0,len);
 13:   }
 14:   fos.close();
 15:   sis.close();


------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值