需求简介:解压ipa文件到当前目录,读取ipa文件下的info.plist,并返回到java界面。
1.最终效果图
2.项目整体图
jar包可以去maven仓库下载
项目工程下载链接
只要5积分,小编整了5天的功能哦。
3.源代码
3.1创建jar包主入口Main
public class Main { public static void main(String[] args) throws Exception { new IpaUI(); } } |
3.2创建IpaUI
主要涉及java.swing的使用,具体可以参考以下链接
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.File; import javax.swing.JButton; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea;
public class IpaUI { public static JFrame frmIpa; public JTextArea textArea;
public IpaUI() { // 窗口框架 frmIpa = new JFrame(); frmIpa.setTitle("ipa工具类"); frmIpa.setBounds(600, 300, 500, 400); frmIpa.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 面板1 JPanel panel = new JPanel(); frmIpa.getContentPane().add(panel, BorderLayout.NORTH); JButton button = new JButton("选择文件"); // 监听button的选择路径 button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { JFileChooser jfc = new JFileChooser(); // jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES ); // 显示打开的文件对话框 jfc.showSaveDialog(frmIpa); try { // 使用文件类获取选择器选择的文件 File file = jfc.getSelectedFile();// String content = IpaService.getIpaInfoMap(file.toString()); textArea.setText(content); } catch (Exception e2) { JPanel panel3 = new JPanel(); JOptionPane.showMessageDialog(panel3, "没有选中任何文件", "提示", JOptionPane.WARNING_MESSAGE); } } }); panel.add(button);
// 可滚动面板 JScrollPane scrollPane = new JScrollPane(); frmIpa.getContentPane().add(scrollPane, BorderLayout.CENTER); textArea = new JTextArea(); // textArea.setFont(new Font("黑体",Font.BOLD,15)); scrollPane.setViewportView(textArea);
// 面板2 // JPanel panel2 = new JPanel(); // frmIpa.getContentPane().add(panel2, BorderLayout.SOUTH); // JButton button2 = new JButton("请选择解压路径"); // button2.addActionListener(new ActionListener() { // public void actionPerformed(ActionEvent e) { // JFileChooser jfc=new JFileChooser(); //// jfc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES ); // //显示打开的文件对话框 // jfc.showSaveDialog(frmIpa); // try { // //使用文件类获取选择器选择的文件 // File file = jfc.getSelectedFile(); // String content = ReadUtils.getIpaInfoMap(file.toString()); // textArea.setText(content); // } catch (Exception e2) { // System.out.println("没有选中任何输出路径"); // } // } // }); // panel2.add(button2); //全部显示
frmIpa.setVisible(true); } } |
3.3创建IpaService
主要涉及dd.plist的使用,
解析ipa/*/info.plist文件。
import java.io.File; import java.util.Map.Entry;
import javax.swing.JOptionPane; import javax.swing.JPanel; import com.dd.plist.NSArray; import com.dd.plist.NSDictionary; import com.dd.plist.NSObject; import com.dd.plist.PropertyListParser;
/** * 1.键值对对象,直接添加 * 2.字典对象,添加键,值递归 * 2.1值数组 * 2.2值字典 * * 3.数组对象,添加键,值判断 */ public class IpaService {
/** * 1.生成info.plist文件的键值对 * * @param ipa 输入api文件的路径 * @return map Info.plist文件中的信息转为键值对 .api文件---->.zip文件---->返回Info.plist */ public static String getIpaInfoMap(String ipaPath) { try { File Infofile = IpaDao.unZip(ipaPath); // 解析路径中的文件,封装到map集合 NSDictionary parse = (NSDictionary) PropertyListParser.parse(Infofile); String infoPlist = digui(parse, -1); return infoPlist; } catch (Exception e) { JPanel panel = new JPanel(); JOptionPane.showMessageDialog(panel, "文件类型不支持", "提示", JOptionPane.WARNING_MESSAGE); } return null; }
/** * 2.递归方法 * * @param sb * @return */ public static String digui(NSDictionary parse, int count) { ++count; StringBuffer sb = new StringBuffer(); for (Entry<String, NSObject> entry : parse.entrySet()) { // 获取文档键对应的值 String object = entry.getValue().toString(); // 获取文档键 String key = entry.getKey(); // 1.判断是否是其他类型 if (object.contains("NSArray") || object.contains("NSDictionary")) {
// 1.1数组类型判断 if (object.contains("NSArray")) { NSObject[] array = ((NSArray) parse.get(key)).getArray(); // 1.1.1先添加主键 for (int i = 0; i < count; i++) { sb.append("\t"); } sb.append(key + ":" + "\r\n");
// 1.1.2判断值类型 for (int i = 0; i < array.length; i++) { //如果是字典类型,继续递归 if (array[i].toString().contains("NSDictionary")) { NSDictionary parse3 = (NSDictionary) array[i]; String digui2 = digui(parse3, count); sb.append(digui2); } //如果是数值,直接添加 else { for (int j = 0; j < count; j++) { sb.append("\t"); } sb.append("\t" + array[i] + "\r\n"); } } } //1.2字典类型判断 else { for (int i = 0; i < count; i++) { sb.append("\t"); } sb.append(key + ":" + "\r\n"); NSDictionary parse2 = (NSDictionary) parse.get(key); String digui3 = digui(parse2, count); sb.append(digui3);
} }
// 2.如果是键值对类型直接添加 else { for (int i = 0; i < count; i++) { sb.append("\t"); } sb.append(key + ":" + parse.get(key) + "\r\n"); } } return sb.toString(); }
} |
3.4创建IpaDao
主要涉及对javazip的使用,
IO流解压zip文件。
import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * 解压Zip文件工具类 */ public class IpaDao {
private static final int buffer = 2048;
/** * 解压Zip文件 * @param ipaPath 文件目录 * @throws IOException */ public static File unZip(String ipaPath) throws IOException { int count = -1; File file = null; InputStream is = null; FileOutputStream fos = null; BufferedOutputStream bos = null; ZipFile zipFile = null; File result = null;
String savepath = ""; savepath = ipaPath.substring(0, ipaPath.lastIndexOf(".")) + File.separator; File existsSavePath = new File(savepath); // 创建保存目录 if(existsSavePath.exists()){ existsSavePath.delete(); } existsSavePath.mkdir();
zipFile = new ZipFile(ipaPath); // 解决中文乱码问题 Enumeration<?> entries = zipFile.entries(); while (entries.hasMoreElements()) { byte buf[] = new byte[buffer]; ZipEntry entry = (ZipEntry) entries.nextElement(); String filename = entry.getName(); boolean ismkdir = false; // 检查此文件是否带有文件夹 if (filename.lastIndexOf("/") != -1) { ismkdir = true; } filename = savepath + filename; // 如果是文件夹先创建 if (entry.isDirectory()) { file = new File(filename); file.mkdirs(); continue; } file = new File(filename); // 如果是文件夹先创建 if (!file.exists()) { if (ismkdir) { new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs(); // 目录先创建 } } file.createNewFile(); // 创建文件 //判断文件名字 if(filename.endsWith(".app/Info.plist")) { result = new File(filename); }
is = zipFile.getInputStream(entry); fos = new FileOutputStream(file); bos = new BufferedOutputStream(fos, buffer);
while ((count = is.read(buf)) > -1) { bos.write(buf, 0, count); } bos.flush(); bos.close(); fos.close();
is.close(); } zipFile.close();
try { if (bos != null) { bos.close(); } if (fos != null) { fos.close(); } if (is != null) { is.close(); } if (zipFile != null) { zipFile.close(); } } catch (Exception e) { e.printStackTrace(); } return result; } } |
至此,一个星期的学习工具及使用完毕,感觉思路和学习方法真的重要,在路上浪费了不少思路错误的时间,导致进度缓慢。加油。