Java文件与IO

File类

代表计算机各个文件,目录的抽象表现形式,可以实现文件的创建,删除等

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

public class FileDemo {
    public static void main(String[] args) {
        //File类表示一个文件或目录
        //指定在哪里创建
        //第一种使用方法
        File f1 = new File("/home/xiaoming/音乐/java/vince.text");
        //第二种使用方法,使用类中的常量separator表示斜杠
        File f2 = new File(File.separator+"home"
                +File.separator+"xiaoming"
                +File.separator+"音乐"+File.separator
                +"java"+File.separator+"tey.text");
        //判断文件是否已经存在
        if(!f1.exists()) {
            try {
                f1.createNewFile();//创建文件
                System.out.println("文件创建成功");
            } catch (IOException e) {
                // 基本上IO操作都报这个错误
                e.printStackTrace();
            }
        }
        //判断对象是否是文件
        System.out.println(f1.isFile());
        //判断该对象是否为文件夹
        System.out.println(f1.isDirectory());
        
        //删除文件夹(前提文件夹里无文件)
        File f3 = new File("/home/xiaoming/音乐/java");
        boolean b = f3.delete();
        System.out.println(b);
        
        //列出所有文件名,若是文件夹,则列出文件夹名
        String[] name = f3.list();
        System.out.println(Arrays.toString(name));
        
        //列出当前目录下的所有文件,以file对象返回
        File[] f4 = f3.listFiles();
        for(File f:f4) {
            System.out.println(f.length());
            System.out.println(f.getName());
            System.out.println(f.getPath());//相对路径
            System.out.println(f.getAbsolutePath());//绝对路径
            System.out.println(f.isHidden());//是否隐藏文件
            System.out.println(f.canRead());
            Date date = new Date(f.lastModified());//最后修改时间
            DateFormat df = new SimpleDateFormat("HH:mm:ss");
            System.out.println(df.format(date));
        }
        
        //创建文件夹
        File f5 = new File("/home/xiaoming/音乐/java1");
        f5.mkdir();
        f5.mkdirs();//一次性创建所有指定文件夹
        
        //重命名与移动文件
        f5.renameTo(new File("/home/xiaoming/音乐/Text1"));
        
        //过滤器
        File[] files = f5.listFiles(new FileFilter() {
            
            //从写此方法,用于查找出指定文件
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".text");
            }
        });
        //第二种写法
        File[] files_s  = f5.listFiles((pathname)->pathname.getName().endsWith(".text"));
        for(File f:files) {
            System.out.println(f.getName());
        }
    }
}

字节输出,输入流

输出输入是从程序的角度看的
OutputStream,InputStream是所有类的超类,要向文件中进行操作,使用子类FileOutputStream,FileInputStream
write,read的具体实现都是一个字节一个字节进行读取的

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class IOStreamDemo {

    public static void main(String[] args) {
        out();
        in();
        
    }
    
    //文件输出流(写入文件)
    private static void out() {
        
        //确定目标文件
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        //构建一个文件输出流对象
        try {
            OutputStream out = new FileOutputStream(file,true);//第二个参数append默认为false,true时表示追加
            
            //输出(写入)的内容
            String info = "小桥流水人家\n";
            //把内容写入文件
            out.write(info.getBytes());//write方法接收byte类型参数
            //关闭流
            out.close();
            System.out.println("输出成功!");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //文件写入流(输出文件内容)
    private static void in() {
        //确定目标文件
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        //构建一个文件输入流对象
        try {
            InputStream in = new FileInputStream(file);
            
            byte[] bytes = new byte[1024];//单数用中文会造成乱码,解决办法使用字符流
            StringBuilder buf = new StringBuilder();
            int len = -1;//表示每次读取的长度
            //把数据读入数组中,并返回每次读取的字节数,当不等于-1时表示读取到数据,等于-1表示读取不到数据
            /*
             * @Return
             * the total number of bytes read into the buffer, 
             * or -1 if there is no more data 
             * because the end of the stream has been reached.
             */
            while((len = in.read(bytes))!=-1) {
                //根据读取到的字节数组,再转换为字符串内容,添加到StringBuilder中
                //当读取的字符数多余字符数组大小时,新读的内容会自动替换掉从头已读的内容,但后面的原有已读内容任然保留,这时候需要加入len指定读取到的位置,避免最后读出的内容与前面重复
                buf.append(new String(bytes,0,len));
            }
            //打印内容
            System.out.println(buf);
            //关闭输入流
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

字符输出,输入流

字符流的内部实现还是字节流
字符输出流:Writer,对文件的操作使用子类FileWriter
字符输入流:Reader,对文件的操作使用子类FileReader
每次操作都是一个字符
文件字符操作流会自带缓存,默认大小为1024字节,在缓存满或手动刷新或关闭流时会写入文件,但是字节操作流没有缓存,直接写入
一般操作非文本文件时,使用字节流,操作文本文件时,使用字符流

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

//字符流
public class CharStreamDemo {
    public static void main(String[] args) {
        out();
        in();
    }

    // 字符输出流
    private static void out() {
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        try {
            Writer out = new FileWriter(file, true);
            out.write("小桥流水人家,古道西风瘦马\r\n");
            System.out.println("写入文件成功");
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 字符输入流
    private static void in() {
        File file = new File("/home/xiaoming/音乐/java/vince.text");

        try {
            Reader in = new FileReader(file);
            char[] cs = new char[5];
            int len = -1;
            StringBuilder buf = new StringBuilder();
            while((len = in.read(cs))!=-1) {
                buf.append(new String(cs,0,len));
            }
            System.out.println(buf);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字节字符转换流

OutputStreamWriter:可以将输出的字符转换成字节流的输出形式
InputStreamReader:可以将输入的字节流转化为字符形式的输入流

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.charset.Charset;

//字节字符转换流
public class StreamChangeDemo {
    
    public static void main(String[] args) {
        
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(file);
            out = new FileOutputStream(file,true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        read(in);
        write(out);
    }
    
    //输入流:字节转字符
    private static void read(InputStream in) {
        //将字节输入流转换成字符输入流,可以指定编码方法
        Reader reader = new InputStreamReader(in,Charset.defaultCharset());
        char[] cs = new char[1024];
        int len = -1;
        
        try {
            while((len = reader.read(cs)) != -1) {
                System.out.println(new String(cs,0,len));
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //输出流:字符转字节
    private static void write(OutputStream out) {
        Writer writer = new OutputStreamWriter(out);
        
        try {
            writer.write("新年快乐!!!");
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

字节字符缓冲流

先将数据缓冲起来,再一起写入或者读取出来,提高效率
BufferedInputStream,BufferedOutputStream为两个字节缓冲流的类
内部默认缓存大小为8KB,每次写入时存储到缓存中的byte数组,当数组存满时,会把数组中的数据写入文件,并且缓存下标归零
BufferedReader
BufferedWriter

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;


public class BufferStreamDemo {
    public static void main(String[] args) {
        byteWriter();
        byteReader();
        
        charWriter();
        charReader();
    }
    
    //缓冲字节输出
    private static void byteWriter() {
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        
        try {
            OutputStream out = new FileOutputStream(file,true);
            //构造一个字节缓冲流
            BufferedOutputStream bos = new BufferedOutputStream(out);
            String info = "枯藤老树昏鸦\r\n";
            bos.write(info.getBytes());
            bos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //缓冲字节输入
    private static void byteReader() {
        
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        
        try {
            InputStream in = new FileInputStream(file);
            //构造缓冲流
            BufferedInputStream bis = new BufferedInputStream(in);
            byte[] bytes = new byte[1024];
            int len = -1;
            while((len = bis.read(bytes))!=-1) {
                System.out.println(new String(bytes,0,len));
            }
            bis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //缓冲字符输出
    private static void charWriter() {
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        try {
            Writer writer = new FileWriter(file,true);
            //构造缓存器
            BufferedWriter bw = new BufferedWriter(writer);
            bw.write("夕阳西下\r\n");
            bw.flush();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //缓冲字符输入
    private static void charReader() {
        File file = new File("/home/xiaoming/音乐/java/vince.text");
        try {
            Reader reader = new FileReader(file);
            BufferedReader br = new BufferedReader(reader);
            char[] cs = new char[1024];
            int len = -1;
            while((len=br.read(cs))!=-1) {
                System.out.println(new String(cs,0,len));
            }
            br.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }	
    }
}

打印流

便利输出
PrintStream
PrintWriter

File file = new File("xxxx");
OutputStream out = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(out);//加缓存
PrintStream ps = new PrintStream(bos);//增强打印流
ps.println("xxxxx");
ps.close;

对象流和序列化

序列化:将对象的状态信息转化为可以存储或传输的形式
反序列化:将已经序列化的对象重新转换成对象的状态信息
对象流的两个类:ObjectOutputStream将java对象的基本数据类型和图形写入OutputStream,ObjectInputStream对写入ObjectOutputStream的基本数据和对象进行反序列化
需要序列化的情况:

  1. 把对象保存到文件中
  2. 对象需要在网络中传输时
import java.io.Serializable;

//继承标记接口表示该类需要进行序列化,否则会报java.io.NotSerializableException错误
public class Dog implements Serializable{

    /**
     * 定义版本号,防止两个不同对象因属性一样造成混乱
     */
    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    private String sex;
    //可以使用关键字transient声明一个变量在存储时不需要维持其具体值(默认0或null)
    private transient int id;
    public Dog() {
        super();
    }

    public Dog(String name, int age, String sex) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public String toString() {
        return "Dog [name=" + name + ", age=" + age + ", sex=" + sex + ", getName()=" + getName() + ", getAge()="
                + getAge() + ", getSex()=" + getSex() + "]";
    }

}

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class ObjectStreamDemo {
    public static void main(String[] args) {
        writeObject();
        readObject();
    }

    //对象序列化
    public static void writeObject() {
        Dog dog = new Dog("猪猪",6,"girl");
        //当要读取多个对象时,使用数组
        //Dog[] dogs = {dog1,dog2};
        File file = new File("/home/xiaoming/音乐/java/ObjectStream.text");
        try {
            OutputStream out = new FileOutputStream(file);
            ObjectOutputStream oos = new ObjectOutputStream(out);
            oos.writeObject(dog);//多个时改为dogs
            oos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    //对象反序列化
    public static void readObject() {
        Dog dog = new Dog("猪猪",6,"girl");
        File file = new File("/home/xiaoming/音乐/java/ObjectStream.text");
        try {
            InputStream in = new FileInputStream(file);
            ObjectInputStream ois= new ObjectInputStream(in);
            Dog dog2 = (Dog)ois.readObject();
            //多个时:Dog[] dog = (Dog[])ois.readObject();
            System.out.println(dog2);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

字节数组流

基于内存操作,内部维护着一个字节数组,可以利用流的读取机制来处理字符串
与文件操作无关,无需关闭
ByteArrayInputStream
ByteArrayOutputStream

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

public class ByteArrayStreamDemo {

    public static void main(String[] args) {
        byteArray();
    }
    
    private static void byteArray() {
        
        String s = "123456789sljtiegrgGRGFRTGAFWER(*&*^&%%$@#)";
        ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int curr = -1;//每次读取的字节
        while((curr = bais.read())!=-1) {
            if((curr>=65 && curr<=90) || (curr>=97 && curr<=122)) {
                baos.write(curr);
            }
        }
        //此时无需关闭,因为字节数组流是基于内存的操作流
        System.out.println(baos.toString());
    }
}

数据流

应用程序以与机器无关的方式从底层输出或输入java基本数据类型
DataInputStream
DataOutputStream

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class DataStreamDemo {

    public static void main(String[] args) {
        write();
        read();
    }
    
    private static void write() {
        File file = new File("/home/xiaoming/音乐/java/vince.data");
        try {
            OutputStream out = new FileOutputStream(file);
            BufferedOutputStream bos = new BufferedOutputStream(out);
            DataOutputStream dos = new DataOutputStream(bos);
            dos.writeInt(15);//4个字节
            dos.writeByte(1);//写入1个字节
            dos.writeUTF("花花卡");
            
            dos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private static void read() {
        File file = new File("/home/xiaoming/音乐/java/vince.data");
        try {
            InputStream in = new FileInputStream(file);
            BufferedInputStream bis = new BufferedInputStream(in);
            DataInputStream dis = new DataInputStream(bis);
            int num = dis.readInt();
            byte b = dis.readByte();
            String s =dis.readUTF();
            System.out.println(num+","+b+","+s);
            
            dis.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

文件分割与合并

合并流SequenceInputStream

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;

/*
 * 文件的分割和合并
 */
public class FileDivisionMergeDemo {

    public static void main(String[] args) {
        //分割
        File file = new File(
                "/media/M_fM__VM__GM_fM_!M_#/编程语言/Java/课程/千锋Java基础教程-Java基础(完结-217集)/千锋java基础教程:第10章 多线程与并发(12集)/第10章 多线程与并发_12_线程生命周期与线程池_小结.mp4");
        division(file, 1024 * 1024 * 10);
        System.out.println("分割成功");
        
        //合并
        Vector<InputStream> v = new Vector<InputStream>();
        for(int i=1;i<=59;i++) {
            try {
                InputStream in = new FileInputStream(new File("/home/xiaoming/音乐/java/花花卡" + i + ".mp4"));
                v.add(in);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        Enumeration<InputStream> es = v.elements();
        merge(es);
    }

    /**
     * 文件切割
     * 
     * @param file    要切割的文件
     * @param cutSite 切割后每份文件的大小
     */
    private static void division(File targetFile, long cutSize) {

        if (targetFile == null)
            return;
        // 计算文件的总分割数
        int num = (targetFile.length() % cutSize == 0) ? (int) (targetFile.length() / cutSize)
                : (int) ((targetFile.length() / cutSize) + 1);
        try {
            // 构造一个文件输入流
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(targetFile));
            BufferedOutputStream out = null;

            byte[] bytes = null;// 每次希望读取的最大字节数
            int len = -1;// 每次读取的字节数
            int count = 0;// 每一个文件要读取的次数

            for (int i = 1; i < num; i++) {
                out = new BufferedOutputStream(new FileOutputStream("/home/xiaoming/音乐/java/花花卡" + i + ".mp4"));

                if (cutSize <= 1024) {
                    bytes = new byte[(int) cutSize];
                    count = 1;
                } else {
                    bytes = new byte[1024];
                    count = (int) cutSize / 1024;
                }

                // 边读边写入,不然会刷新数组,写入不了
                // 判断条件应该把读放在后面,防止多读一次
                while (count > 0 && (len = in.read(bytes)) != -1) {
                    out.write(bytes);
                    out.flush();
                    count--;
                }

                // 如果余数不为零,数组不整除就需要多读一遍
                if ((int) cutSize % 1024 != 0) {
                    bytes = new byte[(int) cutSize % 1024];
                    len = in.read(bytes);
                    out.write(bytes, 0, len);
                    out.flush();
                }
                out.close();// 关闭本次输出流
            }
            in.close();// 最后才关闭输入流

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
    
    private static void merge(Enumeration<InputStream> es) {
        //构造一个合并流
        SequenceInputStream sis = new SequenceInputStream(es);
        
        try {
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream("/home/xiaoming/音乐/java/花花卡.mp4"));
            byte[] bytes = new byte[1024];
            int len = -1;
            while((len=sis.read(bytes))!=-1) {
                bos.write(bytes,0,len);
                bos.flush();
            }
            bos.close();
            sis.close();
            System.out.println("合并完成");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
}

字符串流

StringReader以一个字符串为数据源,来构造一个字符流
StringWriter无需关闭

import java.io.IOException;
import java.io.StreamTokenizer;
import java.io.StringReader;

//字符串流
public class StringStreamDemo {

    private static void stringReader() {
        String info = "中 大 奖,花 呗 免 单!";
        StringReader sr = new StringReader(info);
        //流标记器
        StreamTokenizer st = new StreamTokenizer(sr);
        
        int count = 0;//计算总数
        //TT_EOF表示读到流的末尾,ttype是每一次读取返回的类型
        while(st.ttype != StreamTokenizer.TT_EOF) {
            try {
                //TT_WORD表示读取的内容是文字
                if(st.nextToken()==StreamTokenizer.TT_WORD) {
                    count++;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        sr.close();
        System.out.println("count="+count);
    }
    public static void main(String[] args) {
        stringReader();
    }
}

RandomAccessFile

直接继承Object类,只可以对文件进行操作,有两种模式(r,rw)

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo {

    public static void main(String[] args) {
        try {
            RandomAccessFile r = new RandomAccessFile("/home/xiaoming/音乐/java/vince.text", "r");
            RandomAccessFile w = new RandomAccessFile("/home/xiaoming/音乐/java/vince2.text","rw");
            
            byte[] bytes = new byte[1024];
            int len = -1;
            while((len = r.read(bytes))!= -1) {
                w.write(bytes,0,len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("copy success");
    }
}

Properties文件操作类

主要用于读取配置文件

//properties配置文件
#update config
#Sun Feb 03 10:58:41 CST 2019
db.password=987654321
db.username=xiaoming
app.version=2

//对配置文件的操作
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

public class PropertiesDemo {
    
    public static String version = "";
    public static String username = "";
    public static String password = "";
    
    //静态代码块,在创建对象时执行一次
        static {
            readConfig();
        }
    /**	
     * 输出操作
     */
    private static void readConfig() {
        
        Properties p = new Properties();
        try {
            InputStream inStream = new FileInputStream("config.properties");
            //当文件不在当前项目根目录下时,使用如下方式指定路径
//			InputStream inStream1 = Thread.currentThread().getContextClassLoader()
//					.getResourceAsStream("com/res/config.properties");
            p.load(inStream);//加载文件
            
            //从properties中获取数据
            
            version = p.getProperty("app.version");
            username = p.getProperty("db.username");
            password = p.getProperty("db.password");
            
            inStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 写入操作
     * @param version
     * @param username
     * @param password
     */
    private static void writeConfig(String version,String username,String password) {
        Properties p = new Properties();
        //把属性写入变量p
        p.put("app.version",version);
        p.put("db.username", username);
        p.put("db.password",password);
        try {
            OutputStream outStream = new FileOutputStream("config.properties");
            //写入文件,第二个参数是注释
            p.store(outStream, "update config");
            outStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        //readConfig();
        writeConfig("2", "xiaoming", "987654321");
        System.out.println(PropertiesDemo.version);
        System.out.println(PropertiesDemo.username);
        System.out.println(PropertiesDemo.password);
    }
}

文件压缩和解压缩

压缩:ZipOutputStream
ZipOutputStream(OutputStream out):创建新的ZIP输出流
void putNextEntry(ZipEntry e):开始写入新的ZIP文件条目并将流定位到条目数据的开始处
ZipEntry(String name):使用指定名创建新的ZIP条目
解压:ZipInputStream
ZipInputStream(InputStream in):创建新的ZIP输入流
ZipEntry getNextEntry():读取写一个ZiP文件条目并将流定位到该条目数据的开始处

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 压缩和解压缩实例
 * 
 * @author xiaoming
 *
 */
public class CompressionAndDecompressionDemo {

    public static void main(String[] args) {
        File file = new File("/home/xiaoming/音乐/12345");
        compression("/home/xiaoming/音乐/123456789.zip", file);

        decompression("/home/xiaoming/音乐/123456789.zip", "/home/xiaoming/音乐");

    }

    /**
     * 压缩
     * 
     * @param zipFileName 希望压缩后的文件名(路径)
     * @param targetFile  目标文件
     * @return
     */
    private static void compression(String zipFileName, File targetFile) {
        System.out.println("正在压缩...");
        try {
            ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFileName));
            // 添加缓存加快效率
            BufferedOutputStream bos = new BufferedOutputStream(out);
            // 进行压缩
            zip(out, targetFile, targetFile.getName(), bos);
            bos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("压缩完成!!!");
    }

    /**
     * 执行具体的压缩操作
     * 
     * @param out            对文件进行压缩的类
     * @param targetFile     目标文件
     * @param targetFileName 要压缩文件的文件名
     * @param bos            缓存流
     * @throws IOException
     */
    private static void zip(ZipOutputStream out, File targetFile, String targetFileName, BufferedOutputStream bos)
            throws IOException {
        // 判断是目录还是文件夹
        if (targetFile.isDirectory()) {
            // 如果是空目录
            if (targetFile.length() == 0) {
                out.putNextEntry(new ZipEntry(targetFileName));// 处理空目录
            }
            File[] files = targetFile.listFiles();
            for (File f : files) {
                zip(out, f, targetFileName + "/" + f.getName(), bos);
            }
        } else {
            out.putNextEntry(new ZipEntry(targetFileName));
            FileInputStream in = new FileInputStream(targetFile);
            BufferedInputStream bis = new BufferedInputStream(in);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            bis.close();
        }
    }

    /**
     * 解压
     * 
     * @param targetFileName 要解压的文件名
     * @param parent         解压到的位置
     */
    private static void decompression(String targetFileName, String parent) {
        // 构造解压的输入流
        ZipInputStream zIn;
        try {
            zIn = new ZipInputStream(new FileInputStream(targetFileName));
            ZipEntry entry = null;
            File file = null;
            while ((entry = zIn.getNextEntry()) != null && !entry.isDirectory()) {
                file = new File(parent, entry.getName());
                if (!file.exists()) {
                    new File(file.getParent()).mkdirs();// 创建此文件的上级目录
                }
                OutputStream out = new FileOutputStream(file);
                BufferedOutputStream bos = new BufferedOutputStream(out);
                byte[] bytes = new byte[1024];
                int len = -1;
                while ((len = zIn.read(bytes)) != -1) {
                    bos.write(bytes, 0, len);
                }
                bos.close();
                System.out.println(file.getAbsolutePath() + "解压成功");
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

New IO(NIO)

原来的IO采用流的方式处理数据,为NIO以块的方式处理数据,效率更高,在NIO中,所有的数据都是在缓冲区处理,缓冲区实际上是一个数组

缓冲区

缓冲区的类型:

  • ByteBuffer
  • CharBuffer
  • ShortBuffer
  • LongBuffer
  • DoubleBuffer
  • IntBuffer
  • FloatBuffer
package nio;

import java.nio.ByteBuffer;

public class NIODemo {

    public static void main(String[] args) {
        //创建一个字节缓冲区,申请内存空间为8字节,参数为申请的内存空间
        ByteBuffer buf = ByteBuffer.allocate(8);
        
        //查看其内部属性值
        System.out.println("position="+buf.position());
        System.out.println("limit="+buf.limit());
        System.out.println("capacity="+buf.capacity());
        
        //向缓冲区写入数据
        buf.put((byte)10);
        buf.put((byte)20);
        buf.put((byte)30);
        buf.put((byte)40);
        
        System.out.println("position="+buf.position());
        System.out.println("limit="+buf.limit());
        System.out.println("capacity="+buf.capacity());
        
        //缓冲区反转(把limit设置为position的值,并把positon置零),在取值前使用
        buf.flip();
        System.out.println("position="+buf.position());
        System.out.println("limit="+buf.limit());
        System.out.println("capacity="+buf.capacity());
        
        //取值
        //判断当前位置与限制元素之间是否有元素
        if(buf.hasRemaining()) {
            //返回当前位置与限制之间的元素数
            for(int i=0;i<buf.remaining();i++) {
                byte b = buf.get(i);//取值
                System.out.println(b);
            }
        }		
    }
}

通道:Channel

数据通过通道进出缓冲区,Channel是一个类

/**
 * 文件复制实例
 */
package nio;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

public class CopyFileDemo {
    
    public static void main(String[] args) {
        try {
            copyFile();
            randomAccessFileCopy();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    //NIO方式
    private static void copyFile() throws IOException {
        //创建一个输入文件的通道
        FileChannel in = new FileInputStream("/home/xiaoming/图片/v2-c4a14410a05ed4ddede728e6d467effc_r.jpg").getChannel();
        //创建一个输出文件的通道
        FileChannel out = new FileOutputStream("/home/xiaoming/音乐/background.jpg").getChannel();
        
        ByteBuffer buf = ByteBuffer.allocate(1024);
        while(in.read(buf)!=-1) {
            buf.flip();
            out.write(buf);
            buf.clear();
        }
        in.close();
        out.close();
        System.out.println("copy success");
    }
    
    //印射方式
    private static void randomAccessFileCopy() throws IOException {
        RandomAccessFile in = new RandomAccessFile("/home/xiaoming/图片/v2-c4a14410a05ed4ddede728e6d467effc_r.jpg","r");
        RandomAccessFile out = new RandomAccessFile("/home/xiaoming/音乐/background1.jpg", "rw");
        
        FileChannel fcIn = in.getChannel();
        FileChannel fcOut = out.getChannel();
        
        long size = fcIn.size();//输入流的字节大小
        //输入流的缓冲区
        MappedByteBuffer inBuf = fcIn.map(MapMode.READ_ONLY, 0, size);
        //输出流的缓冲区
        MappedByteBuffer outBuf = fcOut.map(MapMode.READ_WRITE, 0, size);
        
        for(int i=0;i<size;i++) {
            outBuf.put(inBuf.get());
        }
        fcIn.close();
        fcOut.close();
        in.close();
        out.close();
        System.out.println("copy success");
    }
}

IO操作的性能比较:

  1. 内存印射最快
  2. NIO读写
  3. 使用缓存的IO流
  4. 普通无缓存IO

Path接口

Path表示一个目录名,表示具体路径

package nio;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

public class PathFileDemo {

    public static void main(String[] args) {
        File file = new File("/home/xiaoming/音乐/background.jpg");
        
        //path,通过这种方式获取文件
        Path p1 = Paths.get("/home/xiaoming/音乐","background.jpg");
        System.out.println(p1);
        
        Path p2 = file.toPath();
        System.out.println(p2);
        
        //toPath方法的具体实现方法
        Path p3 = FileSystems.getDefault().getPath("/home/xiaoming/音乐","background.jpg");
        
        //Files工具类
        Path p4 = Paths.get("/home/xiaoming/音乐/工具类.text");
        String info = "一闪一闪亮晶晶";
        try {
            Files.write(p4, info.getBytes("gb2312"), StandardOpenOption.CREATE_NEW);
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        try {
            byte[] bytes = Files.readAllBytes(p4);
            System.out.println(new String(bytes));
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        //复制(第三个参数可选)
        try {
            Files.copy(p3, Paths.get("/home/xiaoming/音乐/background2.jpg"),StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //移动文件
        try {
            Files.move(p3, Paths.get("/home/xiaoming/音乐/background2.jpg"),StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //删除文件
        try {
            Files.delete(p3);
            Files.deleteIfExists(p3);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //创建目录文件
        try {
            Files.createDirectory(Paths.get("/home/xiaoming/音乐/abc"));//除了最后的一个部件,其他的必须是已存在的
            Files.createDirectories(Paths.get("/home/xiaoming/音乐/abc"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //创建文件
        try {
            Files.createFile(Paths.get("/home/xiaoming/音乐/abc.txt"));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //添加前后缀创建临时文件或临时目录
        //Path newPath = Files.createTempFile(prefix, suffix, attrs);
        //Path newPath = Files.createTempDirectory(dir, prefix);

    }
    
}