黑马程序员_毕向东_Java基础_DAY20-21_File、Properties、各种功能流

----------- android培训java培训、期待与您交流! ------------

File类

文件是一类事物,它有自己的名字、属性、大小、位置、后缀名等属性信息,那么根据面向对象的思想,就可以把它封装描述为一个类,

这个类就java.io包中的File类。File类是文件和目录路径名的抽象表示形式,它可以方便的对文件与文件夹的属性信息进行操作,也可以作为参数传递给流对象。

它弥补了了流的不足,比如流只能操作数据,而不能操作文件的属性与文件夹。

 

java.lang.Object

 java.io.File

文件和目录路径名的抽象表示形式。

 

构造方法摘要

File(File parent, String child)

File(String pathname)

File(String parent, String child)

File(URI uri) 

 

//将存在或不存在的文件或文件夹封装成对象

File f1 = newFile("filedemo.txt");

//将目录和文件名分开存放

File f2 = newFile("c:\\bi\\day20", "filedemo2.txt");

 

//目录可以用File表示

File d1 = newFile("c:\\bi\\day20");

File f3 = new File(d1,"filedemo3.txt"); //将File传入构造器

 

File.toString()返回的是文件的路径,封装的是什么,返回的就是什么。如果封装的是相对路径,返回的也是相对路径。

 

关于目录分割符:

windows使用\作为目录分割符,/也可以用。

linux系统使用/作为分割符。

 

因为各个平台的目录分割符不统一,所以使用"c:\\bi"这种形式的定义方式不具备跨平台性,此时可以使用File文件的静态字段separator来标示一个与系统有关的默认名称分隔符。

static String separator

static char separatorChar

 

File类常用方法:

1.创建:

boolean createNewFile()

 

File f = new File("file.txt");

sop("create: " +f.createNewFile());

 

在指定位置创建文件,如果该文件已经存在,则不创建返回false。

如果文件不存在,则创建空文件,返回true。

 

注意:这里和输出流不一样,输出流与文件关联后,如果文件不存在直接创建文件,如果文件存在,则覆盖原文件。

 

//创建在默认临时文件目录中

static File createTempFile(String 前缀,String 后缀)

//创建在指定目录中

static File createTempFile(String 前缀,String 后缀, Filedirectory)

 

创建文件夹:

 boolean mkdir() //直接创建目录

 boolean mkdirs() //如果创建此目录所需的父目录不存在,则依次创建

 

2.删除:

boolean delete() //删除

void deleteOnExit() //在退出时删除

 

3.判断:

 boolean exists()

 boolean isDirectory()

 boolean isFile()

 boolean isHidden()

 boolean canExecute()  //文件是否可执行

 boolean canRead()

 boolean canWrite()

 boolean isAbsolute()

 

 boolean equals(Object obj)

 intcompareTo(File pathname)

 

进行isDirectory和isFile判断之前,一定要先进行exists判断。

 

4.获取:

getName()

getParent() //返回指明了的父目录,如果未指明,返回null

getPath()

getAbsolutePath()

lastModified()

length() //目录的大小为0

 

String[] list()

String[] list(FilenameFilter filter)

File[] listFiles()

File[] ListFiles(FileFilter filter)

File[] ListFiles(FilenameFilter filter)

File[] listRoots()

 

5.重命名

boolean renameTo(File dest)

重命名操作无法将一个文件从一个文件系统移动到另一个文件系统

 

练习:

class FileDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         method_4(); 
    } 
    public static void method_4() throws IOException 
    { 
         File f1 = new File("c:\\Test.java"); 
         File f2 = new File("c:\\haha.java"); 
 
         System.out.println("rename:"+f1.renameTo(f2));//类似剪切,并修改文件名 
    } 
    public static void method_3() throws IOException 
    { 
         File f = new File("FileDemo.java"); 
 
         System.out.println("path:"+f.length()); 
         System.out.println("path:"+f.getAbsolutePath()); 
 
    } 
    public static void method_2() throws IOException 
    { 
         File f = new File("file.txt"); 
         f.mkdir(); 
         //在判断文件对象是否是文件或者目录时,必须先判断该文件是否存在. 
         //通过exists()判断. 
         System.out.println("dir:"+f.isDirectory()); 
         System.out.println("dir:"+f.isFile()); 
    } 
    public static void method_1() throws IOException 
    { 
         File f = new File("file.txt"); 
         System.out.println("create:"+f.createNewFile());//创建 
         System.out.println("delete:"+f.delete());//删除 
         System.out.println("execute:"+f.canExecute());//判断是否能执行 
         System.out.println("exist:"+f.exists());//判断文件是否存在 
    } 
 
    //创建File对象 
    public static void consMethod() 
    { 
         //将a.txt封装成file对象.可以将已有的和未出现的文件或者文件夹封装成对象. 
         File f1 = new File("c:\\abc\\a.txt"); 
          
         //File.separator跨平台的分隔符类似newLine() 
         File f2 = new File("c:"+File.separator+"abc","b.txt"); 
          
         File d = new File("c:\\abc"); 
         File f3 = new File(d,"c.txt"); 
 
         System.out.println("f1:"+f1); 
         System.out.println("f2:"+f2); 
         System.out.println("f3:"+f3); 
    } 
} 

 
class FileDemo2 
{ 
    public static void main(String[] args) 
    { 
         listFileDemo(); 
    } 
    public static void listFileDemo() 
    { 
         File dir = new File("d:\\learn\\day19"); 
         //获取当前目录下所有文件的对象. 
         File[] files = dir.listFiles(); 
         for (File f : files ) 
         { 
              System.out.println(f.getName()+"::"+f.length()); 
         } 
    } 
    public static void listDemo() 
    { 
         File f = new File("D:\\learn\\day19"); 
         //调用list方法的file对象封装的必须是一个目录,并且存在. 
         String[] names = f.list(new MyFilenameFileter());//传进一个过滤器 
         for(String s : names) 
         { 
               System.out.println(s); 
         } 
    } 
 
     public static void listRootsDemo() 
    { 
         //列出电脑中有效的盘符 
         File[] files = File.listRoots(); 
 
         for(File f : files) 
         { 
               System.out.println(f); 
         } 
    } 
} 
 
//定义一个过滤器 
class MyFilenameFileter implementsFilenameFilter 
{     
    public boolean accept(File dir,String name) 
    { 
         return name.endsWith(".class"); 
    } 
}  

递归--列出目录下所有内容:

/*
列出指定目录下文件或者文件夹,包含子目录中的内容.
也就是列出指定目录下所有内容.
 
因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可.
在列出过程中出现的还是目录的话,还可以再次调用本功能.
也就是函数自身调用自身.
这种表现形式,或者变成手法,称为递归.
 
递归要注意的:
 
1.一定要限定条件
 
2.要注意递归的次数,尽量避免内存溢出.
*/ 
import java.io.*; 
class FileDemo3 
{ 
    public static void main(String[] args) 
    { 
         File f = new File("d:\\learn"); 
         //showDir(f); 
         //toBin(6); 
         System.out.println(getSum(10)); 
    } 
    public static int getSum(int n) 
    { 
         if (n==1) 
               return 1; 
         else 
               return n+getSum(n-1); 
 
    } 
    public static void toBin(int n) 
    { 
         if (n>0) 
         { 
               toBin(n/2); 
               System.out.print(n%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]); 
         } 
    } 
}  

列出目录下所有内容--带层级 

import java.io.*; 
class FileDemo4 
{ 
    public static void main(String[] args) 
     { 
         File f = new File("d:\\learn"); 
         showDir(f,0); 
    } 
    //定义一个层级方法 
    public static String getLevel(int level) 
    { 
         StringBuilder sb = new StringBuilder(); 
         for (int x = 1; x<level; x++) 
         { 
               sb.append("    "); 
         } 
         return sb.toString(); 
    } 
    public static void showDir(File dir,int level) 
    { 
         System.out.println(getLevel(level)+dir); 
         level++; 
         File[] files = dir.listFiles(); 
         for(int x= 0; x<files.length; x++) 
         { 
               if(files[x].isDirectory()) 
                   showDir(files[x],level); 
               else 
                   System.out.println(getLevel(level)+files[x]); 
         } 
    } 
} 

 

删除带内容的目录

import java.io.*; 
/*
删除原理:
在windows中,删除目录是从里面往外删除的.
 
既然是从里面往外删除,就需要用到递归.
*/ 
class RemoveDir 
{ 
    public static void main(String[] args) 
    { 
         File dir = new File("d:\\新建文件夹"); 
         removeDir(dir); 
    } 
 
    public static void removeDir(File dir) 
    { 
         File [] files = dir.listFiles(); 
         for (int x=0; x<files.length; x++ ) 
         { 
              if(files[x].isDirectory()) 
                    removeDir(files[x]); 
               else 
                   System.out.println(files[x]+"--file--"+files[x].delete()); 
         } 
         System.out.println(dir+"==dir=="+dir.delete()); 
    } 
} 

 

创建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("d:\\learn"); 
         List<File> list = new ArrayList<File>(); 
         fileToList(dir,list); 
         File file = new File(dir,"javalist.txt"); 
         writeTOFile(list,file); 
    } 
    public static void fileToList(File dir,List<File> list) 
    { 
         File[] files = dir.listFiles(); 
         for (File f : files ) 
         { 
               if (f.isDirectory()) 
                    fileToList(f,list); 
               else 
               { 
                   if(f.getName().endsWith(".java")); 
                         list.add(f); 
               } 
         } 
    } 
    public static void writeTOFile(List<File> list,File file)throwsIOException 
    { 
         BufferedWriter bw = new BufferedWriter(new FileWriter(file)); 
         for (File f : list ) 
         { 
               bw.write(f.getAbsolutePath()); 
               bw.newLine(); 
               bw.flush(); 
         } 
    } 
} 

Properties类

Properties是hashtable的子类.

也就是说它具备map集合的特点.而且它里面存储的键值对都是字符串.

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

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

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

import java.io.*; 
import java.util.*; 
import java.util.*; 
class PropertiesDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         //setAndget(); 
         //method_1(); 
         loadDemo(); 
    } 
    //Properties中提供了load方法来完成method_1 
    public static void loadDemo() throws IOException 
    { 
         Properties prop = new Properties(); 
         FileInputStream fis = newFileInputStream("c:\\info.txt"); 
         prop.load(fis); 
          prop.setProperty("zhangsan","88"); 
         FileOutputStream fos = newFileOutputStream("c:\\info.txt"); 
         prop.store(fos,"haha"); 
         prop.list(System.out); 
         fis.close(); 
         fos.close(); 
    } 
 
    //演示,如何将流中的数据存储到集合中. 
    //想要将info.txt中键值数据存到集合中进行操作. 
    /*
         1.用一个流和info.txt文件关联.
         2.读取一个数据,将该数据用"="进行切割
         3.等号左面作为键,右边作为值.存入到Properties集合中即可
    */ 
    public static void method_1() throws IOException 
    { 
         BufferedReader br = new BufferedReader(newFileReader("c:\\info.txt")); 
         Properties prop = new Properties(); 
         String line = null; 
         while ((line=br.readLine())!=null) 
         { 
               String[] arr = line.split("="); 
              prop.setProperty(arr[0],arr[1]); 
         } 
         br.close(); 
         System.out.println(prop); 
    } 
 
    //设置和获取元素. 
    public static void setAndget() 
    { 
         Properties prop = new Properties(); 
         prop.setProperty("zhangsan","39"); 
         prop.setProperty("lisi","47"); 
 
         System.out.println(prop); 
         System.out.println(prop.getProperty("lisi")); 
          
         prop.setProperty("lisi",90+"");  
 
         Set<String> names = prop.stringPropertyNames(); 
         for (String s : names) 
         { 
              System.out.println(s+":"+prop.getProperty(s)); 
         } 
 
    } 
} 

 

Properties练习--限定程序执行次数

import java.io.*; 
import java.util.*; 
/*
用于记录应用程序运行次数.
如果使用次数已到,那么给出注册提示.
 
很容易想到的是:计数器.
开始该计数器定义在程序中,随着程序的运行而存在的内存中,并进行字增
可是随着该应用程序的推出,该计数器也在内存中消失了.
 
下一次在启动该程序,又重新开始从0计数
这样就不是我们想要的.
 
程序即使结束,该计数器的值也存在.
下次程序启动会先家在该计数器的值并加1后在重新存储起来.
 
所以要建立一个配置文件,用于记录该软件的使用次数.
 
该配置文件使用键值对的形式.
这样便于阅读数据,并操作数据.
 
键值对数据是map集合
数据是以文件形式存储,用到IO技术.
那么map-->Properties + IO
 
配置文件可以实现应用程序数据的共享.
 
1.创建有给读取流关联配置文件
*/ 
class RunCount 
{ 
    public static void main(String[] args) throws IOException 
    { 
         File file = new File("c:\\property.ini"); 
         if(!file.exists()) 
               file.createNewFile(); 
         Properties prop = new Properties(); 
         FileInputStream fr = new FileInputStream(file); 
         prop.load(fr); 
         String value = prop.getProperty("count"); 
         if(value==null) 
              prop.put("count","1"); 
         else 
         { 
               System.out.println(value); 
               int count = Integer.parseInt(value); 
               if(count>=5) 
               { 
                    System.out.println("您的使用次数已到"); 
                    return; 
               } 
               count++; 
              prop.setProperty("count",count+""); 
         } 
         FileOutputStream fw = new FileOutputStream(file);//输出流会覆盖原文件 
         prop.store(fw,"test"); 
         fr.close(); 
         fw.close(); 
    } 
}  

打印流PrintWriter和PrintStream

打印流:

该流提供了打印方法,可以将各种数据类型的数据都原样打印.

字节打印流

PrintStream

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

1.File对象.File

2.字符串路径.String

3.字节输出流.OutputStream

字符打印流

PrintWriter(常用)

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

1.File对象.File

2.字符串路径.String

3.字节输出流.OutputStream

4.字符输出流.Writer

import java.io.*; 
 
class PrintStreamDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         BufferedReader br = 
               new BufferedReader(newInputStreamReader(System.in)); 
         PrintWriter pw = 
               new PrintWriter(newFileWriter("c:\\demo.txt"),true);//可实现自动刷新 
         String line = null; 
         while ((line=br.readLine())!=null) 
         { 
              if(line.equals("over")) 
                    break; 
              pw.println(line.toUpperCase()); 
         } 
         br.close(); 
         pw.close(); 
    } 
}  

序列合并流

SequenceInputStream是能对多个流进行合并成一个读取流,它在构造时需要传入Enumeration,而这个只用Vector中有,所以这个多个读取流要加入Vector集合中。注意:它只是对读取流进行合并。

它使用步骤:

1.创建Vector<InputStream>

2.将要合并的InputStream加入Vector

3.通过Vector获取Enumeration

4.创建SequenceInputStream,将Enumeration作为参数传入。

import java.io.*; 
import java.util.*; 
class SequenceDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         Vector<FileInputStream> v = newVector<FileInputStream>(); 
         v.add(new FileInputStream("c:\\1.txt")); 
         v.add(new FileInputStream("c:\\2.txt")); 
         v.add(new FileInputStream("c:\\3.txt")); 
         Enumeration<FileInputStream> e = v.elements(); 
 
         SequenceInputStream sis = new SequenceInputStream(e); 
         FileOutputStream fos = new FileOutputStream("c:\\4.txt"); 
 
         byte[] bys = new byte[1024]; 
         int len = 0; 
         while ((len = sis.read(bys))!=-1) 
         { 
               fos.write(bys,0,len); 
         } 
         fos.close(); 
         sis.close(); 
    } 
} 

 

文件的切割和合并

import java.io.*; 
import java.util.*; 
class SplitFile 
{ 
    public static void main(String[] args) throws IOException 
    { 
         //splitFile(); 
         merge(); 
    } 
    //合并 
    public static void merge() throws IOException 
    { 
         ArrayList<FileInputStream> al = new ArrayList<FileInputStream>(); 
         al.add(new FileInputStream("c:\\2.part")); 
         al.add(new FileInputStream("c:\\3.part")); 
         al.add(new FileInputStream("c:\\4.part")); 
         final Iterator<FileInputStream> it = al.iterator(); 
         Enumeration<FileInputStream> en = newEnumeration<FileInputStream>() 
         { 
               public booleanhasMoreElements() 
               { 
                    return it.hasNext(); 
               } 
               public FileInputStreamnextElement() 
               { 
                    return it.next(); 
               } 
         }; 
         SequenceInputStream sis = new SequenceInputStream(en); 
         FileOutputStream fos = new FileOutputStream("c:\\0.jpg");  
         byte[] bys = new byte[1024]; 
         int len = 0; 
         while ((len=sis.read(bys))!=-1) 
         { 
               fos.write(bys,0,len); 
         } 
         sis.close(); 
         fos.close(); 
    } 
   //切割 
    public static void splitFile() throws IOException 
    { 
         FileInputStream fis = new FileInputStream("c:\\1.jpg"); 
         FileOutputStream fos = null; 
         byte[] bys = new byte[1024*50]; 
         int len = 0; 
         int count = 2; 
         while ((len=fis.read(bys))!=-1) 
         { 
               fos = newFileOutputStream("c:\\"+(count++)+".part"); 
               fos.write(bys,0,len); 
               fos.close(); 
         } 
         fis.close(); 
     } 
}  

对象序列化:

被序列化的类必须实现Serializable接口,来获得ID.

也可以自己设置ID,例如:static final long serialVersionUID = 42L

static静态成员是不能被序列化的.

transient修饰的成员也是不能被序列化的

import java.io.*; 
class ObjectStreamDemo 
{ 
    public static void main(String[] args) throws Exception 
    { 
         //writeObj(); 
         readObj(); 
    } 
    public static void readObj() throws Exception 
    { 
         ObjectInputStream ois = 
               new ObjectInputStream(newFileInputStream("obj.txt")); 
         Person p = (Person)ois.readObject(); 
         System.out.println(p); 
         ois.close(); 
    } 
    public static void writeObj() throws IOException 
    { 
         ObjectOutputStream oos = 
               new ObjectOutputStream(newFileOutputStream("obj.txt")); 
         oos.writeObject(new Person("lisi",97)); 
         oos.close(); 
    } 
} 
class Person implements Serializable 
{ 
    //给类设置ID, 
    public static final long serialVersionUID = 42L; 
    String name; 
    int age; 
    Person(String name,int age) 
    { 
         this.name = name; 
         this.age = age; 
    } 
    public String toString() 
    { 
         return name+":"+age; 
    } 
}  

管道流:

管道流:输入输出可以直接连接,结合线程使用.

    |--管道输入流:PipedInputStream

    |--管道输出流:PipedOutpuStream

import java.io.*; 
class Read implements Runnable 
{ 
    private PipedInputStream in; 
    Read(PipedInputStream in) 
    { 
         this.in=in; 
    } 
    public void run() 
    { 
         try 
         { 
               byte[] bys = newbyte[1024]; 
               System.out.println("读取前..没有数据..进入阻塞状态"); 
               int len = in.read(bys); 
               System.out.println("读取到数据..阻塞状态结束"); 
               String s = newString(bys,0,len); 
               System.out.println(s); 
               in.close(); 
         } 
         catch (IOException e) 
         { 
               throw newRuntimeException("管道读取流失败"); 
         } 
    } 
} 
class Write implements Runnable 
{ 
    private PipedOutputStream out; 
    Write(PipedOutputStream out) 
    { 
         this.out = out; 
    } 
    public void run() 
    { 
         try 
         { 
               System.out.println("开始写入数据,等待6秒"); 
               Thread.sleep(6000); 
              out.write("PipedOutputStream is coming".getBytes()); 
               out.close(); 
         } 
         catch (Exception e) 
         { 
               throw newRuntimeException("管道输出流失败"); 
         } 
    } 
} 
class PipedStreamDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         PipedInputStream in = new PipedInputStream(); 
         PipedOutputStream out = new PipedOutputStream(); 
         in.connect(out); 
         new Thread(new Read(in)).start(); 
         new Thread(new Write(out)).start(); 
    } 
}  

随机读写RandomAccessFile

该类不算是IO体系中的子类.

而是直接继承自Object.

但是它是IO包的成员,因为它具备读和写功能.

内部封装了一个byte数组,而且通过指针对数组的元素进行操作.

可以通过getFilePointer获取指针位置.

同时可以通过seek改变指针的位置

其实完成读写的原理就是内部封装了字节输入流和输出流.

通过构造函数可以看出,该类只能操作文件.

而且操作的文件还需要指定权限.

如果模式为只读 r,则不会创建文件,回去读取一个已存在的文件,如果该文件不存在,会出现异常

如果模式为 rw,操作的文件不存在,会自动创建,如果存在则不会覆盖

class RandomAccessFileDemo 
{ 
    public static void main(String[] args) throws IOException 
    { 
         //writeFile(); 
         //readFile(); 
         writeFile_2(); 
    } 
     
    public static void readFile() throws IOException 
    { 
         RandomAccessFile raf = newRandomAccessFile("ran.txt","r"); 
         //用seek()方法把指针调到8位置上 
         //raf.seek(8); 
 
         //跳过指定的字节数,skipBytes()只能向前,不能后退 
         raf.skipBytes(8); 
 
         byte[] bys = new byte[4]; 
         raf.read(bys); 
         String name = new String(bys); 
 
         //方法readInt()取一个32位的整数 
         int age = raf.readInt(); 
           
         System.out.println("name="+name); 
         System.out.println("age="+age); 
    } 
    public static void writeFile_2()throws IOException 
    { 
         RandomAccessFile raf = newRandomAccessFile("ran.txt","rw"); 
         raf.seek(16);//利用seek方法,可以实现指定位置数据的添加和修改 
         raf.write("周七".getBytes()); 
         raf.writeInt(103); 
 
    } 
    public static void writeFile() throws IOException 
    { 
         RandomAccessFile raf = new RandomAccessFile("ran.txt","rw"); 
         raf.write("李四".getBytes()); 
         raf.writeInt(97); 
         raf.write("王五".getBytes()); 
         raf.writeInt(99); 
         raf.close(); 
    }          
}  



----------- android培训java培训、期待与您交流! ------------

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值