zoukankan      html  css  js  c++  java
  • 25. IO流.md


    IO分类:

    字节流&字符流的IO操作:

    • 字节流:输入输出和字符有关的操作
      • IO类:FileInputStream和FileOutPutStream;缓冲:BufferedInputStream和BufferedOutStream
    • 字符流:输入输出和字符无关的操作
      • IO类:FileReader和 FileWriter;缓冲:BufferedReader和BufferedWriter

    1.FIle类

    1.1目录分隔符

    不同机器上目录分隔符是不一样的,所以用File类的成员变量separator来表示:

    public static final String separator = "" + separatorChar;  
    
    

    注意:windows上认两种目录分隔符,也就是正(/)反()都可以

    1.2常用方法

    • 创建:

    createNewFile() 在指定位置创建一个空文件,成功就返回true,如果已存在就不创建然后返回false
    mkdir() 在指定位置创建目录,这只会创建最后一级目录,如果上级目录不存在就抛异常。
    mkdirs() 在指定位置创建目录,这会创建路径中所有不存在的目录。
    renameTo(File dest) 重命名文件或文件夹,也可以操作非空的文件夹,文件不同时相当于文件的剪切,剪切时候不能操作非空的文件夹。移动/重命名成功则返回true,失败则返回false。

    • 删除:

    delete() 删除文件或一个空文件夹,如果是文件夹且不为空,则不能删除,成功返回true,失败返回false。

       deleteOnExit()    在虚拟机终止时,请求删除此抽象路径名表示的文件或目录,保证程序异常时创建的临时文件也可以被删除
    
    • 判断:

    exists() 文件或文件夹是否存在。

       isFile()      是否是一个文件,如果不存在,则始终为false。
       isDirectory() 是否是一个目录,如果不存在,则始终为false。
       isHidden()    是否是一个隐藏的文件或是否是隐藏的目录。
       isAbsolute()  测试此抽象路径名是否为绝对路径名。
    
    • 获取:

    getName() 获取文件或文件夹的名称,不包含上级路径。

    getPath() 返回绝对路径,可以是相对路径,但是目录要指定
    getAbsolutePath() 获取文件的绝对路径,与文件是否存在没关系
    length() 获取文件的大小(字节数),如果文件不存在则返回0L,如果是文件夹也返回0L。
    getParent() 返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回null。
    lastModified() 获取最后一次被修改的时间。
    文件夹相关:
    staic File[] listRoots() 列出所有的根目录(Window中就是所有系统的盘符)
    list() 返回目录下的文件或者目录名,包含隐藏文件。对于文件这样操作会返回null。
    list(FilenameFilter filter) 返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null。
    listFiles() 返回目录下的文件或者目录对象(File类实例),包含隐藏文件。对于文件这样操作会返回null。
    listFiles(FilenameFilter filter) 返回指定当前目录中符合过滤条件的子文件或子目录。对于文件这样操作会返回null

    2.FileInputStream类

    2.1读取文件

    使用FileInputStream类可以用read方法,这个方法的不同重载都可以实现读取文件:

    
    package per.liyue.code.filedemo;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    public class Demo1 {
        public static void main(String[] args) throws IOException {
            // TODO Auto-generated method stub
            File file = new File("");
            String separator = file.separator;
            
            ReadFile1(separator);
            ReadFile2(separator);
        }
        
        //直接读取
        public static void ReadFile1(String separator) throws FileNotFoundException, IOException {
            File fileOpen = new File("d:" + separator + separator + "a.txt");
            if (fileOpen.exists()) {
                FileInputStream in = new FileInputStream(fileOpen);
                
                //read方法
                int concent = 0;
                System.out.println("read方法while读取:");
                while(-1 != concent){
                    concent = in.read();
                    System.out.print((char)concent);
                }
                in.close();
            }
        }
        
        //byte数组读取
        public static void ReadFile2(String separator) throws FileNotFoundException, IOException {
            File fileOpen = new File("d:" + separator + separator + "a.txt");
            if (fileOpen.exists()) {
                FileInputStream in = new FileInputStream(fileOpen);
                
                //byte方法-一般数组大小为1024倍数
                byte[] b = new byte[2];
                System.out.println("byte方法while读取:");
                int length = 0;
                while(-1 != (length = in.read(b))){
                    System.out.print(new String(b, 0, length));
                }
                in.close();
                Arrays
            }
        }
    
    }
    

    读取文件的注意事项

    • 使用byte的方法效率高!

    • 重要的事情说三遍:一定要关闭资源!一定要关闭资源!一定要关闭资源!

    3.FileOutputStream类

    FileOutputStream 的write方法可以写:

    每次写之前先清空目标文件

    
    public static void WriteNew(String separator) throws FileNotFoundException, IOException {
            File fileWrite = new File("d:" + separator + separator + "a.txt");
            FileOutputStream out = new FileOutputStream(fileWrite);
            String concent = "1234567890abcdef";
            out.write(concent.getBytes());
            out.close();
        }  
    
    
    

    每次追加到最后

    
    public static void WriteEnd(String separator) throws FileNotFoundException, IOException {
            File fileWrite = new File("d:" + separator + separator + "a.txt");
            FileOutputStream out = new FileOutputStream(fileWrite, true);
            String concent = "1234567890abcdef";
            out.write(concent.getBytes());
            out.close();
        }  
    
    
    

    拷贝文件

    拷贝文件需要边读边拷写:

    
        public static void main(String[] args) throws IOException {
            // TODO Auto-generated method stub
            File file = new File("");
            String separator = file.separator;
            
            //缓冲
            byte[] b = new byte[1024];
            //拷贝源
            File fileSour = new File("D:" + separator + "a.bmp");
            FileInputStream fileIn = new FileInputStream(fileSour);
            //目标源
            File fileTar = new File("D:" + separator + "b.bmp");
            FileOutputStream FileOut = new FileOutputStream(fileTar, true);
            
            //开始拷贝
            int concent = 0;
            while(-1 != (concent = fileIn.read(b))){
                FileOut.write(b, 0, concent);
                //这样拷贝会增大文件,因为最后不满1024也按照1024拷贝了
                //out.write(b);
            }
            fileIn.close();        
            FileOut.close();
        }  
    
    
    

    4.缓冲流

    4.1 BufferedInputStream

    • BufferedInputStream其实只是在内部维护了一个8KB的字节数组,快的原因和上面byte[]一样,每次从缓冲数组中读取,减少IO次数

    • BufferedInputStream的close实际上是调用父类的方法。

    4.2 BufferedOutputStream

    • BufferedOutputStream的内部也是维护了一个字节数组。

    • BufferedOutputStream真正写入文件的时机:

      • 调用其close方法

      • 调用其flush方法

      • 当内部缓冲数组满了也会写入

    5.字符流

    字符流的操作和字节流类似

    5.1BufferedReader

    5.2 BufferedWriter



    6.序列流

    • Serializable称作标志接口,对象的输入输出必须实现此接口,称作序列化。
    • 这个接口没有方法,输出中只需要实现此接口!
    • 对象的反序列化并不会创建对象
    • 反序列化读取的时候,使用serialVersionUID来判断是否是同一个序列化对象,如果反序列化的时候,类对象经过变更,不同于序列化时候,反序列化就会失败。对于需要的情况,可以使用默认的serialVersionUID(在类名上Ctrl+1`)来避免无法序列化的问题,但是要注意,反序列化必须对应的是同一个类
    • 如果序列化的类中包含了另一个没有序列化的类是不可以的
    package per.liyue.code.serializabledemo;
    import java.io.Serializable;
    public class Employee implements Serializable{
        //使用默认的serialVersionUID
        private static final long serialVersionUID = 1L;
        private int id;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        private int age;
    }
    
    package per.liyue.code.serializabledemo;
    import java.io.Serializable;
    public class User implements Serializable{
        //使用默认的serialVersionUID
        private static final long serialVersionUID = 1L;
        private String name;
        //可以下序列化写文件以后,增加这个成员变量,用反序列化读取实验serialVersionUID的作用
        //private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        @Override
        public String toString() {
            // TODO Auto-generated method stub
            return "用户的名字是:" + this.name;
        }
    }
    
    package per.liyue.code.serializabledemo;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    public class DemoPrint {
        public static void main(String[] args) throws IOException, ClassNotFoundException{
            //序列化对象
            WriteData();
            //反序列化对象
            ReadData();
        }
        public static void ReadData() throws IOException, FileNotFoundException, ClassNotFoundException {
            ObjectInputStream inStream = new ObjectInputStream(new FileInputStream(new File("D:\a.txt")));
            //这里直接强转了,并没有创建新的类对象,克隆的时候也是一样的没有创建类对象
            User u = (User)inStream.readObject();
            System.out.println(u);
            //如果下面反序列化的是Employee类,那么必定会报错
    //        Employee u = (Employee)inStream.readObject();
    //        System.out.println(u);
            inStream.close();
        }
        public static void WriteData() throws IOException, FileNotFoundException {
            ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream(new File("D:\a.txt")));
            User u = new User();
            u.setName("张三");
            outStream.writeObject(u);
            outStream.close();
        }
    }
    

    如果一个成员变量不想被序列化,可用关键字**transient **修饰:

    //使用transient关键字修饰后不会被序列化
        private transient String id;  
    
    

    7.配置文件:Properties类

    这个类是集合体系下的类(uitl),基础map类。

    7.1写文件

    • 写的时候要注意,api推荐使用 setProperty 方法而不是Properties类继承map的put方法,因为前者有类型检查,强制使用String类安全
    • 传入store方法的stream要注意,默认Java使用ISO 8859-1,不支持中文,所以要用字符流来写而不是字节流

    7.2读文件

    Properties类继承于map,所以用迭代器可遍历

    7.3修改文件

    修改Properties类对象后,要写入文件才能生效!

    Demo:

    package per.liyue.code.properities;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Map.Entry;
    import java.util.Properties;
    import java.util.Set;
    public class ProperitiesMain {
        public static void main(String[] args) throws IOException{
            Properties p = new Properties();
            
            WriteProperties(p);
            
            ReadProperties(p);
            
            UpdateProperties(p);
            
        }
        public static void UpdateProperties(Properties p) throws IOException {
            p.setProperty("张三", "000");
            //必须要写进去才生效,但是会覆盖原来的
            p.store(new FileWriter(new File("D:\a.properties")), "这是一个属性文件例子");
        }
        public static void ReadProperties(Properties p) throws IOException, FileNotFoundException {
            p.load(new FileReader(new File("D:\a.properties")));
            //注意,这里必须写明是Object类
            Set<Entry<Object, Object>> entrys = p.entrySet();
            for (Entry<Object, Object> entry : entrys) {
                System.out.println("键:" + entry.getKey() + "值:" + entry.getValue());
            }
        }
        public static void WriteProperties(Properties p) throws IOException {
            p.setProperty("张三", "123");
            p.setProperty("李四", "456");
            p.setProperty("王五", "789");
            p.store(new FileWriter(new File("D:\a.properties")), "这是一个属性文件例子");
        }
    }
    

    8.打印流

    可以对System.out.println重新定位输出对象到文件

    System.setOut(new PrintStream(new File("D:\errorlog.txt")));
    System.out.println("输出到文件");  
    
    

    异常的情况也是一样

    try {
         //...
    } catch (Exception e) {
         //追加模式,否则会每次覆盖原来的日志
              PrintStream error = new PrintStream(new FileOutputStream("D:\errorlog.txt"), true);
         e.printStackTrace(error);  }  
    
    

    9.转换流

    InputStreamReader和OutputStreamReader是字符流FileReader和FileWriter的父类。用于字节流和字符流的转换。在网络编程中用的比较多。

    • InputStreamReader:字节流->字符流
    • OutputStreamWriter:字符流->字节流
  • 相关阅读:
    产品经理必备工具之一:Axure产品原型设计
    解决UserDefault读取慢的问题
    MAC常用快捷键
    asi网络请求中遇到的一些问题的解决
    oc运行时runtime
    图片拉伸,气泡式
    ios nil、NULL和NSNull 的使用
    错误:linker command failed with exit code 1 (use v to see invocation)
    ios url 编码和解码
    SQL重置数据表id
  • 原文地址:https://www.cnblogs.com/bugstar/p/8492840.html
Copyright © 2011-2022 走看看