RandomAccessFile使用之更新当前内容

先说下需求。在做自动化测试的时候,每个用例的配置文件是不一样的,于是需要在执行的时候先将用例上传,然后再执行,这边就有个问题。我的用例可能是半年前写的,所以当时的配置文件和现在最新的配置文件已经有了变化,主要是新配置文件会有新的配置项加进来。这种情况下,如果只是简单替换,那么有些关键配置的缺失会导致程序起不来。于是我便想到,每次上传的时候,都用最新的配置项,只是把用例里边的配置值拷贝过来就可以了。

比如最新的配置为new.conf,用例里的配置为old.conf。

new.conf:

#instand id
id=sitea

# MPCC customer default time zone
default_time_zone=GMT-05:00

# data persistent cron job default configuration
data_persistent_cron=0/15 * * * * ?

# data synchronization cron job configuration
data_synchronization_cron=25 0 0 * * ?

old.conf:

#instand id
id=site_def

# MPCC customer default time zone
default_time_zone=GMT-08:00

# data persistent cron job default configuration
data_persistent_cron=0/5 * * * * ?

开始我想到了用Java的properties来操作,分别读取比较,value不一样就更新。可是我发现更新之后的数据是这个样子的:

id=site_def
default_time_zone=GMT-08:00
data_persistent_cron=0/5 * * * * ?
data_synchronization_cron=25 0 0 * * ?

这显然不是我想要的结果。网上查了下没有看到properties如果解决这个问题(有知道的朋友麻烦说一下),于是便想用RandomAccessFile。

关于RandomAccessFile,网上有各种介绍,我这里只说我用到的。

  • 新建RandomAccessFile对象

           RandomAccessFile raf = new RandomAccessFile(new File(filepath), "rw");

  • pointer概念 

          pointer就是指针。RandomAccessFile支持文件的随机读写,随机的方法就是通过pointer实现,它指向了当前文件的读写位置,以byte进行计数。

  • pointer的定位

            文件初始化时,pointer的值为0,即为文件的最开始,当我们读取了一行数据,如果有这行数据有8个byte,那么读取完毕后,pointer的值就是8,如果有换行的话,那么换行字符也要加上,如果是\r\n,就再加两个字符,pointer的值就是10。可以通过getFilePointer()来会去当前的pointer位置。写文件也会改变pointer的位置。

             如果要重新定位pointer,可以通过seek()方法,比如到到文件开头,那就seek(0)

  • 文件的长度可以用length()方法获取。
  • 可以将文件写入到一个buffer中,也可以将文件从buffer中读取。命令分别为:

             raf.read(buffer, 0, (int)(raf.length() - point + 1)); 注意此处第二个参数指的是buffer的索引

             raf.write(buffer);

             RandomAccessFile的buffer读写都是和pointer有关的,读取的是pointer开始后的length个字节,写也是写到pointer之后

下面是代码:

    public static void compareConfig(File oldConf, File newConf)
      
        try {
            
            Properties pps = new Properties();
            pps.load(new FileInputStream(oldConf)); //将case中的配置读取到properties对象中
            
            RandomAccessFile raf = new RandomAccessFile(newConf, "rw"); //将新配置读取到RandomAccessFile对象中,此处访问方式是读写
            long lastPoint = 0; //定义RandomAccessFile 对象的pointer
            String line = "";
           
            while((line = raf.readLine()) != null) {              
                
                long point = raf.getFilePointer(); //每读一行,都记录下读取后的pointer位置
                System.out.println(point);
                if(!line.trim().equals("") && !line.trim().startsWith("#") && line.trim().indexOf("=") != -1) //判断是不是注释或者空行

                {
                     String[] item = line.split("="); //去配置的key和value
                     String key = item[0];
                     String oldValue = item[1];
                     String newValue = "";
                     if(pps.containsKey(key)) { //如果在case的配置中存在,就取出来case中的配置值
                         newValue = pps.getProperty(key);
                     } else {
                         lastPoint = point;  //如果case中的配置不存在,那就读取新配置的下一行,读取前,保存当前的pointer位置
                         continue;
                     }
                     if(oldValue.trim().equals(newValue.trim())) { //值相等,就continue
                         lastPoint = point;
                         continue;
                     }

                     //下边是配置相同但是值不同的逻辑
                     String newLine = line.replace(oldValue, newValue);//先用新值换旧值
                     int readBytes = (int) (raf.length() - point + 1);
                     byte[] buffer = new byte[readBytes]; //创建一个buffer,大小是newConf文件剩余的bytes数目
                     if(oldValue.length() > newValue.length()) { //处理替换的新值比旧值短的情况,比如例子中的id,缺的用空格补齐
                         int n = oldValue.length() - newValue.length();
                         while(n>0) {
                             newLine = newLine + " ";
                             n--;
                         }
                     } else if(oldValue.length() < newValue.length()) { //处理新值比旧值长的情况,将剩余的字节读取到buffer中
                         raf.seek(point-1); //将回车也拷贝到buffer中
                         raf.read(buffer, 0, (int)(raf.length() - point + 1));
                     }
                     raf.seek(lastPoint); //找到上次读取的位置
                     raf.writeBytes(newLine); //写入新值
                     if(oldValue.length() < newValue.length()) {  //对于新值比旧值长,将buffer回写               
                         lastPoint = point + newValue.length() - oldValue.length();
                         raf.write(buffer);
                     } else {
                         lastPoint = point; //新值比旧值短,简单记录上次写的位置,因为前面空格补齐了,所以pointer值不变
                     }
                     raf.seek(point);       
                     
                } else {
                    lastPoint = point;
                }
                raf.seek(lastPoint);    //最后将pointer定位在上次读或者写的地方
            }
            raf.close();
                 
        } catch (IOException e) {
            // TODO Auto-generated catch block
        }
    }

这个程序其实可以更精简一些,这里就不做了

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值