1. 程式人生 > >oui.txt檔案的格式化操作以及db檔案的重寫

oui.txt檔案的格式化操作以及db檔案的重寫

Organizationally unique identifier (OUI) “組織唯一識別符號”,是IEEE分發給各個廠家的唯一MAC識別符號。

我們知道,裝置的MAC地址由12位數字和字母混合組成,這裡需要注意的是:MAC地址的前六位代表唯一的廠商,且MAC地址中的英文字元取值範圍為A~F。

考慮這樣一個需求,我們需要在自己的應用中查詢某一個MAC對應的廠商,有兩個方法可以實現:

直接把oui.txt下載到本地,然後將txt檔案放到res資料夾下的raw資料夾下,然後在程式碼中直接查詢,如下所示:

        InputStream inputStream = context.getResources().openRawResource(R.raw.oui);
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        BufferedReader reader = new BufferedReader(inputStreamReader);
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                if (line.contains(mac)) {
                    return line;                    //獲取到型號行
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

這樣做的好處在於方便,壞處也顯而易見:效能太低。

第二種方法是將oui.txt先格式化,然後將格式化的新的txt檔案讀取到資料庫中,這樣在應用中查詢時將直接查詢sqlite資料庫,查詢時間將大大縮短。

那麼首先我們把oui.txt檔案格式化,新的檔案我們命名為new_oui.txt(需要注意的點已經寫在程式碼註釋中):

public class FileConvert {
    public static void main(String[] args){
        try{
            FileReader fr = new FileReader(new File("/Users/admin/Downloads/oui.txt"));
            BufferedReader br = new BufferedReader(fr);
            FileWriter fw = new FileWriter(new File("/Users/admin/Downloads/new_oui.txt"));
            String str;
            String tempStr;
            while ((str = br.readLine()) != null) {
                if(str.equals("") || str.length() < 7){
                    continue;
                }
                tempStr = str.substring(0,6);
                if(regexTest(tempStr)){//檢查某一行的前六位是否是mac,如果是則進行抽取
                    str = tempStr + " " + str.substring(22);//從第22位字元開始的是廠商名字,將6位的mac和廠商名字拼接起來
                    fw.write(str + "\n");
                }
            }
            br.close();
            fr.close();
            fw.flush();
            fw.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    public static boolean regexTest(String str){
        Pattern r = Pattern.compile("^[A-F0-9]{6}$");//mac的前六位由英文A~F及數字0-9構成
        Matcher m = r.matcher(str);
        return m.matches();
    }
}

經過這樣一步操作後,我們得到了新的txt檔案:

接下來要做的是從新的txt檔案中讀取資料到sqlite的db檔案中:

首先把new_oui.txt放到raw資料夾下,然後把它讀取到應用在本機中的本地資料夾下:

public static void writeFile(){
        try {
            if(!(new File("/data/data/xxx.xxx.xx/new_oui.txt").exists())){
                InputStream is = MyApplication.getContext().getResources().openRawResource(
                        R.raw.new_oui);
                FileOutputStream fos = new FileOutputStream("/data/data/xxx.xxx.xx/new_oui.txt");
                byte[] buffer = new byte[400000];
                int count;
                while ((count = is.read(buffer)) > 0) {
                    fos.write(buffer, 0, count);
                }
                fos.close();
                is.close();
            }

        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

然後,我們開始把new_oui.txt中的資料匯入到db檔案中,這裡為了方便,我並沒有構造一個新的db檔案,而是從網上下載了一個db檔案,然後將其進行重寫:

public static void rewriteDb(){
        deleteAll();
        try{
            FileReader fr = new FileReader(new File("/data/data/xxx.xx.xxx/new_oui.txt"));
            BufferedReader br = new BufferedReader(fr);
            String str;
            String mac;
            String factory;
            while ((str = br.readLine()) != null) {
                if(str.equals("") || str.length() < 7){
                    continue;
                }
                mac = str.substring(0,6);
                factory = str.substring(7,str.length());
                DeviceFactoryEntity entity = new DeviceFactoryEntity();
                entity.threeByteMac = mac;
                entity.factory = factory;
                insert(entity);
            }
            br.close();
            fr.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

public static void deleteAll(){
        try {
            String sqlDeleteData = "DELETE  FROM device_factory_entity";
            getInstance().db.execSQL(sqlDeleteData);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

public static void insert(DeviceFactoryEntity entity){
        if(entity != null){
            ContentValues values = new ContentValues();
            values.put("three_byte_mac",entity.threeByteMac);
            values.put("factory",entity.factory);
            getInstance().db.insert("device_factory_entity",null,values);
        }
    }

完成以後,就可以愉快的用sqlite去查詢MAC對應的廠商名啦。

這裡給出一個db檔案的下載,db檔案中的資料對應2018年9月底的oui.txt: