Java IO(三)

   File

   File类的常见方法:

  1、创建。

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

    boolean mkdir():创建文件夹。

    boolean mkdirs():创建多级文件夹。

  2、删除。

    boolean delete():删除失败返回false。

    void deleteOnExit():在程序退出时删除指定文件。

  3、判断。

    boolean exists():文件是否存在。

    isDirectory()

    isFile()

    isHidden():是否是一个隐藏文件。

    isAbsolute():文件不存在也可以判断。

  4、获取信息。

    getName():获取文件或目录的名称。

    getPath():返回的就是File类构造函数里面的字符串,不管什么绝对或相对路径,你给我什么,我就返回什么。

    getParent():该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null。如果相对路径中有上一层目录,那么该目录就是返回结果。

    getAbsolutePath():该方法法返回的是绝对路径。

    long lastModified()

    long length()

   示例代码如下:

import java.io.File;
import java.io.IOException;

public class FileDemo0 {

    public static void main(String[] args) throws IOException {
        //consMethod();
        //method_1();
        //method_2();
        //method_3();
        //method_4();
        method_5();
    }
    
    public static void method_5() {
        File f1 = new File("d:\\java\\LoginDemo.java");
        File f2 = new File("d:\\java\\aaa.java");
        
        sop("rename:" + f2.renameTo(f1));
    }
    
    public static void method_4() {
        File f = new File("abc\\file.txt");
        
        sop("path:" + f.getPath());//返回的就是File类构造函数里面的字符串,里面是什么就返回什么
        sop("abspath:" + f.getAbsolutePath());
        sop("parent:" + f.getParent());//该方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null
                                       //如果相对路径中有上一层目录,那么该目录就是返回结果。
    }
    
    public static void method_3() throws IOException {
        File f = new File("E:\\MyJava\\workspace\\IO_Project\\file2.txt");
        
        //f.createNewFile();
        //f.mkdir();
        
        /*
         * 记住在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在,
         * 通过exists()判断。
         */
        sop("dir : " + f.isDirectory());
        sop("file : " + f.isFile());
        sop(f.isAbsolute());//文件不存在也可以判断
    }
    
    public static void method_2() {
        File f = new File("file.txt");
        //sop("exists : " + f.exists());
        //sop("execute: " + f.canExecute());
        
        /*
         * 创建文件夹
         */
        File dir = new File("abc\\kkk\\asd\\qewq\\as\\er");
        
        sop("mkdir : " + dir.mkdirs());
        
    }
    
    public static void method_1() throws IOException {
        File f = new File("file.txt");
        f.deleteOnExit();
        //code();
        //sop("create : " + f.createNewFile());
        sop("delete :" + f.delete());
    }
    
    /*
     * 创建File对象
     */
    public static void consMethod() {
        /*
         * 将a.txt封装成file对象,可以将已有和未出现的文件或文件夹封装成对象
         */
        File f1 = new File("a.txt");
        
        File f2 = new File("d:\\java\\io123", "b.txt");
        
        File d = new File("d:\\java\\io123");
        File f3 = new File(d, "c.txt");
        
        sop("f1 : " + f1);
        sop("f2 : " + f2);
        sop("f3 : " + f3);
        
        File f4 = new File("d:" + File.separator + "java" + File.separator + "io123" + File.separator + "d.txt");
    }
    
    
    public static void sop(Object obj) {
        System.out.println(obj);
    }

}

  5、列出可用的文件系统根,也就是本机上的盘符。

    listRoots()

  6、字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。如果目录为空,那么数组也将为空如果此抽象路径名不表示一个目录,或者发生 I/O 错误,则返回null

    list()

  7、返回一个抽象路径名数组,这些路径名表示此抽象路径名表示的目录中的文件。

    listFiles()

   代码如下:

import java.io.File;
import java.io.FilenameFilter;

public class FileDemo1 {

    public static void main(String[] args) {
        //listRootsDemo();
        //listDemo();
        
        File dir = new File("c:\\");
        File[] files = dir.listFiles();
        for(File f : files) {
            System.out.println(f.getName() + "::" + f.length());
        }
        
    }
    
    /*
     * 专门找指定目录下指定后缀名(例如:.java/.jpg/.mp3/.log)的文件
     */
    public static void listDemo_2() {
        File dir = new File("d:\\java\\io");
        
        String[] arr = dir.list(new FilenameFilter() {
            
            @Override
            public boolean accept(File dir, String name) {
                //System.out.println("dir:" + dir + "...name:" + name);
                /*
                if(name.endsWith(".log"))
                    return true;
                else
                    return false;
                */
                return name.endsWith(".log");
            }
        });
        
        System.out.println("len:" + arr.length);
        for(String name : arr) {
            System.out.println(name);
        }
    }
    
    public static void listDemo() {
        File f = new File("c:\\abc.txt");
        
        String[] names = f.list();//调用list()方法的file对象必须是封装了一个目录。该目录还必须存在。
        for(String name : names) {
            System.out.println(name);
        }
    }
    
    public static void listRootsDemo() {
        File[] files = File.listRoots();
        
        for(File f : files) {
            System.out.println(f.length());
        }
    }

}

   

   递归

   例,列出指定目录下文件或者文件夹,包含子目录中的内容。也就是列出指定目录下的所有内容。

   分析:

   因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身。这种表现形式或者编程手法,称为递归。 

   递归要注意:

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

   代码如下:

import java.io.File;

public class FileDemo2 {

    public static void main(String[] args) {
        File dir = new File("d:\\java");
        showDir(dir, 0);
    }
    /*
     * 分层级列出指定目录下的所有内容
     */
    public static String getLevel(int level) {
        StringBuilder sb = new StringBuilder();
        sb.append("|--");
        for(int x = 0; x < level; x++) {
            //sb.append("|--");
            sb.insert(0, "|  ");
        }
        return sb.toString();
    } 
    public static void showDir(File dir, int level) {
        
        System.out.println(getLevel(level) + dir.getName());
        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]);
            }
            
        }
    }
}

   举例说之,十进制数转二进制数。代码如下:

public class FileDemo0 {

    public static void main(String[] args) {
        toBin(6);
    }
    
    public static void toBin(int num) {
        if(num > 0) {
            toBin(num / 2);
            System.out.print(num % 2);
        }
    }

}

   图解:

   

   

   再举例说之:求和。代码如下:

public class FileDemo0 {

    public static void main(String[] args) {
        int sum = getSum(100);
        System.out.println("sum = " + sum);
    }
    
    public static int getSum(int n) {
        if(n == 1)
            return 1;
        return n + getSum(n - 1);
    }

}

   图解:

   删除一个带内容的目录。

   删除原理:在windows中,删除目录从里面往外删除的。既然是从里往外删除,就需要用到递归。

   代码如下:

import java.io.File;

public class RemoveDir {

    public static void main(String[] args) {
        File f = new File("d:\\java");
        removeDir(f);
    }
    
    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].toString() + ":-file-:" + files[x].delete());
            }
        }
        
        System.out.println(dir + "::dir::"+ dir.delete());
    }

}

 

   Properties

   Properties是HashTable的子类,也就是说它具备map集合的特点,而且他里面存储的键值对都是字符串。是集合和IO技术相结合的集合容器。该对象的特点:可以用于键值对形式的配置文件。那么在加载数据时,需要数据有固定格式,通常是键=值。

   示例代码:

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo0 {

    public static void main(String[] args) throws IOException {
        //setAndGet();
        //method_1();
        loadDemo();
    }
    
    public static void loadDemo() throws IOException {
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("D:\\java\\io123\\info.txt");
        //将流中的数据加载进集合
        prop.load(fis);
        
        prop.setProperty("wangwu", "21");
        
        FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\info.txt");
        
        prop.store(fos, "haha");
        //System.out.println(prop);
        prop.list(System.out);//将属性列表输出到指定的输出流。功能与System.out.println(prop);语句相似
        
        fos.close();
        fis.close();
    }
    
    /*
     * 演示,如何将流中的数据存储到集合中。(也即是Properties类中load(InputStream in)方法的原理)
     * 想要将info.txt中的键值对数据存到集合中进行操作
     * 
     * 1、用一个流和info.txt文件关联
     * 2、读取一行数据,将该行数据用“=”进行切割
     * 3、等号左边作为键,右边作为值。存入到Properties集合中即可。
     */
    public static void method_1() throws IOException {
        BufferedReader bufr = new BufferedReader(new FileReader("D:\\java\\io123\\info.txt"));
        String line = null;
        Properties prop = new Properties();
        while((line = bufr.readLine()) != null) {
            String[] arr = line.split("=");
            prop.setProperty(arr[0], arr[1]);
            //System.out.println(arr[0]+"...."+arr[1]);
        }
        bufr.close();
        System.out.println(prop);
    }
    
    /*
     * 设置和获取元素
     */
    public static void setAndGet() {
        Properties pro = new Properties();
        pro.setProperty("zhangsan", "30");
        pro.setProperty("lisi", "39");
        //System.out.println(pro);
        String value = pro.getProperty("lisi");
        //System.out.println(value);
        
        pro.setProperty("lisi", 89+"");
        
        Set<String> names = pro.stringPropertyNames();
        for(String s : names) {
            System.out.println(s+":"+pro.getProperty(s));
        }
    }
}

 

   打印流

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

   1、字节打印流(PrintStream)

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

  1. file对象。File
  2. 字符串路径。String
  3. 字节输出流。OutputStream  

   2、字符打印流(PrintWriter)

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

  1. file对象。File
  2. 字符串路径。String
  3. 字节输出流。OutputStream
  4. 字符输出流。Writer

   示例代码:

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;

public class PrintStreamDemo {

    public static void main(String[] args) throws IOException {
        BufferedReader bufr = 
                new BufferedReader(new InputStreamReader(System.in));
        
        PrintWriter out = new PrintWriter(new FileWriter("a.txt"), true);//不需要写刷新代码out.flush();自动刷新。
        
        String line = null;
        
        while((line = bufr.readLine()) != null) {
            if("over".equals(line))
                break;
            out.println(line.toUpperCase());
            //out.flush();
        }
        out.close();
        bufr.close();
    }
}

   练习1:将一个指定目录下的java文件的绝对路径,存到一个文本文件中,建立一个java文件列表清单。

   思路:

  1. 对指定的目录进行递归。
  2. 获取递归过程中所有的java文件的路径。
  3. 将这些路径存储到集合中。
  4. 将集合的数据写入到一个文件中。

   代码:

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class JavaFileList {

    public static void main(String[] args) throws IOException {
        File dir = new File("d:\\java");
        List<File> list = new ArrayList<File>();
        fileToList(dir, list);
        File file = new File(dir, "javalist.txt");
        writeToFile(list, file.toString());
        
        //System.out.println(list.size());
    }
    
    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(".java"))
                    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(File f : 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;
            }
        }
            
    }

}

   练习2:用于记录应用程序运行次数,如果使用次数已到,那么给出注册提示。

   分析:

   很容易想到的是:计数器。可是该计数器定义在程序中,随着程序的运行而在内存中存在,并进行自增,可是随着该应用程序的退出,该计数器也在内存中消失了。下一次在启动该程序,又重新开始从0计数。这样不是我们想要的。

   程序即使结束,该计数器的值也存在。下次程序启动会先加载该计数器的值,并+1后重新存储起来。所以要建立一个配置文件,用于记录该软件的使用次数。该配置文件使用键值对的形式,这样便于阅读数据,并操作数据。键值对数据是map集合。数据是以文件形式存储,使用io技术。那么map+io ---> properties。配置文件可以实现应用程序数据的共享。

   代码:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;

public 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 = new FileOutputStream(file);
        prop.store(fos, "");
        
        fos.close();
        fis.close();
        
    }
}

   当然配置文件还有另外一种格式保存,那就是XML,格式如下:

<persons>
    <person id="001">
        <name>zhangsan</name>
        <age>30</age>
        <address>bj</address>
    </person>
    <person id="002">
        <name>zhangsan1</name>
        <age>31</age>
        <address>bj</address>
    </person>
</persons>

   一个用来解析XML格式的文件的工具:dom4j,即dom for(four的谐音) java   

   

   合并流

   SequenceInputStream表示其他输入流的逻辑串联。它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,依次类推,直到到达包含的最后一个输入流的文件末尾为止。

   它有两个构造函数:

  1. SequenceInputStream(Enumeration<? extends InputStream> e),通过记住参数来初始化新创建的SequenceInputStream,该参数必须是生成运行时类型为InputStream对象的Enumeration型参数。
  2. SequenceInputStream(InputStream s1, InputStream s2),通过记住这两个参数来初始化新创建的SequenceInputStream(将按顺序读取这两个参数,先读取 s1,然后读取s2),以提供从此SequenceInputStream读取的字节。

   示例代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

public class SequenceDemo {

    public static void main(String[] args) throws IOException {
        /*
         * 将3个文件中的数据合并到1个文件中
         */
        Vector<FileInputStream> v = new Vector<FileInputStream>();
        v.add(new FileInputStream("D:\\java\\io123\\1.txt"));
        v.add(new FileInputStream("D:\\java\\io123\\2.txt"));
        v.add(new FileInputStream("D:\\java\\io123\\3.txt"));
        Enumeration<FileInputStream> en = v.elements();
        
        SequenceInputStream sis = new SequenceInputStream(en);
        
        FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\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();
    }

}

   有合并文件,那么就有切割文件

   例,切割一张图片,再合成为一张完整的图片。

   代码:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;

public class SplitFile {

    public static void main(String[] args) throws IOException {
        //splitFile();
        merge();
    }
    
    /*
     * 合并图片
     */
    public static void merge() throws IOException {
        //使用Vector的效率很低下,所以使用List集合
        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
        
        for(int x = 1; x < 6; x++) {
            al.add(new FileInputStream("D:\\java\\io123\\split\\"+x+".part"));
        }
        /*
         * 匿名内部类访问局部变量,所以要用final修饰
         */
        final Iterator<FileInputStream> it = al.iterator();
        /*
         * 枚举,匿名内部类
         * 虽然见过Enumeration,但是从来没这么写过,这是用ArrayList来实现一个Enumeration。
         * 即使用Enumeration来访问ArrayList。
         */
        Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {

            @Override
            public boolean hasMoreElements() {
                return it.hasNext();
            }

            @Override
            public FileInputStream nextElement() {
                return it.next();
            }
            
        };
        
        
        SequenceInputStream sis = new SequenceInputStream(en);
        
        FileOutputStream fos = new FileOutputStream("D:\\java\\io123\\ye.JPG");
        
        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("D:\\java\\io123\\DSC_0206.JPG");
        
        FileOutputStream fos = null;
        byte[] buf = new byte[1024 * 1024];//1MB大小的字节数组
        
        int len = 0;
        int count = 1;
        while((len = fis.read(buf)) != -1) {
            fos = new FileOutputStream("D:\\java\\io123\\split\\"+(count++)+".part");
            fos.write(buf, 0, len);
            fos.close();
        }
        fis.close();
    }

}

 

posted @ 2016-03-13 16:25  叶十一少  阅读(335)  评论(0编辑  收藏  举报