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();
    }
}

五、最后

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

原文地址:https://www.cnblogs.com/csyh/p/12527470.html