oui.txt檔案的格式化操作以及db檔案的重寫
阿新 • • 發佈:2018-12-14
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: