• java输入输出流操作同一资源实现覆盖引发冲突的解析


    一、问题发生的场景

    把文本中大写转成小写,小写转成大写,空格转成下划线,在输入到文件中覆盖之前的

    前面的没有问题,问题出现在后面的覆盖文件上,输入流、输出流要操作同一个文件的问题

    二、问题操作

    //口述一下,
    //头就创建一个文件输入流对象,紧接着创建一个文件输出流对象,问题就在这里,后面是调用各流的读写方法
    //调试:发现read()方法首次读取就是返回-1,说明遇到了文件末尾,也说明此时文件时空的
    //运行结果:文件被置空了,原来的内容没了,也没有写入内容进去
    public void wordCase(String path){
    		try(//------①
    		FileReader fr = new FileReader(path);//------②
    		FileWriter fw = new FileWriter(path))//------③
    		{
    			System.out.println(new File(path).length());
    			//记录读取到的字符
    			StringBuilder sb = new StringBuilder();
    			int hasRead = 0;
    			while((hasRead = fr.read()) != -1){
    				char c = (char)hasRead;
    				//转空格
    				if(c == ' '){
    					sb.append("_");
    				}
    				System.out.println(c);
    				//判断是否是小写
    				if(Character.isLowerCase(c)){
    					//转换成大写并加入字符串
    					sb.append(Character.toUpperCase(c));
    				}else{
    					//转换成小写并加入字符串
    					sb.append(Character.toLowerCase(c));
    				}
    			}
    			//将新字符串内容写入文件
    				fw.write(sb.toString());
    		}catch(IOException e){
    			e.printStackTrace();
    		}
    	}
    

    三、分析原因

    查找了一些资料,总结一下:

    输入流资源未关闭的情况下又开启了输出流,去操作同一个路径的文件,引发了冲突;单步调试:看上面代码的标注,从①开始运行-->②-->①-->③-->①-->下面... ,而且我在运行完②③时都查看了本地文本,发现在第③步运行完后,文件内容被置空;

    由此我推测,在运行到②时,输入流获取了文件资源;而后运行到③时,输出流获取不到资源,又没抛出FileNotFoundException,应该是没有访问权限或者访问受限了,进而直接生成了一个文件对原文件进行了替换,所以使得文件置空,而获取了文件资源的输入流再来读取文件内容就为空了,从而写出的也是空内容,最终出现文件置空的情况

    四、纠错

    老老实实做事,先读取完内容,再进行写出操作:

    //测试方法:略...
    public void wordCase(String path){
        StringBuilder sb = null;
        /*读取文件内容,并保存成字符串*/
        try(
            FileReader fr = new FileReader(path))
        {
            System.out.println(new File(path).length());
            //记录读取到的字符
            sb = new StringBuilder();
            int hasRead = 0;
            while((hasRead = fr.read()) != -1){
                char c = (char)hasRead;
                //转空格
                if(c == ' '){
                    sb.append("_");
                }
                System.out.println(c);
                //判断是否是小写
                if(Character.isLowerCase(c)){
                    //转换成大写并加入字符串
                    sb.append(Character.toUpperCase(c));
                }else{
                    //转换成小写并加入字符串
                    sb.append(Character.toLowerCase(c));
                }
            }
        }catch(IOException e){
            e.printStackTrace();
        }
        /*将新字符串内容写入文件*/
        try(
            FileWriter fw = new FileWriter(path))
        {
            fw.write(sb.toString());
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    

    五、最后

    老司机带带我,了解的前辈来发表一下见解,小白学习一下~

  • 相关阅读:
    比较对象的相对性
    深拷贝与浅拷贝(TBD)
    创建UI的线程才能访问UI,那么怎样才算访问UI呢
    多层级的数据绑定效果
    众所周知,static修饰的成员只实例化一次,而string类型每次赋值都会重新创建一个实例,那么用static修饰string呢?
    常量、只读字段
    使用dos打开相关软件
    查看电脑硬件信息dos命令
    Windows常用快捷键
    使用外部编辑器出现乱码
  • 原文地址:https://www.cnblogs.com/csyh/p/12527470.html
Copyright © 2020-2023  润新知