IO流的复习新知

背景

关于 IO流只是在以前上课老师说要一个序列化的任务要完成,我才去学习了一下IO流去完成任务式的学了一下,之后任务完成也就没接着学习了,这导致后来一碰到IO相关的问题都两眼一抹黑,特别是在文件上传的后台处理的那部分,完全暴露了我对IO的操作的缺陷。于是前两天我重新复习了一遍java中的IO操作。
本次复习的地址为 How2J

文件

文件的操作在java中有以下常用操作:

file.getParentFile();	//获取父文件对象
file.exsits(),	//文件存在的boolean值 ,存在为true ,反之为false。
file.mkdir();//创建文件夹,若上级路径不存在,创建就无效
file.mkdirs();//创建文件夹,若上级路径不存在,则会一并创建

file.createNewFile();	//创建文件

值得一提的是,若是在创建文件时,file的上一级目录不存在,则会抛出异常,所以在创建文件前我都会以下操作:

	File parent = file.getParentFile();
	if(parent != null && !parent.exists() ){
		parent.mkidrs();
		file.createNewFile();
	}

保证不会抛出异常。

		file.getAbsolutePath();//获取文件的绝对路径
		file.listFile();// 以 **文件数组** 的形式返回本对象(文件夹)下的所有文件的对象
		file.length();	//文件的大小	字节为单位 返回类型int
		file.isFile();	//是文件	文件返回true	文件夹返回false
		file.isDirectory();	//是文件夹的boolean	文件夹返回true	文件返回false
		file.lastModified();	//文件最后修改时间 返回类型为long。

流的基础

1 何为流:
Java中的流是个抽象的概念,当程序需要从某个数据源读入数据的时候,就会开启一个数据流,数据源可以是文件、内存或网络等等。相反地,需要写出数据到某个数据源目的地的时候,也会开启一个数据流,这个数据源目的地也可以是文件、内存或网络等等(摘自百度)
2:
流的初步分类:字节流(byte流),字符流(char流)。
流向来分类的话为:输入流 和 输出流。这里的 输入 输出 的对象为 电脑的程序,故 输入流 是 从 其余地方(如磁盘) 将数据 输入到程序 ,输出流 是将程序的 数据 输出 到 其余地方(如磁盘)

2:字节流(byte流)的初步使用
可以写以下的几道小小的demo熟练。
1:拆分文件(如将一个 图片文件 按字节数拆分为若干个子文件)。
2:合并文件, 将上面拆分的文件合并成 一个图片文件,再点击查看,观察图片文件是否被破坏。
3:将 一个 文件 copy到 另外一个文件夹(此文件夹事先不存在)中。
4:将 一个文件夹 下的所有文件 复制 到 另外一个文件夹下。
下面给出demo4的代码:

    // path 为 复制的文件 存储的路径 ,file为 要复制的文件夹 的文件对象
    public static void coptDerictory(String path,File file){
        String name = "copy-"+file.getName();
        //若 file 为文件夹
        if(file.isDirectory()){

            //获取file 下的所有 文件对象
            File[] files = file.listFiles();


            //复制的文件夹的路径 
            path += File.separator+name;

            //创建复制的文件夹
            File parentFile = new File(path);
            parentFile.mkdir();

            //递归创建文件夹下的文件
            for ( File file1 : files){
                coptDerictory(path,file1);
            }
        }else{
            //若 file 为文件
            File file1 = new File(path+File.separator+name);
            try {
                //创建文件
                file1.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try(
                    //输入输出流
                    //此处定义的流 都是final 且在执行完try catch 后 自动关闭
                    FileInputStream fileInputStream = new FileInputStream(file);
                    FileOutputStream fileOutputStream = new FileOutputStream(file1)
                )
            {
                byte[] bytes = new byte[1024 * 5];
                int len = 0;
                
                //输出
                while  ( (len = fileInputStream.read(bytes)) != -1 ){
                    fileOutputStream.write(bytes,0,len);
                }
                //强制刷出
                fileOutputStream.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

有几个要注意的点:
1:File.separator 为 不定的 文件的分割符 , 在windows 下 为‘\’,在linux下为‘/’,故在以后写分割符时,尽量使用File.separator
2:在使用fileOutputStream.write();方法时,一开始 我使用的是:fileOutputStream.write(byte[]);但是这样会导致可能源文件已经结束了,但是复制出来的文件中在本应该结束的地方多余出来一些文本 ,这是因为此方法会将byte数组所有的都写入磁盘,但是,上一次的读入可能仅读入x长度的byte,x之后的byte为上上次读取的废弃byte,此时再全部写入磁盘就会导致多写数据到新文件(复制出来的文件),解决的方法是使用fileOutputStream.write(byte[],int begin,int end);如此一来,解决问题。
3:在try 后方的括号中 定义的 流 在 try catch 块完毕后会
自动关闭

3字符流初始用

字符流有以下(未包含全部,本次复习主要包含以下):
FileReader
FileWriter
BufferedReader
PrintWriter
ObjectInputStream
ObjectOutputStream
DataInputStream
DataOutputStream

下方的输入流(BufferedReader,ObjectInputStream,DataInputStream)的构造函数 均需以流作为 入参,如:

			    FileReader fileReader = new FileReader(file);
                BufferedReader bufferedReader = new BufferedReader(fileReader);

基本操作可以去 How2J 去稍作学习。
以下几个小demo可以帮你迅速掌握 字符流:
1:使用字符流将文件输出到控制台。
2:写入一些字符到文件中。
3:将文件加密(加密规则可以 如:* 数字:
* 如果不是9的数字,在原来的基础上加1,比如5变成6, 3变成4
* 如果是9的数字,变成0
* 字母字符:
* 如果是非z字符,向右移动一个,比如d变成e, G变成H
* 如果是z,z->a, Z-A。
* 字符需要保留大小写
* 非字母字符
* 比如’,&^ 保留不变,中文也保留不变)。
4:使用BufferedReader读取有规律的数据进行操作(如,将一本小说按章节拆分)。
5:ObjectOutputStream 持久化 对象。
6:PrintWriter 向文件中写入字符串。
7:DataOutputStream 持久化数据,DataInputStream读取。
8:查找指定文件夹下 内容带关键字的文件。
下面为demo8的代码:

    /**
     * 在 file 文件夹下找到 。java后缀的文件
     * @param file
     * @return
     */
    public static List<File> findJavaFile(File file){
        List<File> fileList = new ArrayList<>();
        //System.out.println("file.getName() = " + file.getName());
        if(file.isDirectory()){
            File[] files = file.listFiles();

            for(File file1 : files){
                
                if(file1.isDirectory()){
                    List<File> temp = findJavaFile(file1);

                    if(temp != null){
                        fileList.addAll(temp);
                    }

                }else {
                    if(file1.getName().indexOf(".java") > 0){
                        fileList.add(file1);
                    }
                }
            }

        }
        return fileList;
    }

    /**
     * 从fileList中找到文件内容带关键字的文件
     * @param fileList
     * @param word
     * @return
     */
    public static List<File> constanitWord(List<File> fileList,String word){
        List<File> files = new ArrayList<>();
        for (File f : fileList) {
            try(FileReader fileReader = new FileReader(f);
                BufferedReader bufferedReader = new BufferedReader(fileReader)
            ) {
                String line = null;

                while( (line = bufferedReader.readLine()) != null ){
                    if(line.indexOf(word) > 0){
                        files.add(f);
                        break;
                    }
                }

            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return files;
    }

注意:
1:ObjectInputStream 和 DataInputStream 两个在读入时 是没有 结束 标志的,解决方法有两种:
若文件中有若干个Object对象,你用ObjectInputStream中的readObject()去读,何时判读到结尾?
方法之一:(常用的方法)将若干个对象(数量不定)都装入一个容器中(如:ArrayList之类),
然后将容器这一个对象写入就行了。读取时,只要读取一个对象(即容器对象)就行了。
方法之二:(若不想用容器),则由于数量不定,正是用EOFException来判断结束。
值得一提的是 EOFException 是 IOException,故catch时应放在IOException前catch。
2:要用DataInputStream 读取一个文件,这个文件必须是由DataOutputStream 写出的,否则会出现EOFException,因为DataOutputStream 在写出的时候会做一些特殊标记,只有DataInputStream 才能成功的读取。

本次的复习以how2J上的教程来的,故本片博客的demo部分和上面教程的练习一样,侵删。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值