黑马程序员-Java IO输入与输出-day20

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

1、IO流——File概述

File类

1.用来将文件或者文件夹封装成对象

2.方便对文件与文件夹的属性信息进行操作。

3.File对象可以作为参数传递给流的构造函数

4.了解File类中的常用方法。

流只能操作数据,而想操作文件或者文件夹,则必须使用File对象

separator:与系统有关的默认名称分隔符,为了方便,它被表示为一个字符串

import java.io.*;
       public static void consMethod()
       {
              //将a.txt封装成file对象,可以将已有的和未出现的文件或者文件夹封装成对象。
              File f1 = new File("a.txt");
              File f2 = new File("C:\\abc","b.txt");
              File d = new File("C:\\abc");
              File f3 = new File(d,"c.txt");
 
              sop("f1:"+f1);
              sop("f2:"+f2);
              sop("f3:"+f3);
              //封装成相对路径,则打印相对路径;反之则反。
              //跨平台的目录分隔符:separator
              //File f4 = newFile("C:\\abc\\a.txt");
              File f4 = newFile("C:"+File.separator+"abc"+File.separator+"a.txt");//将路径分隔符替换成跨平台的separator,方便跨平台使用
              sop(f4);
       }
       public static void sop(Object obj)
       {
              System.out.println(obj);
       }
}


2、File对象功能

File类常见方法:

1.创建

       booleancreateNewFile():在制定位置创建文件,如果该文件已经存在,则不创建,返回false;和输出流不一样,输出流对象一建立创建文件,而且文件已经存在,均会覆盖文件。

       booleanmkdir():创建文件夹

       booleanmkdirs():创建多级文件夹

2.删除

       booleandelete():删除失败,返回false

       voiddeleteOnExit():在程序退出的时候删除指定文件。

3.判断

       booleanexists():文件是否存在

       isFile():判断是否是文件

       isDirectory():判断是否是目录

       isHidden():判断是否隐藏,Java一般最好不要访问隐藏文件,否则会出错

       isAbsolute():是否是绝对路径 

4.获取信息

       getName();获取文件或目录名称

       getPath();获取路径

       getParent();获取父目录

       getAbsolute();获取绝对路径

       longlastModified();最后修改时间

       longlength();获取文件大小

class FileDemo
{
       public static void main(String[] args) throws IOException
       {
              method_5();
       }
 
       publicstatic void method_5()
       {
              File f1 = new File("C:\\1.log");
              File f2 = new File("C:\\2.txt");
              sop("fename:"+f1.renameTo(f2));//重命名,类似于Windows下的剪切
       }
 
       public static void method_4()
       {
              File f = new File("file.txt");
 
              sop("path:"+f.getPath());
              sop("abspath:"+f.getAbsolutePath());
              sop("parent:"+f.getParent());//该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null。
                                                               //如果相对路径中有上一层目录,那么该目录就是返回结果。
       }
       public static void method_3()
       {
              File f = new File("file.txt");
              //f.createNewFile();
              f.mkdir();
 
              //记住,在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在。
              //通过exists来判断。
 
              sop("dir:"+f.isDirectory());
              sop("file:"+f.isFile());
       }
       public static void method_2()
       {
              File f = new File("file.txt");
              //创建文件夹
              File dir = newFile("abc\\a\\c\\c\\v\\v\\n\\f\\r");
 
              //sop("mkdir:"+dir.mkdirs());
              sop("delete:"+dir.delete());
       }
       public static void method_1()throws IOException
       {
              File f = new File("file.txt");
              f.deleteOnExit();//程序在退出的时候将垃圾文件删除
              //sop("create:"+f.createNewFile());
              sop("delete:"+f.delete());
              //如果想删除一个文件,但文件正在被使用,放在finally里面仍旧删不掉
       }
}


3、File对象功能-文件列表

import java.io.*;
class FileDemo2
{
       public static void main(String[] args)
       {
              listDemo_3();
       }
 
       public static void listDemo_3()
       {
              File dir = new File("D:\\java0414\\day18");
              File[] files = dir.listFiles();
 
              for(File f:files)
                     sop(f.getName()+"......"+f.length());
       }
       public static void listDemo_2()
       {
              File dir = new File("D:\\java0414\\day18");
              String[] arr = dir.list(new FilenameFilter()
              {
                     public boolean accept(File dir,String name)
                     {
                            //sop("dir:"+dir+"......name::"+name);
                            /*
                            if(name.endsWith(".bmp"))
                                   returntrue;
                            return false;
                            */
                            return name.endsWith(".java");
                     }
              });
                     sop("len:"+arr.length);
              for(String name:arr)
              {
                     sop(name);           
              }
       }
       public static void listDemo()
       {
              File f = new File("C:\\");
              String[] names = f.list();//调用list方法的file对象必须是封装了一个目录。该目录还必须存在。
              for(String name:names)
                     sop(name);
       }
       public static void listRootDemo()
       {
              File[] files = File.listRoots();//获取系统有效盘符
              for(File f:files)
              {
                     sop(f);
              }
       }
       public static void sop(Object obj)
       {
              System.out.println(obj);
       }
}


4、列出目录下所有内容—递归

因为目录中还有目录,只要使用同一个列出目录功能的桉树完成即可。

在列出过程中出现的还是目录的话,还可以再次调用本功能。

也就是函数自身调用自身。

这种表现形式,或者编程手法,称为递归。

import java.io.*;
class FileDemo3
{
       public static void main(String[] args)
       {
              File dir = new File("D:\\java0414");
              showDir_1(dir);
              //showDir(dir);
 
              //toBin(6);
              //int n = getSum(10);
              //System.out.println("n="+n);
       }
       public static int getSum(int n)
       {
              if(n==1)
                     return1;
              return n+getSum(n-1);
       }
       public static void toBin(int num)
       {
              while(num>0)
              {
                     System.out.println(num%2);
                     num= num/2;
              }
       }
 
       public static void showDir(File dir)
       {
              System.out.println(dir);//显示根目录
              File[] files = dir.listFiles();
              for(int x=0; x<files.length; x++)
              {
                     if(files[x].isDirectory())
                            showDir(files[x]);
                     else
                            System.out.println(files[x]);
              }
       }
}
小结:

递归要注意:

1.限定条件。

2.要注意递归的次数,尽量避免内存溢出。

/*

showA(); -->CBA

void showA()

{

       showB();

       showA();

}

void showB()

{

       showC();

       showB();

}

void showC()

{

       showC();

}

*/

 

5、删除一个带内容的目录

删除原理:

在Windows中,删除目录从里面往外删除的。

既然是从里往外删除,就需要用到递归。

import java.io.*;
class RemoveDir
{
       public static void main(String[] args)
       {
              File dir = newFile("D:\\javatest");
              removeDir(dir);
       }
       public static void removeDir(File dir)
       {
              File[] files = dir.listFile();
              for(int x=0;x<files.length; x++)
              {
                     if(!files.isHidden()&& files[x].idDirectory())
                            removeDir(files[x]);
                     else//之所以输出是为了更方便的了解文件是否删除
                            System.out.println(files[x].toString()+"::::"+files[x].delete());
              }
              System.out.println(dir+"::dir::"+dir.delete());
       }
}
小结:

Java是无法删除带隐藏属性的文件,因此需要删除某个文件前,最好能判断文件是否隐藏,且Java删除文件时不走回收站,因此在确保文件的确要删除的前提下,再进行删除动作。

 

6、创建Java文件列表

练习:

将制定目录下的java文件的绝对路径,存储到一个文本文件中,

建立一个java文件列表文件。

思路:

1.对制定的目录进行递归。

2.获取递归过程中所有java文件的路径

3.将这些路径存储到集合中。

4.将集合中的数据写入到一个文件中。

import java.io.*;
import java.util.*;
class JavaFileList
{
       public static void main(String[] args) throws IOException
       {
              File dir = new File("E:\\黑马程序员JavaEE+Android——开学前自学的Java课程");
 
              List<File> list = new ArrayList<File>();
 
              fileToList(dir,list);
              //System.out.println(list.size());
 
              File file = new File(dir,"javalist.txt");
              writeToFile(list,file.toString());
       }
       public static void fileToList(File dir,List<File> list)
       {
              File[] files = dir.listFiles();
 
              for(File file:files)
              {
                     if(file.isDirectory())
                            fileToList(file,list);
                     else
                     {
                            if(file.getName().endsWith(".avi"))
                                   list.add(file);
                     }
 
              }
       }
 
       public static void writeToFile(List<File> list,String javaListFile)throws IOException
       {
              BufferedWriter bufw = null;
              try
              {
                     bufw= new BufferedWriter(new FileWriter(javaListFile));
                     for(Filef:list)
                     {
                            String path = f.getAbsolutePath();
                            bufw.write(path);
                            bufw.newLine();
                            bufw.flush();
                     }
              }
              catch (IOException e)
              {
                     throw e;
              }
              finally
              {
                     try
                     {
                            if(bufw!=null)
                                   bufw.close();
                     }
                     catch(IOException e)
                     {
                            throw e;
                     }
              }
       }
}


7、IO流—Properties

1.简述

Properties是hashtable的子类,也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。该对象特点:可以用于键值对形式的配置文件。

2.Properties存取

Set<String>stringPropertyNames()  返回此属性列表中的键集,其中该键及其对应值是字符串,如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键

import java.io.*;
import java.util.*;
class PropertiesDemo
{
       public static void main(String[] args)
       {
              setAndGet();
       }
       public static void setAndGet()
       {
              Properties prop = new Properties();
              prop.setProperty("zhangsan","30");
              prop.setProperty("lisi","39");
 
              //System.out.println(prop);
 
              String value =prop.getProperty("lisi");
              //System.out.println(value);
 
              prop.setProperty("lisi","89");
              Set<String> names =prop.stringPropertyNames();
              for(String s : names)
              {
                     System.out.println(s+":"+prop.getProperty(s));
              }
       }
}


8、Properties存取配置文件

Properties是hashtable的子类,也就是说它具备map集合的特点,而且它里面存储的键值对都是字符串。

是集合中和IO技术相结合的容器。

该对象的特点:可以用于键值对形式的配置文件。

那么在加载数据时,需要数据有固定格式:键=值

void load(InputStream inStream)  从输入流中读取属性列表(键和元素对)

void load(Readr reader)  按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)

void list(PrintStream out)  将属性列表输出到制定的输出流

void list(PrintWriter out)  将属性列表输出到制定的输出流

void store(Writer writer,String comments)   以适合使用load(Reader)方法的格式,将此Properties表中的属性列表(键和元素对)写入输出字符。

import java.io.*;
import java.util.*;
class PropertiesDemo2
{
       public static void main(String[] args) throws IOException
       {
              //method_1();
              loadDemo();
       }
       public static void loadDemo()throws IOException
       {
              Properties prop = new Properties();
              FileInputStream fis = new FileInputStream("info.txt");
              //将流中的数据加载进集合
              prop.load(fis);
 
              prop.setProperty("wangwu","39");
              FileOutputStream fos = new FileOutputStream("info.txt");
              prop.store(fos,"haha");
 
              //System.out.println(prop);
              prop.list(System.out);
 
              fos.close();
              fis.close();
       }

 /*
       演示,如何将流中的数据存储到集合中。
       想要将info.txt中键值数据存到集合中进行操作。
 
       1.用一个流和info.txt文件关联。
       2.读取一行数据,将改行数据用“=”进行切割
       3.等号左边作为键,右边作为值,存入到Properties集合中即可
       */
       public static void method_1()throws IOException
       {
              BufferedReader bufr =
                     new BufferedReader(new FileReader("info.txt"));
 
              String line = null;
              Properties prop = new Properties();
              while((line=bufr.readLine())!=null)
              {
                     String[]arr = line.split("=");
                     //System.out.println(arr[0]+"..."+arr[1]);
                     prop.setProperty(arr[0],arr[1]);
              }
              bufr.close();
              System.out.println(prop);
       }
       public static void SetAndGet()
       {
              Properties prop = new Properties();
 
              prop.setProperty("zhangsan","30");
              prop.setProperty("lisi","39");
 
              //System.out.println(prop);
              String value =prop.getProperty("lisi");
              //System.out.println(value);
             
              prop.setProperty("lisi","89");
              Set<String> names =prop.stringPropertyNames();
              for(String s : names)
              {
                     System.out.println(s+"::"+prop.getProperty(s));
              }
       }
}

小结:

load只是将数据写入到流中,而store则是将数据写入到流以后,并写入到文件中。

凡是前面带#表示注释信息,不会被Properties所加载,前提是Properties所加载的必须是键值对


练习:

用于记录应用程序运行次数,如果使用次数一道,那么给出注册提示。

很容易想到的是:计数器,可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增。

可是随着该应用程序的退出,该计数器也在内存中消失了。下一次在启动该程序,又重新开始从0计数。这样不是我们想要的。

程序及时结束,该计数器的值也存在。下次程序启动在会先加载该计数器的值并加1后在重新存储起来。

所以要建立一个配置文件,用于记录该软加你的使用次数。该配置文件使用键值对的形式,这样便于阅读数据,并操作数据。

键值对数据时map集合,数据时一文件的形式存储,使用IO技术,那么map+io -->Properties。配置文件可以实现应用程序数据的共享。

import java.io.*;
import java.util.*;
class RunCount
{
       public static void main(String[] args) throws IOException
       {
              Properties prop = new Properties();
 
              File file = new File("count.ini");
              if(!file.exists())
                     file.createNewFile();
 
              FileInputStream fis = new FileInputStream(file);
              prop.load(fis);
 
              int count = 0;
              String value =prop.getProperty("time");
 
              if(value !=null)
              {
                     count= Integer.parseInt(value);
                     if(count>=5)
                     {
                            System.out.println("您好,该软件使用次数已到,请注册!");
                            return ;
                     }
              }
              count++;
              prop.setProperty("time",count+"");
 
              FileOutputStream fos = newFileOutputStream(file);
              prop.store(fos,"");
 
              fos.close();
              fis.close();
       }
}
小结:

将文件封装成对象,方便对文件的操作,例如可以判断文件是否存在,然而流却无法直接对文件进行该操作。

 

9、IO包中的其他类

打印流:PrintWriter与PrintStream,可以直接操作输入流和文件。该流提供了打印方法,可以将各种数据类型的数据都能打印。

1、字节打印流:PrintStream

构造函数可以接收的参数类型:

1.file对象,File;

2.字符串路径,String;

3.字节输出流,OutputStream

 

2、字符打印流:PrintWriter

构造函数可以接收的参数类型:

1.file对象,File;

2.字符串路径,String;

3.字节输出流,OutputStream

4.字符输出流,Writer

public PrintWriter(OutputStream out,booleanautoFlush)    通过现有的OutputStreamWriter创建新的PrintWriter。

out:输出流   autoFlush:boolean变量,如果为true,则println、printf或format方法将刷新输出缓冲区

import java.io.*;
class PrintStreamDemo
{
       public static void main(String[] args) throws IOException
       {
              //输入流
              BufferedReader bufr =
                     new BufferedReader(new InputStreamReader(System.in));
              //输出流
              //PrintWriter out = new PrintWriter(System.out,true);//添加true后可直接自动刷新
              PrintWriter out = new PrintWriter(newFileWriter("a.txt"),true);//如果想直接写入到文件里,可以先将文件封装成流对象,然后进行true自动刷新,保证数据安全
                                                                      //如果想提高效率,则也可以嵌套BufferedWriter
              String line = null;
              while((line=bufr.readLine())!=null)
              {
                     if("over".equals(line))
                            break;
                     //out.write(line.toUpperCase());//既然是打印流,那么可以直接用println进行换行
                     out.println(line.toUpperCase());
                     //out.flush();
              }
              out.close();
              bufr.close();
       }
}
小结:

需要特别注意的一点是,如果PrintWriter中带true方法,那么输出到控制台中的println必须加ln,否则无法正常识别并换行

 

10、合并流

序列流:SequenceInputStream,对多个流进行合并。

SequenceInputStream

public SequenceInputStream(Enumeration<?extends InputStream> e)通过记住参数来初始化新创建的 SequenceInputStream,该参数必须是生成运行时类型为 InputStream 对象的 Enumeration 型参数。将按顺序读取由该枚举生成的输入流,以提供从此 SequenceInputStream 读取的字节。在用尽枚举中的每个输入流之后,将通过调用该流的 close 方法将其关闭。

import java.io.*;
import java.util.*;
class SequenceDemo
{
       public static void main(String[] args) throws IOException
       {
//由于SequenceInputStream中如果需要合并多个对象的时候,就需要Enumeration,而只有Vector中才有Enumeration对象,于是就事先创建Vector带泛型的对象
              Vector<FileInputStream> v = new Vector<FileInputStream>();
              v.add(new FileInputStream("C:\\1.txt"));
              v.add(new FileInputStream("C:\\2.txt"));
              v.add(new FileInputStream("C:\\3.txt"));
 
              Enumeration<FileInputStream> en =v.elements();
 
              SequenceInputStream sis = new SequenceInputStream(en);
 
              FileOutputStream fos = new FileOutputStream("C:\\4.txt");
 
              byte[] buf = new byte[1024];
              int len = 0;
              while((len=sis.read(buf))!=-1)
              {
                     fos.write(buf,0,len);
              }
              fos.close();
              sis.close();
       }
}


11、切割文件

import java.io.*;
import java.util.*;
 
class SplitFile
{
       public static void main(String[] args) throws IOException
       {
              //splitFile();   
              hebing();
       }
//合并对象
       public static void hebing()throws IOException
       {
              ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
              for(int x=1; x<=7; x++)
              {
                     al.add(new FileInputStream("C:\\splitfiles\\"+x+".part"));
              }
//由于内部类访问的是本地变量,因此这里的迭代器必须被final修饰
              final Iterator<FileInputStream> it= al.iterator();
              Enumeration<FileInputStream> en =new Enumeration<FileInputStream>()
              {
                     public boolean hasMoreElements()
                     {
                            return it.hasNext();
                     }
                     public FileInputStream nextElement()
                     {
                            return it.next();
                     }
              };
              SequenceInputStream sis = new SequenceInputStream(en);
 
              FileOutputStream fos = new FileOutputStream("C:\\splitfiles\\1.exe");
 
              byte[] buf = new byte[1024];
              int len =0;
              while((len=sis.read(buf))!=-1)
              {
                     fos.write(buf,0,len);
              }
              fos.close();
              sis.close();
       }
 
//切割文件
       public static void splitFile()throws IOException
       {
              FileInputStream fis = new FileInputStream("C:\\BaiduYun_3.6.0.exe");
 
              FileOutputStream fos = null;
              byte[] buf = new byte[1024*1024];
 
              int len =0;
              int count = 1;
              while((len=fis.read(buf))!=-1)
              {
                     fos= new FileOutputStream("C:\\splitfiles\\"+(count++)+".part");
                     fos.write(buf,0,len);
                     fos.close();
              }
              fis.close();
       }
}

小结:

在定义切割容器的读取容器byte大小时,不能直接将其定义得超过一定大小,否则会发生内存溢出异常,因此这里可以再次定义一个容器,达到一定数据大小后,将定义好的输出流对象写入相关数据文件中,依次就能将一个较大文件切割完毕,既提高了效率,又防止内存溢出。


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
详细请查看:http://edu.csdn.net
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值