一、使用RandomAccessFile为普通文件追加内容
有的时候,需要在文件的特定位置实现内容的追加,但往往又不是xml文件,所以无法利用Jdom API来操作,为了达到在文件特定位置追加,就必须使用游标RandomAccessFile了,例如下面这个方法:
public static void appendApplication(String filePath, String packName) {
StringBuffer sb = new StringBuffer();
packName = packName.replace("\\", "/");
System.out.println(packName);
//要在return-void前面追加的内容
sb.append("invoke-virtual {p0}, L"+ packName +";->getApplicationContext()Landroid/content/Context;\r\n");
sb.append("move-result-object v0\r\n");
sb.append(".local v0, context:Landroid/content/Context;\r\n");
sb.append("invoke-static {v0}, Lcom/xx/xx/xx/xx;->install(Landroid/content/Context;)V\r\n");
try {
RandomAccessFile raf = new RandomAccessFile(filePath, "rw");
long fileLength = raf.length();
// System.out.println(fileLength);
raf.seek(fileLength - ".end method".length()-" return-void".length());
raf.writeBytes(sb.toString());
long newLength = raf.length();
raf.seek(newLength);
//这2行必须要加上,否则追加后它们将会被替换掉,\r\n是换行符
raf.writeBytes("\r\nreturn-void");
raf.writeBytes("\r\n.end method");
raf.close();
} catch (Exception e) {
e.printStackTrace();
}
}
注:或许往“普通”文件(相对xml结构的文件而言)的特定位置追加内容有更好的方法,使用游标并不是十分理想的选择,这方面待探索。。
二、往xml结构文件的特定位置追加内容(需导入w3c-dom.jar包)
由于JDOM API的存在,读写xml文件会比非xml文件容易多了,一般向xml文件追加内容会大致分为2种情况:——向特定节点内追加子节点,向根节点追加子节点。
2.1 往根节点追加子节点
public static void appendToRoot(String filePath, String permission) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try{
DocumentBuilder db = dbf.newDocumentBuilder();
File file=new File(filePath);
//Document doc = db.parse(filePath);按理说也可以,但是会因为中文路径而出现异常:
// java.net.MalformedURLException: unknown protocol: f
Document doc = db.parse(file);
Element elName = doc.createElement("uses-permission");
Attr attr = doc.createAttribute("android:name");
attr.setValue(permission);
elName.setAttributeNode(attr);
Element root = doc.getDocumentElement();
root.appendChild(elName);
doc2XmlFile(doc, filePath);
}catch(Exception e) {
e.printStackTrace();
}
}
其中,doc2XmlFile方法如下:
public static void doc2XmlFile(Document document, String filename) {
try {
// 将document中的内容写入文件中
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
DOMSource source = new DOMSource(document);
StreamResult result = new StreamResult(new File(filename));
transformer.transform(source, result);
} catch (Exception ex) { System.out.println("更新" + filename + "出错:" + ex);
//
ex.printStackTrace();
}
}
这样,就能达到向根节点<manifest />追加一个权限<uses-permission android:name="android.permission.xxxx"/>的效果;
注:为了避免访问中文路径而发生java.net.MalformedURLException: unknown protocol: f 异常,建议Document doc = db.parse(file);方法的参数是一个File file = new File(String path)的类。
2.2 往特定子节点追加节点
public static void appendToNode(String filePath, String serviceName) {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try{
DocumentBuilder db = dbf.newDocumentBuilder();
File f = new File(filePath);
Document doc = db.parse(f);
Node appNode = doc.getElementsByTagName("application").item(0);
//注册service
Element serviceEle = doc.createElement("service");
Attr attr = doc.createAttribute("android:name");
attr.setValue("xx.xx.xxx.xx.xxxx");
serviceEle.setAttributeNode(attr);
appNode.appendChild(serviceEle);
doc2XmlFile(doc, filePath);
}catch(Exception e) {
e.printStackTrace();
}
}
关键是Node appNode = doc.getElementsByTagName("application").item(0); appNode.appendChild(serviceEle);这样就实现了往根节点<manifest />下的子节点<application />追加一个形如<service android:name="xx.xx.xxx.xxxx"/>的子节点
三、BufferedReader读取文件特定内容
eg.读取包名:
public static String getPackName(String xmlPath) {
String packName = null;
try {
File f = new File(xmlPath + "\\AndroidManifest.xml");
InputStream in = new FileInputStream(f);
//获取缓冲字符输入流
BufferedReader br = new BufferedReader(new InputStreamReader(in, "utf-8"));
String line = null;
while(null != (line = br.readLine())) {
if(line.contains("android:name=")) {
//循环读取
int start = line.indexOf("android:name=")+"android:name=".length()+1;
int end = line.indexOf("\"", start);
packName = line.substring(start, end);
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
return packName;
}