程序员

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

2019-09-30  本文已影响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框架时就去购买收费的了。这里不是打广告,只是感谢站长让我有收获了。

上一篇下一篇

猜你喜欢

热点阅读