最近做实验室项目,因为有过多长短类型不一的数组要保存交互,感觉JDBC实在是有些麻烦,所以尝试用文件形式做交互,但是也遇到了一些问题。

1、文件读写相关程序

1)新建文件

     

File f=new File(path);
        if(!f.exists()){
            f.createNewFile();
        }

2)删除文件

 

if(f.exists()&&f.isFile()){
           f.delete();
        }3)bufferedreader读取
        BufferedWriter br = new BufferedReader(new FileWriter(path));
       String content;        
        content=br.readLine(); //每次读取一行,如有分隔符可以进行分割
        content.trim().//去除头尾的空格
        //如果每一行是存入以逗号分隔的数组,以转换为double类型数组为例
        String[] strAry = str.split(",");
        double[] ary = new double[strAry.length]; 

        for(int i = 0; i < strAry.length; i++){ 

            ary[i] = Double.parseDouble(strAry[i]); 

        } 

        //如果每行只是一个单独的double类型数,即
       double result=Double.parseDouble(br.readLine());
        //读取全部结束后记得关闭数组       
         br.close();
4)BufferedWriter写入
        BufferedWriter bw = new BufferedWriter(new FileWriter(path));
        bw.write(string+"\n");
        bw.close();

5)几个注意点:

    【1】BufferedWriter bw = new BufferedWriter(new FileWriter(path)); 这句话是直接新建文件,在执行这句话的时候新文件就已经生成好了。如果原本已有文件,会覆盖内容。

    【2】这种写法保存的文件一般后缀为txt或dat

    【3】由于先建立文件,再进行写入,因此再前后端交互时,就算用先删除文件再创建文件的方式,也没有办法保证前后端写入和读取文件不发生冲突。


2、类型转化相关程序

    为了将String和其他类型变量,或其他类型数组的相互转化,需要定义一些类型转化的方法,具体如下:

public static int[] intStrToArray(String str) {
        String[] strAry = str.split(",");
        int[] ary = new int[strAry.length];
        for(int i = 0; i < strAry.length; i++){
            ary[i] = Integer.parseInt(strAry[i]);
        }        return 

    public static String[] strToArray(String str) { 

        String[] strAry = str.split(","); 

        return strAry; 

    } 



    public static double[] doubleStrToArray(String str) { 

        String[] strAry = str.split(","); 

        double[] ary = new double[strAry.length]; 

        for(int i = 0; i < strAry.length; i++){ 

            ary[i] = Double.parseDouble(strAry[i]); 

        } 

        return ary; 

    } 



    public static String arrayToString(int[] ary){ 

        StringBuilder sb = new StringBuilder(); 

        for(int i = 0; i < ary.length; i++){ 

            sb.append(ary[i]).append(","); 

        } 

        sb.deleteCharAt(sb.length() -1); 

        return sb.toString(); 

    }

    public static String arrayToString(double[] ary){ 

        StringBuilder sb = new StringBuilder(); 

        for(int i = 0; i < ary.length; i++){ 

            sb.append(ary[i]).append(","); 

        } 

        sb.deleteCharAt(sb.length() -1); 

        return sb.toString(); 

    }

    public static String arrayToString(String[] ary){ 

        StringBuilder sb = new StringBuilder(); 

        for(int i = 0; i < ary.length; i++){ 

            sb.append(ary[i]).append(","); 

        } 

        sb.deleteCharAt(sb.length() -1); 

        return sb.toString(); 

    }


3、采用的方案及遇到的坑

    设前端为A,后端为B,A给B的文件称为A*,B给A的文件成为B*,如果整个流程需要控制为A*生成,后端读取A*,B*生成,前端读取B*四个顺序执行的步骤,

    1)尝试1:用增删文件A*,B*的方式

    流程开始时,先删除老的A*,B*,后端是while循环,判断A*生成了就开始读并计算,计算后生成B*,而前端此时写了一句File f=new File(path_B*); while(!f.exists()); 即是通过while一直等在那里,等到B*文件生成,再进行读取。

    尝试失败,原因是write时先生成了文件,才进行的写入,因此读取时刻很可能文件没有写完。


    2) 尝试2,用判断文件修改时间的方式

    和1)其实本质上是一样的,用一个语句不断读取文件修改时间,如果更新了,则进行读取操作,但是与1)一样会遇到冲突。

    判断文件是否修改的方法:

public String modify_time_old="2018-00-00 10:24:21";
public String modify_time;
public boolean isModify(String filepath){
    File f = new File(filepath);
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Calendar cal = Calendar.getInstance();
    cal.setTimeInMillis(f.lastModified());
    String info=new String();
    modify_time = sdf.format(cal.getTime());
    boolean ismod=(!modify_time.equals(modify_time_old));
    modify_time_old = modify_time;
    return ismod;
}

    3)尝试3,新建一个文件,通过读写这个文件的内容专门控制流程。

    例如包装好一个set_stage和get_stage的方法,就是用与读取文件中的内容(如1,2),然后流程如前述方法一样,用while控着,直到读取的内容变为所需要的内容。问题和1),2)中是一样的,前后端再while的时候都再同时读取文件,所以会出bug。


    4)尝试4,专门设定一个文件或多个文件用作flag,只判断这个文件是否存在,用delete和create的方式来控制流程。f.exists()相当于flag置1,否则相当于置0。和前面三种方法的不同在于,并不需要在创建文件后再进行读写,即整个流程中都不需要打开这个文件,没有同时读写这一冲突存在。

    这种方法还是很蠢...不过可以使用。

    

    5)尝试5,用重命名的方式让一个文件先变名字,写入完成后再变回来...理论上听起来好像可以,实际上还是会报错,报文件占用冲突的错误,不可取。


    6)尝试6,对1)进行改进,具体有两种方案

    6.1 采用文件锁的方法,参考

            

            

保证同时只有一个进程可以拿到文件的锁,这个进程从而可以对文件做访问;而其它拿不到锁的进程要么选择被挂起等待,要么选择去做一些其它的事情

     在1)的基础上,添加文件锁,等待到一个进程写入完成后另一个进程再

      6.2 用file.exist的方式再加一个delay

      读取程序判断到文件生成后,先不进行读取,加一个delay(问题就是delay时间不好控制)。保证文件写入完成后再进行读取。