zoukankan      html  css  js  c++  java
  • 6、I/O

    主要是解决设备与设备之间的数据传输问题 (内存 <----> 硬盘)
    应用场景:导出报表、上传数据、下载、解释XML文件
    数据一般以文件形式保存在硬盘上,使用了一个File类用于描述文件或者文件夹的(文件和目录路径名的抽象表示形式),读取文件或者文件夹的属性数据
    要读到文件中的内容数据,需要用到流技术
     

    一、File

    1、File类的构造方法:

    File(File parent, String child);  // 根据父抽象路径和子路径创建文件对象
    File(String pathname);  // 指定文件路径创建文件对象 File file = new File("E:\1.txt"); 并不是创建文件
    File(String parent, String child) // 两部分构建

    目录分隔符:Windows“”(都可以使用,/只需要写一个),Linux是“/”,可以通过separator获取

    绝对路径和相对路径
    绝对:完整路径
    相对:资源文件相对于当前程序所在的路径
     
    .代表当前路径
    ..上一级路径
    注意:程序当前所在的路径与资源文件不是在一个盘下,不能写当前路径
     

    2、常用方法:

    1、创建

    (1)指定位置创建一个空文件,成功就返回true,存在就不创建返回false(要抛出IOExecption异常)
    createNewFile();

    (2)创建文件夹,只会创建最后一级文件夹,上级目录不存在就抛出异常

    mkdir();

    (3)创建多级文件夹,创建所有不存在的目录

    mkdirs();

    (4)目标文件与源文件是在同一目录下,就是重命名(文件和文件夹都行);不在则是剪切,而且不能操作文件夹

    renameTo(File dest);

    2、删除

    (1)删除文件或文件夹

    delete();

    (2)JVM退出的时候删除文件,一般用于删除临时文件

    deleteOnExit();

    3、判断

    (1)

    exists();

    (2)

    isFile();

    (3)

    isDirectory();

    (4)是否是隐藏文件或者隐藏目录

    isHidden();

    (5)

    isAbsolute();

    4、获取

    (1)获取文件或文件夹名,不含上级路径

    getName();

    (2)返回绝对路径,也可以是相对路径,但是目录要指定

    getPath();

    (3)获取绝对路径,与文件存在没有关系

    getAbsolutePath();

    (4)获取文件大小,字节数

    length();

    (5)获取文件的父路径

    getParent();

    (6)最后一次修改时间

    lastModified();

    5、文件夹相关

    (1)列出所有的根目录

    listRoots();

    (2)把当前文件夹下面的所有子文件名与子文件夹名(不包括孙)存储到一个String数组中返回

    list();

    (3)把当前文件夹下的所有子文件和子文件夹都使用一个File对象描述,然后把File对象存储到File数组中

    listFiles();

    (4)

    list(FilenameFilter filter);

    (5)自定义文件名过滤器

    listFiles(FilenameFilter filter);

    输入输出划分:

    --------输入流:相对本程序
    --------输出流
     
    处理单位划分:
    --------字节流:读取文件中二进制数据,不会结果任何处理(FileInputStream )
    --------字符流:以字符为单位,读取文件中二进制数据,将其转换为我们能识别的字符,字符流 = 字节流+解码,(FileReader )
     

    二、字节流

    1、输入字节流:

    ---------------| InputStream 所有输入字节流的基类
    --------------------| FileInputStream:读取文件数据的输入字节流
     
    FileInputStream读取文件的步骤
    1、找到目标文件
    2、建立数据的输入通道(管道)
    3、建立缓冲数组,读取文件数据
    4、关闭资源(释放资源)

    注意:用缓冲数组读取效率更高

    要是缓冲数组只有4时,每次读完数据第二次是覆盖到前面的数组

    2、输出字节流

    -----------| OutputStream 所有输出字节流的基类
    ---------------| FileInputStream 向文件输出数据的字节流

     

    1、使用FileInputStream的时候,如果目标文件不存在,会自动创建目标文件对象
    2、写数据的时候,目标文件存在会先清空目标文件的数据,再写入数据
    3、已经存在,需要在原来的后面追加数据,应该使用FileOutputStream(file, true);
    4、write方法写数据的时候,虽然接收的是int型的数据,但是真正写出的只是一个字节(8位)的数据,把低八位二级制数据写出,其他二十四位数据全部丢弃

    输出[-1, 0, 0, 0];255(11111111)以补码形式存在

    拷贝图片

    注意:每新创建一个FileOutputStream的时候,默认情况下FileOutputStream的指针指向文件开始位置,每写出一次指向都会相应移动(写的时候加不加true问题)

    3、异常处理 

     

    将IOException传递给RuntimeException包装一层,然后再抛出,让调用者使用更加灵活,可以处理也可以不处理
    将异常throw的时候,阻止后面代码执行(要是return的话,能阻止代码执行,但是不会通知外界出了问题)

     

    4、缓冲输入字节流BufferedInputStream(其实跟自定义内存数组byte[] buf的原理一样,不常用

    代替自定义的缓冲数组buf
    -------------| InputStream
    ---------------------| FileInputStream
    ---------------------| BufferedInputStream 缓冲输入字节流,提高读取文件数据效率,内部维护了一个8K 的字节数组,效果和自定义缓冲数组一样
     
    使用步骤
    1、找到目标文件
    2、建立数据输入通道
    3、建立缓冲输入字节流
    4、关闭资源
     
    缓冲流都不具备读写的能力,BufferedInputStream借助FileInputStream实现读写; 调用BufferedInputStream的close方法实际关闭FileInputStream
     
    BufferedInputStream读取效率高的原因:每次从内存中BufferedInputStream维护的数组读取8K的数据(FileInputStream 则是从硬盘中读取)

     

    5、缓冲输出字节流BufferedOutputStream

    内部维护了一个8K的缓冲字节数组
    注意:
    1、写数据时,write是写到在内部维护的字节数组中
    2、要想写到硬盘中,需要调用flush或者close方法或者内部字节数组已经填满的时候
     
    用缓冲输入输出流拷贝图片

    bufferedInputStream.read()方法中,要是传入了buf缓冲数组返回值是存储到缓冲数组字节个数;要是没有传入,则返回的是读取到的内容

     三、字符流

    字符流 = 字节流+解码(字节流读取文件中二进制数据,一次读取一个字节),可以读取中英文,一次读取一个字符
     

    输入字符流(默认使用GBK编码表)

    ---------------| Reader 输入字符流的基类
    ---------------------| FileReader 读取文件的输入字符流,每次读一个字符(char),不论中英文都可以读(byte字节,char字符)

     

    1、FileWriter输出字符流

    写数据的时候,FileWriter内部维护了1024字节的数组,写数据的时候会先写到数组中,要写到硬盘上时,需要调用flush或者是close方法或者是填满内部字符数组

     

    使用字符流拷贝图片时,会造成图片变小且打不开
    FileReader默认使用GBK编码表,每次读取数据时会在码表里面找,找得到就存储中文两位(将二进制数据转换为字符),找不到就返回一个未知字符对应的数字,未知字符占一个字节,导致有些数据丢失
     
    字符流的应用场景
    如果是读写字符数据的时候就是用字符流(看得到的1、我......)
     
    字节流的应用场景
    读写的数据不需要转换为字符的时候使用
    用字节流配合缓冲数组读取字符的时候,要是缓冲数组比较小(byte[4]),而字符为中英文混合(我de妈呀),会造成读取乱码;用字符流就每次读取一个字符,不会出错
     

    2、缓冲输入字符流(常用,比缓冲数组好,常用)BufferedReader 

    ----------------| Reader 所有输入字符流的基类,抽象
    ----------------------| FileReader 输入字符流
    ----------------------| BufferedReader 字符缓冲输入流,提高文件读取效率和扩展了FileReader的功能,其内部维护了一个4K的数组(缓冲流都不具备读写文件的能力,每次读取的是一个字符)
     
    readline()方法可以读取一行,文件末尾返回null,读取的一行不包含/r/n(以/r/n 为结束符)
     1 public static void testRead() throws IOException {
     2     // 找到目标文件
     3     File file = new File("E:\eclipseProject\Demo4\src\cn\guojie\file\Demo7.java");
     4     // 建立数据传输通道
     5     FileReader fileReader = new FileReader(file);
     6     // 建立缓冲输入字符流
     7     BufferedReader reader = new BufferedReader(fileReader);
     8     // 读取数据
     9     String line = null;
    10     while((line = reader.readLine())!=null) {
    11         System.out.println(line);
    12     }
    13     // 关闭资源
    14     reader.close();
    15 }
     1 // 自定义readLine方法,读一行
     2 public static String myReadLine(FileReader fileReader) throws IOException {
     3     StringBuilder sb = new StringBuilder();
     4     int content = 0;
     5     while((content = fileReader.read())!=-1) { // 每次读一个字符,存在int中
     6         if(content =='
    ') {  // 
    回车忽略
     7             continue;
     8         } else if(content =='
    ') {  // 
    跳出循环
     9             break;
    10         } else {
    11             sb.append((char)content);  // 整型强转为char
    12         }
    13     }
    14     
    15     if(content==-1) { // 代表读完了
    16         return null;  
    17     }
    18     
    19     return sb.toString();  // StringBuilder转化为String
    20 }
    21 
    22 public static void testReader1() throws IOException {
    23     // 找到目标文件
    24     File file = new File("E:\eclipseProject\Demo4\src\cn\guojie\file\Demo7.java");
    25     // 建立数据传输通道
    26     FileReader fileReader = new FileReader(file);
    27     // 读取数据
    28     String line = null;
    29 //        !(line = myReadLine(fileReader)).equals("")  // 用StringBuilder最少会返回空串""
    30     while((line = myReadLine(fileReader))!=null) {
    31         System.out.println(line);
    32     }
    33     // 关闭通道
    34     fileReader.close();
    35 }

    3、缓冲输出字符流(提高FileWriter的读写效率和扩展功能)(常用) BufferedWriter

    ----------------| Writer 所有输入字符流的基类,抽象
    ----------------------| FileWriter 输入字符流
    ----------------------| BufferedWriter:内部提供了8K的字符数组作为缓冲区
    提供了newLine()方法,换行
     1 boolean isLogin = false;  // 判断是否登录成功标识
     2 while((line = bufferReader.readLine())!=null) {
     3     if(info.equals(line)) {  // 读一行,如果第一行不行接着往下读,如果用if else判断的成功话,会造成
     4                             // 读完一行之后不对会直接判断登录失败,应该用一个isLogin的变量判断是否登录成功
     5         isLogin = true;
     6         break;
     7     }
     8 }
     9 
    10 if(isLogin) {  // 此时通过标识判断是否登录成功
    11     System.out.println("恭喜,登陆成功!");
    12 } else {
    13     System.out.println("对不起,登录失败,请重新输入");
    14 }

    四、装饰者设计模式

    增强一个类的功能,还可以让这些类互相装饰
    通过继承增强一个类的功能:
    优点:代码结构清晰易懂
    缺点:使用不灵活,会导致继承的体系过于庞大
     
    步骤:
    1、在装饰类内部维护一个被装饰类的引用
    2、让装饰类有共同的父类或者父接口
     
    父类有无参的构造方法时默认调用,要是没有无参的构造方法则需要指定有参构造方法
    修饰模式实战增强类:
         优点:内部可以通过多态对多个需要增强的类进行增强,让这些修饰类达到互相装饰的效果,使用灵活
         缺点:需要内部通过多态维护需要被增强类的实力,使代码复杂
     1 // 加;缓冲输入字符流
     2 class BufferedSepetrator extends BufferedReader { // 继承是为了让装饰类对象可以作为参数传递,达到互相装饰的效果
     3     // 在内部维护维护一个被装饰类的引用
     4     BufferedReader bufferedReader;
     5     
     6     public BufferedSepetrator(BufferedReader bufferedReader) { // new BufferdLineNum()
     7         super(bufferedReader);
     8         this.bufferedReader = bufferedReader;
     9     }
    10     
    11     public String readerLine() throws IOException {
    12         String line = bufferedReader.readLine();  // 传入bufferedLineNum,使bufferedReader指
    13                                                   // 向子类BufferdLineNum,调用子类的readLine方法
    14         if(line == null) {
    15             return null;
    16         }
    17         line = line+";";
    18         
    19         return line;
    20     }
    21 }
     1 public class Demo {
     2     
     3     public static void main(String[] args) throws IOException {
     4         File file = new File("E:\eclipseProject\Demo4\src\cn\guojie\file\Demo7.java");
     5         FileReader fileReader = new FileReader(file);
     6         BufferedReader bufferedReader = new BufferedReader(fileReader);
     7         // 建立带行号的缓冲输入字符流
     8         BufferdLineNum bufferedLineNum = new BufferdLineNum(bufferedReader);
     9         // 建立带分号的缓冲输入字符流,传入bufferedLineNum,使父类引用类型指向子类对象从而调用子类的方法
    10         BufferedSepetrator bufferedSeperator = new BufferedSepetrator(bufferedLineNum);
    11         // 读缓冲流
    12         String line = null;
    13         while((line = bufferedSeperator.readerLine())!=null) {
    14             System.out.println(line);
    15         }
    16         // 关闭资源
    17         bufferedSeperator.close();
    18     }
    19 
    20 }

    五、序列流 SequenceInputStream

    合并两个或多个流

    常用方法

    (1)合并两个输入流

    SequenceInputStream(InputStream s1, InputStream s2);

    (2)合并多个输入流,借助vector的element方法获得Enumation枚举对象传入

    SequenceInputStream(Enumeration<? extends InputStream> e);
     1 public static void merge1() throws IOException {
     2     // 找到目标文件
     3     File file1 = new File("E:\a.txt");
     4     File file2 = new File("E:\b.txt");
     5     File file3 = new File("E:\c.txt");
     6     // 建立输入输出字节流
     7     FileInputStream fileInputStream1 = new FileInputStream(file1);
     8     FileInputStream fileInputStream2 = new FileInputStream(file2);
     9     FileOutputStream fileOutputStream = new FileOutputStream(file3);
    10     // 创建序列化流
    11     SequenceInputStream sequenceInputStream = new SequenceInputStream(fileInputStream1, fileInputStream2);
    12     // 读写数据
    13     byte[] buf = new byte[1024];
    14     int length = 0;
    15     while((length = sequenceInputStream.read(buf))!=-1) {
    16         fileOutputStream.write(buf, 0, length);
    17     }
    18     // 关闭资源
    19     sequenceInputStream.close(); // 调用FileInputStreamdeclose()
    20     fileInputStream2.close();
    21     fileOutputStream.close();
    22 }
     1 public static void merge2() throws IOException {
     2     // 找到目标文件
     3     File file1 = new File("E:\a.txt");
     4     File file2 = new File("E:\b.txt");
     5     File file3 = new File("E:\c.txt");
     6     File file4 = new File("E:\d.txt");
     7     // 建立输入输出字节流
     8     FileInputStream fileInputStream1 = new FileInputStream(file1);
     9     FileInputStream fileInputStream2 = new FileInputStream(file2);
    10     FileInputStream fileInputStream3 = new FileInputStream(file3);
    11     FileOutputStream fileOutputStream = new FileOutputStream(file4);
    12     // 创建序列化流
    13     Vector<FileInputStream> vector = new Vector<FileInputStream>();
    14     vector.add(fileInputStream1);
    15     vector.add(fileInputStream2);
    16     vector.add(fileInputStream3);
    17     // 通过Vector获取迭代器
    18     Enumeration<FileInputStream> e = vector.elements();
    19     
    20     SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
    21     byte[] buf = new byte[1024];
    22     int length = -1;
    23     while((length = sequenceInputStream.read(buf))!=-1) {
    24         fileOutputStream.write(buf, 0, length);
    25     }
    26     //关闭资源
    27     sequenceInputStream.close();
    28     fileOutputStream.close();
    29 }

    切割和合并mp3

    // 切割mp3
    public static void cutFile() throws IOException {
        // 找到目标文件
        File file = new File("D:\CloudMusic\走在冷风中.mp3");
        // 建立目标文件夹
        File dir = new File("E:\cutMusic");
        // 建立输入输出流
        FileInputStream fileInputStream = new FileInputStream(file);
        // 读写文件,以1M为单位切割
        byte[] buf = new byte[1024 * 1024];
        int length = 0;
    
        for (int i = 0; (length = fileInputStream.read(buf)) != -1; i++) {
            int num = i + 1;
            FileOutputStream fileOutputStream = new FileOutputStream(new File(dir, "part" + num + ".mp3"));
            fileOutputStream.write(buf, 0, length);
            // 关闭缓冲输出流
            fileOutputStream.close();
        }
        // 关闭资源
        fileInputStream.close();
    }
    
    // 合并mp3
    public static void merge() throws IOException {
        // 找到目标文件
        File dir = new File("E:\cutMusic");
        // 通过目标文件夹找到所有的mp3文件,然后把所有的mp3文件添加到Vector
        Vector<FileInputStream> vector = new Vector<FileInputStream>();
        File[] files = dir.listFiles(); // 列出目标文件夹中所有的目标文件
        
        for (File file : files) {
            if (file.getName().endsWith(".mp3")) { // 文件以.mp3结尾
                vector.add(new FileInputStream(file)); // vector中需要传入FileInputStream
            }
        }
        // 通过Vector获取迭代器
        Enumeration<FileInputStream> e = vector.elements();
        // 创建序列流
        SequenceInputStream sequenceInputStream = new SequenceInputStream(e);
        // 创建文件输出字节流
        FileOutputStream fileOutputStream = new FileOutputStream("F:\合并.mp3");
        // 创建缓冲数组读写文件
        byte[] buf = new byte[1024];
        int length = 0;
        while ((length = sequenceInputStream.read(buf)) != -1) {
            fileOutputStream.write(buf, 0, length);
        }
        // 关闭资源
        fileOutputStream.close();
        sequenceInputStream.close();
    }

     六、序列化

    对象的输入输出流:用于写对象的信息和读对象的信息,对象的信息一旦写到文件就实现了对象的持久化
    序列化:把对象信息写入到硬盘(ObjectOutputStream)
    反序列化:把文件中的对象信息读取出来(ObjectInputStream)
     

    注意细节:

    1、对象需要写出到文件上,那么对象所属的类必须实现Serializable接口(没有任何方法,只是一个标志接口),不实现的话会报错java.io.NotSerializableException
    2、对象的反序列化创建对象时,并不会调用到构造方法 
    3、serialVersionUID用于记录class文件的版本信息,serialVersionUID通过一个类名、成员、包名、工程名计算出的
    4、使用ObjectInputStream反序列化时,ObjectInputStream先读取文件中的serialVersionUID,然后与本地的class文件中对比,相同则成功,不同则失败
    5、序列化和反序列化的时候可能会修改类的成员,最好一开始就给该类指定serialVersionUID,后面序列化和反序列化的时候jvm都不会再算这个class的serialVersionUID
    6、如果一个对象的某项数据不想写到硬盘上,用transient修饰
    7、如果一个类维护了另外一个类的引用,那么另外一个类也需要实现Serialable接口
     
     1 // 序列化
     2 public static void writeObj() throws IOException {
     3     // 把User对象信息持久化存储
     4     User user = new User("xiaoming", "123456");
     5     // 找到目标文件
     6     File file = new File("E:\Obj.txt");
     7     // 建立输出流对象
     8     FileOutputStream fileOutputStream = new FileOutputStream(file); 
     9     // 建立对象的输出流对象
    10     ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
    11     // 写出对象
    12     objectOutputStream.writeObject(user);
    13     // 关闭资源
    14     objectOutputStream.close();
    15     
    16 }
     1 // 反序列化
     2 public static void readObj() throws IOException, ClassNotFoundException {
     3     // 找到目标文件
     4     File file = new File("E:\Obj.txt");
     5     // 建立输入流对象
     6     FileInputStream fileInputStream = new FileInputStream(file);
     7     // 建立对象的输入流对象
     8     ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
     9     // 读取文件信息
    10     User readObject = (User) inputStream.readObject(); // 强转时可能产生ClassNotFoundException
    11     System.out.println(readObject);
    12     // 关闭文件
    13     inputStream.close();
    14 }

    七、配置文件类Properties(常用)

    用于生成和读取配置文件的信息,属于Java.util的集合体系Map的类---> Hashtable

    常用方法:

    (1)添加Properties项,不用put(配置文件的键值都要求是字符串,put却可以任意添加类型数据)

    setProperty(String key, String value);

    (2)产生配置文件

    store(Writer writer, String comments);

    (3)加载配置文件

    load(Reader reader);
     
    注意细节:
    1、配置文件信息使用中文,那么在使用store方法生成配置文件的时候只能使用字符流解决(要是使用字节流默认使用IOS_8859-1码表,出现乱码)
    2、Properties中的内容发生了变化,一定要重新存储配置文件
     1 // 保存配置文件的信息
     2 public static void saveProperties() throws IOException {
     3     // 创建Properties对象
     4     Properties properties = new Properties();
     5     // 添加,不用put
     6     properties.setProperty("张三", "123");
     7     properties.setProperty("李四", "456");
     8     properties.setProperty("王五", "789");
     9     // 遍历Properties
    10     Set<Entry<Object,Object>> entrys = properties.entrySet();
    11     for(Entry<Object,Object> entry : entrys) {
    12         System.out.println("键:"+entry.getKey()+"值:"+entry);
    13     }
    14     // 使用Properties产生配置文件,字符传FileWriter,字节传FileInputStream
    15     properties.store(new FileWriter("E:\a.properties"), "nihao");  // comments
    16 }
     1 // 读取配置文件
     2 public static void readProperties() throws IOException {
     3     // 创建Properties对象
     4     Properties properties = new Properties();
     5     // 加载配置文件
     6     properties.load(new FileReader("E:\a.properties"));
     7     // 遍历Properties
     8     Set<Entry<Object,Object>> entrys = properties.entrySet();
     9     for(Entry<Object,Object> entry : entrys) {
    10         System.out.println("键:"+entry.getKey()+"值:"+entry);
    11     }
    12     // 修改
    13     properties.setProperty("张三", "aaa");
    14     // 修改完成后再保存配置文件
    15     properties.store(new FileWriter("E:\b.properties"), "修改之后");
    16 }
     1 // 软件运行次数配置文件
     2 public static void count() throws IOException {
     3     // 找到目标文件
     4     File file = new File("E:\c.properties");
     5     if(!file.exists()) {  // 目标文件不存在就创建
     6         file.createNewFile();
     7     }
     8     
     9     // 创建Properties对象
    10     Properties properties = new Properties();
    11     // 加载配置文件到Properties中
    12     properties.load(new FileReader(file));
    13     
    14     int count = 0;  // 计数
    15     String value = properties.getProperty("count");  // 从properties取出count
    16     if(value!=null) {
    17         count = Integer.parseInt(value);  // String转换为整数
    18     }
    19     // 超过三次退出jvm
    20     if(count==3) {
    21         System.out.println("您已使用超过试用次数,请购买软件");
    22         System.exit(0);  // 退出java虚拟机
    23     }
    24     
    25     count++;
    26     
    27     System.out.println("已使用"+count+"次");
    28     // 添加properties项
    29     properties.setProperty("count", count+"");  
    30     // 产生配资文件
    31     properties.store(new FileOutputStream(file), "运行次数");  // new FileOutputStream(file)要放到load后,不然FileOutputStream每次会清空
    32 }

     八、打印流PrintStream

    system.setOut();重新设置标准输出流对象

    作用:

    1、可以打印任意类型的数据,打印数据之前都会把数据转换成字符串
    2、收集异常日志信息
    1 Exception e;
    2 e.printStackTrace   // 打印异常信息到控制台,会丢失一部分异常信息
     1 // 收集异常日志信息
     2 public static void exceptionLog() throws IOException {
     3      // 创建打印流对象
     4     PrintStream logPrintStream = new PrintStream(new FileOutputStream(new File("E:\2015年11月29日.log")));
     5     try {
     6         int[] a = null;
     7         System.out.println(a.length);
     8         
     9         int c = 4/0;
    10         System.out.println(c);
    11         
    12     } catch (Exception e) {
    13         e.printStackTrace(logPrintStream);
    14     }
    15 }    

    九、编码和解码

    ASCII码表:一个字节7位(256)表示,26个英文字母对应各自码值,很多空出,2(8)
    ISO8859-1:填上了ASCII的空位
    GBK2312:英文1个字节,中文2字节,GBK升级版,2(16)=65536
    Unicode:国际标准码,规范,融合多种文字,2个字节
    UTF-8:世界通用,英文1个字节,中文3个字节
    UTF-16:不管中英文都是2个字节,指定的是Unicode其实是UTF-16,开始有个标志-2 -1
     
    编码和解码都使用统一的码表,英文在各个码表都一样,中文不同

    十、转换流(常用)

    输入字节转换流 InputStreamReader 
    输出字节转换流OutputStreamWriter

    作用:

    1、如果目前所获取到的是字节流,需要转换成字符流使用,就可以使用转换流(字节流 ---> 字符流),不能反过来(可以使用BufferedReader缓冲输入字符流的readline()方法)
    2、使用转换流可以指定编码表进行读写文件
    1 // 使用输出字节转换流指定码表写数据
    2 public static void writeTest() throws IOException {
    3     // 把输出字节流转换成字符流并指定码表(读写的码表要一样)
    4     OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File("E:\abc.txt")), "utf-8");
    5     // 使用输出字节转换流写数据
    6     outputStreamWriter.write("你好");
    7     //关闭资源
    8     outputStreamWriter.close();
    9 }
     1 // 使用输入字节转换流指定码表读数据
     2 public static void readTest() throws IOException {
     3     // 把输入字节流转换成字符流并指定码表(读写的码表要一样)
     4     InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(new File("E:\abc.txt")), "utf-8");
     5     // 使用输入字节转换流读数据
     6     char[] buf = new char[1024];
     7     int length = 0;
     8     while((length = inputStreamReader.read(buf))!=-1) {
     9         System.out.println(new String(buf, 0, length));
    10     }
    11     // 关闭资源
    12     inputStreamReader.close();    
    13 }

    十一、递归

    函数调用自身
    前提:必须要有条件下的调用
    先易后难
     1 // 递归文件夹的目录,列出子文件名和子文件夹名以及子文件夹下的孙文件名,先浅后深
     2 public static void listFiles(File dir, String space) {
     3     File[] files = dir.listFiles();  // 列出目录下所有文件名
     4     for(File file : files) {
     5         if(file.isFile()) {  // 文件
     6             System.out.println(space+file.getName());  // 列出文件名
     7         } else if(file.isDirectory()) {  // 目录
     8             System.out.println(space+file.getName());  // 列出目录名
     9             // 递归
    10             listFiles(file, "|  "+space);  
    11         }
    12     }
    13 }
     1 // 递归删除文件夹及其下面的文件夹和文件
     2 public static void deleteFiles(File dir) {
     3     File[] files = dir.listFiles(); // 列出目录下所有文件名
     4     for(File file : files) {
     5         if(file.isFile()) {  // 文件
     6             file.delete();  // 删除文件
     7         } else if(file.isDirectory()) {  // 文件夹
     8             deleteFiles(file);  // 文件夹
     9         }
    10     }
    11     dir.delete();  // 删除根目录
    12 }
     
    有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
  • 相关阅读:
    No bean named 'xxxxx' is defined异常,已解决,这个坑很难发现,你get了吗
    JSTL 和 EL
    SpringMVC FistMVC详解
    关于常用的编码工具如何引入jar包
    python-django rest framework框架之序列化
    blog项目知识点梳理
    python-前20天的着重知识点
    python-django rest framework框架之解析器
    python-django rest framework框架之dispatch方法源码分析
    python-django rest framework框架
  • 原文地址:https://www.cnblogs.com/1989guojie/p/6107791.html
Copyright © 2011-2022 走看看