博客 / 詳情

返回

隨機訪問流RandomAccessFile擴展工具類

因為工作上有對Properties文件進行修改屬性值的操作,於是寫了一個RandomAccessFile的擴展類,可以在文件指定位置插入內容刪除指定位置之後自定義大小的內容替換內容
附上代碼:

/**
 * RandomAccessFile的擴展類
 * 新增了在文件指定位置插入內容、刪除指定位置之後自定義大小的內容、替換內容等功能
 * @author objcfeng
 */
public class RandomAccessFileExt extends RandomAccessFile {
    public RandomAccessFileExt(String name, String mode) throws FileNotFoundException {
        super(name, mode);
    }

    public RandomAccessFileExt(File file, String mode) throws FileNotFoundException {
        super(file, mode);
    }

    /**
     * 功能:在文件指定位置插入內容
     * 實現過程:
     * 將添加位置之後的文件內容使用字節數組保存,
     * 向文件寫入插入的內容,再寫入字節數組中的內容
     * 注意:
     * 調用此方法後後將文件指針修改到文件結尾
     *
     * @param bytes 添加的內容
     * @param off   添加的位置,按字節算而不是字符
     */
    public void insert(byte[] bytes, int off) throws IOException {
        byte[] dst = getTheRest(off);
        write(bytes);
        write(dst);
        seek(off);
    }

    /**
     * 功能:刪除指定位置之後自定義大小的內容
     * 實現過程:
     * 使用字節數組記錄off+len之後的內容,
     * 再把字節數組寫入off開始的位置,
     * 相當於把off+len之後的內容覆蓋在off位置上
     * 最後把文件長度設為原長度-len
     *
     * @param off 刪除的位置
     * @param len 刪除的字節數
     */
    public void delete(int off, int len) throws IOException {
        byte[] theRest = getTheRest(off + len);
        seek(off);
        write(theRest);
        setLength(length() - len);
        seek(off);
    }

    /**
     * 功能:替換內容
     * 實現過程:先在指定位置刪除內容再插入內容
     * @param bytes 替換內容
     * @param off 替換起始點
     * @param len 替換長度
     */
    public void replace(byte[] bytes,int off,int len) throws IOException {
        delete(off, len);
        insert(bytes,off);
    }

    /**
     * 功能:獲取off之後剩餘的內容,存儲在byte數組中
     * 注意:
     * 此方法適用於小文件
     *
     * @param off 位置
     * @return 存儲文件剩餘的內容的字節數組
     */
    private byte[] getTheRest(int off) throws IOException {
        long fileLength = length();
        if (fileLength > Integer.MAX_VALUE) {
            throw new RuntimeException("文件太大,不支持插入數據");
        }
        //將添加位置之後的文件內容使用字節數組保存
        byte[] dst = new byte[(int) fileLength - off];
        //因為readFully方法是從文件指針之後開始讀取的,所以先將指針指向off
        seek(off);
        readFully(dst);
        //將指針指回off位置
        seek(off);
        return dst;
    }
}

順便也附上操作Properties文件的工具類:

/**
 * properties配置文件工具類
 * 單例
 * @author objcfeng
 */
public class PropertiesUtil {
    private String propertiesName;
    private static volatile PropertiesUtil propertiesUtil;

    private PropertiesUtil(String propertiesName) {
        this.propertiesName = propertiesName;
    }

    /**
     * 獲取工具類實例
     * @param propertiesName propertiesName文件名,無需後綴
     * @return 工具類實例
     */
    public static PropertiesUtil getInstance(String propertiesName) {
        if (propertiesUtil == null) {
            synchronized (PropertiesUtil.class) {
                if (propertiesUtil == null) {
                    propertiesUtil = new PropertiesUtil(propertiesName);
                }
            }
        }
        return propertiesUtil;
    }

    /**
     * 根據鍵獲取值,若值為空,則返回空字符串""
     * @param key 鍵
     * @return 值
     */
    public String getPropertyValue(String key) {
        //properties文件名
        ResourceBundle resourceBundle = ResourceBundle.getBundle(propertiesName);
        return resourceBundle.getString(key);
    }

    /**
     * 修改屬性,若value長度小於原值的長度,則
     * @param key   鍵
     * @param value 值
     */
    public void setPropertyValue(String key, String value) {
        //使用隨機訪問流
        RandomAccessFileExt randomAccessFile = null;
        //文件路徑
        final String path = "src/main/resources/" + propertiesName + ".properties";
        try {
            //採用讀寫模式
            randomAccessFile = new RandomAccessFileExt(new File(path), "rw");
            //讀取到的行
            String line;
            //記錄上一次
            long filePointer = 0;
            while ((line = randomAccessFile.readLine()) != null) {
                //將讀取到的字符串以=分隔,得到的數組有如下情況 [key,value]、[comment]、[key]
                String[] kv = line.split("=");
                //獲取key
                String k = kv[0];
                if (k.trim().equals(key)) {
                    randomAccessFile.seek(filePointer);
                    String writeKV = k + "=" + value;
                    //替換這一行
                    randomAccessFile.replace(writeKV.getBytes(), (int) filePointer, line.getBytes().length);
                    break;
                }
                filePointer = randomAccessFile.getFilePointer();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (randomAccessFile != null) {
                    randomAccessFile.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.