美文网首页程序员
新手如何学习java的IO(一)

新手如何学习java的IO(一)

作者: 老豆腐 | 来源:发表于2019-09-30 06:36 被阅读0次

    前言,对于java本人是个小白,不过有点其他语言的经验,知道java是面向对象的,也就这么多。刚开始学习java,我也是蒙头啃书,啃完《Java核心编程一卷》的前8章,看着好像都懂,但是合上书回忆自己到底学了些什么,又好像一片空白。ps:我也有过打书上的代码,但是感觉这本书还是实例太少,缺少那种可实际操作的问题吧(仅对于我,勿喷!)。于是,我就去网上查查看看别人是如何学习java的,第一站就是知乎了,翻了好几个帖子,都说这本书是基础,要细心啃,然后就是列出了一些关键点集合,泛型,IO,多线程,类加载机制,反射,代理。下一步,我就去网上找以上类似的资源了,找到一个对于我这种小白特别合适的线上资源,底下有介绍。

    读写文件

    把文件里的内容读入内存,这里有两种方法,一种是字节型的,一种是字符型的,详细如下图。另外,这是一个Java IO 的 Tutorial,虽然是英文的,但是很详细。

    image.png

    读文件

    // 创建文件对象
    File f = new File("/Users/tofu/Downloads/javatext.txt");
    // 创建文件输入流
    FileInputStream fis = new FileInputStream(f);
    // 创建byte数组
    byte[] fileContent = new byte[(int)f.length()];
    //读入文件内容到fileContent数组中
    fis.read(fileContent);
    for(byte b:fileContent){
     System.out.println(b);
    }
    //关闭输入流
    fis.close();
    

    如果指定文件存在的话,就成功把文件里的内容以byte格式读入数组。

    把内容写入指定文件

    Question:创建指定目录下的文件。(如果如果该文件的上一层目录不存在呢?,上上一层也不存在呢?)

    public void StringToFile(path){
        File f = new File(path);
        //获取该文件的父目录
        File dir = f.getParentFile();
        //System.out.println(dir);
        // 如果该父目录不存在,则创建
        if (!dir.exists()) {
            dir.mkdirs();
            System.out.println("dir is not exits");}
        try {
            // 创建文件
            if (!f.exists()) f.createNewFile(); 
            // 创建输出流
            FileOutputStream fout = new FileOutputStream(f);
            byte[] tt = {88,89,32,32,43,54,88,89};
            //写入文件
            fout.write(tt);
            // 关闭文输出流
            fout.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    

    文件夹遍历

    顾名思义,就是使用java查看在某个目录下存在的文件,分两种情况,即包含子文件夹的文件,和不包含子文件夹的文件。

    找出其中最大、最小文件(一)

    Attention:不包含子文件夹里的文件

    这个比较简单,主要就是知道,Java中File类里有个listFiles()函数,同时file.length()可以计算文件大小,主要代码如下:

    //创建一个File类型的数组,把该文件夹下的文件全部放入该数组中,之后遍历数组,并比较即可
    File dir = new File(path);
    File[] allFiles = dir.listFilse();
    for(File f : allFiles){
        if(f.isDirectory()) continue;
        else{
            .          
        }
    }
    

    找出其中最大、最小文件(二)

    Attention:包含子文件夹里的文件

    看似差不多的问题,其实难度还是相差很多的,因为上个问题,我们只需在指定目录下列出所有文件即可,但是这个问题不行,我们无法知道,该目录下还有多少个子目录,就像拨洋葱,一层又一层。这里,就很容易想到使用递归去解决问题了,不过本文不打算使用递归的方法,本文采用广度优先搜索的方法来解决该问题。

    广度优先搜索,简单来说就是按层级搜索,第一层遍历完了,遍历第二层。如图所示,遍历的顺序就是1>2>3>4>5>6>7>8。主要思想为:

    1. 创建两个队列,一个队列用来装所有文件计作q1,一个用来装所有目录计作q2
    2. q2每弹出一个目录,遍历其下所有文件及文件夹,把文件按顺序放入q1,目录按顺去放入q2
    3. 循环上述操作,直至q2为空,遍历结束
    4. q1里存放的即为所有文件
    5. 这里没讲文件的比较,因为比较简单,就不讲了,贴了代码。
    image
    public void getAllFiles(){
        String path = "/Users/tofu/Downloads";
        File root = new File(path);
        //存放所有的文件
        LinkedList<File> fileList = new LinkedList<File>();
        //存放所有的目录
        LinkedList<File> DirList = new LinkedList<File>();
        DirList.add(root);
        long maxLength = Long.MIN_VALUE;
        long minLength = Long.MAX_VALUE;
        //记录当前最大文件和最小文件
        File[] fillNames = new File[2];
        File queue = null;
        //判断目录是否为空
        while(DirList.size()>0){
            //弹出一个目录
            queue = DirList.remove();
            File[] filesInQueue = queue.listFiles();
            for (File f:filesInQueue){
                if(f.isFile()) {
                    fileList.add(f);
                    long tmpLength = f.length();
                    if(tmpLength>maxLength){
                        fillNames[0] = f;
                        maxLength = tmpLength;
                    }
                    if(tmpLength < minLength){
                        fillNames[1] =f;
                        minLength = tmpLength;
                    }
                }
                if(f.isDirectory()) {
                    DirList.add(f);
                    System.out.println(f + "is a Directory");
                }
            }
        }
        System.out.println("the maximum file name is" + fillNames[0]+" the size is "+maxLength);
        System.out.println("the minimum file name is" + fillNames[1]+" the size is "+minLength);
    }
        
    

    文件拆分

    Question:找到一个大于100k的文件,按照100k为单位,拆分成多个子文件,并且以编号作为文件名结束。

    public void splitFile(String toSplitFile){
        File sourceFile = new File(toSplitFile);
        byte[] fileContent = new byte[(int) sourceFile.length()];
        int fileNum = 0;
        FileInputStream fis=null;
        try(fis = new FileInputStream(sourceFile)){
            fis.read(fileContent);
        }catch(IOException e){
            e.printStackTrace();
        }
        //存储每个小文件的内容
        byte[] eachContent;
        //计算文件个数
        if(sourceFile.length()%blockSize==0){
            fileNum = fileContent.length/blockSize;
        }
        else{
            fileNum = fileContent.length/blockSize+1;
        }
        FileOutputStream fout =null;
        for(int i=0;i<fileNum;i++){
            File f = new File(sourceFile.getParent(),sourceFile.getName()+"_"+i);
            if (i!=fileNum-1){
                eachContent = Arrays.copyOfRange(fileContent,i*blockSize,(i+1)*blockSize);
            }
            else{
                eachContent = Arrays.copyOfRange(fileContent,i*blockSize,fileContent.length);
            }
            try(fout = new FileOutputStream(f)){
                fout.write(eachContent);
            }catch(IOException e){
                e.printStackTrace();
            }
            System.out.printf("the no %d is create\n",i);
        }
    }
    

    文件合并

    Question:合并上述已拆分的文件

    public void mergeFile(String floder, String name){
        File allFiles = new File(floder,name);
        try(FileOutputStream fout = new FileOutputStream(allFiles)){
            int i = 1;
            while(true){
                File f = new File(floder,name+"_"+i++);
                if(!f.exists()) break;
                byte[] each = new byte[(int)f.length()];
                try(FileInputStream fis =new FileInputStream(f)){
                    fis.read(each);
                }catch(IOException e){
                    e.printStackTrace();
                }
                fout.write(each);
            }
        }catch(IOException e){
            e.printStackTrace();
        }
        System.out.println("the file is create");
    }
    

    流的两种关闭方式

    在finally中关闭

    1. 首先把流的引用声明在try的外面,如果声明在try里面,其作用域无法抵达finally.
    2. 在finally关闭之前,要先判断该引用是否为空
    3. 关闭的时候,需要再一次进行try catch处理
        public static void main(String[] args) {
            File f = new File("/Users/tofu/Downloads/javaTest.txt");
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(f);
                byte[] all = new byte[(int) f.length()];
                fis.read(all);
                for (byte b : all) {
                    System.out.println(b);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                // 在finally 里关闭流
                if (null != fis)
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
            }
     
        }
    
    

    在try中关闭

    File f = new File("d:/lol.txt");
    //把流定义在try()里,try,catch或者finally结束的时候,会自动关闭
    try (FileInputStream fis = new FileInputStream(f)) {
        byte[] all = new byte[(int) f.length()];
        fis.read(all);
        for (byte b : all) {
            System.out.println(b);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    

    网站介绍

    我是在这个网站上学习的,感觉站长很厉害,讲的很清楚,例子也很好。网站一部分是收费的,一部分是免费的,目前我还在学习免费的,可能下次学spring框架时就去购买收费的了。这里不是打广告,只是感谢站长让我有收获了。

    相关文章

      网友评论

        本文标题:新手如何学习java的IO(一)

        本文链接:https://www.haomeiwen.com/subject/isaefctx.html