zoukankan      html  css  js  c++  java
  • java基础之流的事例

    2.JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)

    1、Java断点续传原理

    =====

    实战演练

    • FileInputStream类的使用:读取文件内容
    public class A1 {
    
        public static void main(String[] args) {
            A1 a1 = new A1();
            //电脑d盘中的abc.txt 文档
            String filePath = "D:/abc.txt" ;
            String reslut = a1.readFile( filePath ) ;
            System.out.println( reslut ); 
        }
    
        /**
         * 读取指定文件的内容
         * @param filePath : 文件的路径
         * @return  返回的结果
         */
        public String readFile( String filePath ){
            FileInputStream fis=null;
            String result = "" ;
            try {
                // 根据path路径实例化一个输入流的对象
                fis  = new FileInputStream( filePath );
    
                //2. 返回这个输入流中可以被读的剩下的bytes字节的估计值;
                int size =  fis.available() ;
                //3. 根据输入流中的字节数创建byte数组;
                byte[] array = new byte[size];
                //4.把数据读取到数组中;
                fis.read( array ) ; 
    
                //5.根据获取到的Byte数组新建一个字符串,然后输出;
                result = new String(array); 
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }finally{
                if ( fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            return result ;
        }
    
    }
    
    • FileOutputStream 类的使用:将内容写入文件
    public class A2 {
    
        public static void main(String[] args) {
            A2 a2 = new A2();
            //电脑d盘中的abc.txt 文档
            String filePath = "D:/abc.txt" ;
            //要写入的内容
            String content = "今天是2017/1/9,天气很好" ;
            a2.writeFile( filePath , content  ) ;
        }
    
        /**
         * 根据文件路径创建输出流
         * @param filePath : 文件的路径
         * @param content : 需要写入的内容
         */
        public void writeFile( String filePath , String content ){
            FileOutputStream fos = null ;
            try {
                //1、根据文件路径创建输出流
                fos  = new FileOutputStream( filePath );
    
                //2、把string转换为byte数组;
                byte[] array = content.getBytes() ;
                //3、把byte数组输出;
                fos.write( array );
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }finally{
                if ( fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
    
    

    注意:

    1. 在实际的项目中,所有的IO操作都应该放到子线程中操作,避免堵住主线程。
    2. FileInputStream在读取文件内容的时候,我们传入文件的路径("D:/abc.txt"), 如果这个路径下的文件不存在,那么在执行readFile()方法时会报FileNotFoundException异常。
    3. FileOutputStream在写入文件的时候,我们传入文件的路径("D:/abc.txt"), 如果这个路径下的文件不存在,那么在执行writeFile()方法时, 会默认给我们创建一个新的文件。还有重要的一点,不会报异常。

    效果图:

     
    这里写图片描述
    • 综合练习,实现复制文件,从D盘复制到E盘
    public class A3 {
    
        public static void main(String[] args) {
            A3 a2 = new A3();
    
            //电脑d盘中的cat.png 图片的路径
            String filePath1 = "D:/cat.png" ;
    
            //电脑e盘中的cat.png 图片的路径
            String filePath2 = "E:/cat.png" ;
    
            //复制文件
            a2.copyFile( filePath1 , filePath2 );
    
        }
    
        /**
         * 文件复制 
         * @param filePath_old : 需要复制文件的路径
         * @param filePath_new : 复制文件存放的路径
         */
        public void copyFile( String filePath_old  , String filePath_new){
            FileInputStream fis=null ;
            FileOutputStream fout = null ;
            try {
                // 根据path路径实例化一个输入流的对象
                fis  = new FileInputStream( filePath_old );
    
                //2. 返回这个输入流中可以被读的剩下的bytes字节的估计值;
                int size =  fis.available() ;
                //3. 根据输入流中的字节数创建byte数组;
                byte[] array = new byte[size];
                //4.把数据读取到数组中;
                fis.read( array ) ; 
    
                //5、根据文件路径创建输出流
                fout = new FileOutputStream( filePath_new ) ;
    
                //5、把byte数组输出;
                fout.write( array );
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }catch (IOException e) {
                e.printStackTrace();
            }finally{
                if ( fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if ( fout != null ) {
                    try {
                        fout.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }   
                }
            }
        }
    }
     

    2.JAVA 遍历文件夹下的所有文件(递归调用和非递归调用)

    1.不使用递归的方法调用.

    public void traverseFolder1(String path) {
            int fileNum = 0, folderNum = 0;
            File file = new File(path);
            if (file.exists()) {
                LinkedList<File> list = new LinkedList<File>();
                File[] files = file.listFiles();
                for (File file2 : files) {
                    if (file2.isDirectory()) {
                        System.out.println("文件夹:" + file2.getAbsolutePath());
                        list.add(file2);
                        foldeNum++;
                    } else {
                        System.out.println("文件:" + file2.getAbsolutePath());
                        fileNum++;
                    }
                }
                File temp_file;
                while (!list.isEmpty()) {
                    temp_file = list.removeFirst();
                    files = temp_file.listFiles();
                    for (File file2 : files) {
                        if (file2.isDirectory()) {
                            System.out.println("文件夹:" + file2.getAbsolutePath());
                            list.add(file2);
                            folderNum++;
                        } else {
                            System.out.println("文件:" + file2.getAbsolutePath());
                            fileNum++;
                        }
                    }
                }
            } else {
                System.out.println("文件不存在!");
            }
            System.out.println("文件夹共有:" + folderNum + ",文件共有:" + fileNum);
    
        }

    2.使用递归的方法调用.

    public void traverseFolder2(String path) {
    
            File file = new File(path);
            if (file.exists()) {
                File[] files = file.listFiles();
                if (null == files || files.length == 0) {
                    System.out.println("文件夹是空的!");
                    return;
                } else {
                    for (File file2 : files) {
                        if (file2.isDirectory()) {
                            System.out.println("文件夹:" + file2.getAbsolutePath());
                            traverseFolder2(file2.getAbsolutePath());
                        } else {
                            System.out.println("文件:" + file2.getAbsolutePath());
                        }
                    }
                }
            } else {
                System.out.println("文件不存在!");
            }
        }
    public static List<File> getFileList(String strPath) {
            File dir = new File(strPath);
            File[] files = dir.listFiles(); // 该文件目录下文件全部放入数组
            if (files != null) {
                for (int i = 0; i < files.length; i++) {
                    String fileName = files[i].getName();
                    if (files[i].isDirectory()) { // 判断是文件还是文件夹
                        getFileList(files[i].getAbsolutePath()); // 获取文件绝对路径
                    } else if (fileName.endsWith("avi")) { // 判断文件名是否以.avi结尾
                        String strFileName = files[i].getAbsolutePath();
                        System.out.println("---" + strFileName);
                        filelist.add(files[i]);
                    } else {
                        continue;
                    }
                }
    
            }
            return filelist;
        }

     2、Java断点续传原理

     为什么要使用断点续传

    在进行数据上传的时候可能是多线程操作,很多图像数据同时做上传或者单一的图像,如果图像比较多或者单一图像数据比较大,自然不希望失败一次或者暂停一次之后完全重传,有断点续传功能可以节省网络流量和节省用户时间,体验自然比你一次次的重传好很多。

     Java断点续传原理

    3.1什么是断点续传

    所谓断点续传,也就是要从文件已经下载的地方开始继续下载。在以前版本的 HTTP 协议是不支持断点的,HTTP/1.1 开始就支持了。

    一般断点下载时才用到 Range (请求报文)和 Content-Range(响应报文) 实体头。下面会介绍HTTP版本的发展历程。

    3.2什么是Range? 

    模拟http请求

    当用户在听一首歌的时候,如果听到一半(网络下载了一半),网络断掉了,用户需要继续听的时候,文件服务器不支持断点的话,则用户需要重新下载这个文件。而Range支持的话,客户端应该记录了之前已经读取的文件范围,网络恢复之后,则向服务器发送读取剩余Range的请求,服务端只需要发送客户端请求的那部分内容,而不用整个文件发送回客户端,以此节省网络带宽。

    3.3HTTP1.1规范的Range是怎样一个约定?

    如果Server支持Range,首先就要告诉客户端,咱支持Range,之后客户端才可能发起带Range的请求。这里套用唐僧的一句话,你不说我怎么知道呢。response.setHeader('Accept-Ranges', 'bytes');

    Server通过请求头中的Range: bytes=0-xxx来判断是否是做Range请求,如果这个值存在而且有效,则只发回请求的那部分文件内容,响应的状态码变成206,表示Partial Content,并设置Content-Range。如果无效,则返回416状态码,表明Request Range Not Satisfiable。如果不包含Range的请求头,则继续通过常规的方式响应。

    3.4应用场景

    假设你要开发一个多线程下载工具,你会自然的想到把文件分割成多个部分,比如4个部分,然后创建4个线程,每个线程负责下载一个部分,如果文件大小为403个byte,那么你的分割方式可以为:0-99 (前100个字节),100-199(第二个100字节),200-299(第三个100字节),300-402(最后103个字节)。

    分割完成,每个线程都明白自己的任务,比如线程3的任务是负责下载200-299这部分文件,现在的问题是:线程3发送一个什么样的请求报文,才能够保证只请求文件的200-299字节,而不会干扰其他线程的任务。这时,我们可以使用HTTP1.1的Range头。

    Range头域可以请求实体的一个或者多个子范围,Range的值为0表示第一个字节,也就是Range计算字节数是从0开始的:

    表示头500个字节:Range: bytes=0-499
    表示第二个500字节:Range: bytes=500-999 
    表示最后500个字节:Range: bytes=-500 
    表示500字节以后的范围:Range: bytes=500- 
    第一个和最后一个字节:Range: bytes=0-0,-1
    同时指定几个范围:Range: bytes=500-600,601-999  
    

    所以,线程3发送的请求报文必须有这一行:

    Range: bytes=200-299
    

    服务器接收到线程3的请求报文,发现这是一个带有Range头的GET请求,如果一切正常,服务器的响应报文会有下面这行:
    HTTP/1.1 206 OK

    表示处理请求成功,响应报文还有这一行
    Content-Range: bytes 200-299/403
    斜杠后面的403表示文件的大小

    3.5Http协议的发展历程

    HTTP协议到现在为止总共经历了3个版本的演化,第一个HTTP协议诞生于1989年3月。

    xml属性描述
    HTTP/0.9 1991年
    HTTP/1.0 1992-1996年
    HTTP/1.1 1997-1999年
    HTTP/2.0 2012-2014年

    也就是HTTP/1.1 从1997-1999 年就应用了,所以现在基本上是支持断点续传的。  

  • 相关阅读:
    Java实现 蓝桥杯VIP 基础练习 完美的代价
    Java实现 蓝桥杯VIP基础练习 矩形面积交
    Java实现 蓝桥杯VIP 基础练习 完美的代价
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    Java实现 蓝桥杯 蓝桥杯VIP 基础练习 数的读法
    核心思想:想清楚自己创业的目的(如果你没有自信提供一种更好的产品或服务,那就别做了,比如IM 电商 搜索)
    在Linux中如何利用backtrace信息解决问题
  • 原文地址:https://www.cnblogs.com/awkflf11/p/12578242.html
Copyright © 2011-2022 走看看