44-Android之提取系统所有string字段

44-Android之提取系统所有string字段


平台: Android10 MTK6739

根据上篇43-Android之提取所有的strings.xml文件已经提取到所有的strings.xml文件,发送给客户。但是客户希望将所有的字段提取到Excel文件中,肯定不可能手动整理,因此写了个工具类进行提取。


package uitls;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

public class Main {

    public static void main(String[] args) {
        // 存放所有strings.xml文件的目录
        String rootPath = "F:\\xxxxx\\Language";
        Main main = new Main();
        main.launch(rootPath);
    }
   	// 需要语言类型
    final static String LOCALE_EN = "en";
    final static String LOCALE_ES = "es";
    final static String LOCALE_CA = "ca";
    final static String LOCALE_EU = "eu";
    final static String LOCALE_GL = "gl";
    final static String LOCALE_PT = "pt";

    private void launch(String rootPath) {
        
        File file = new File(rootPath);

        if (!file.exists() || !file.isDirectory()) {
            return;
        }

        // 所有的字段及语言翻译
        List<StringBean> allData = new ArrayList<>();
        Map<String, StringBean> stringsMap = new HashMap<>();
        // 目标路径,记录每个字段所在的文件
        String targetPath = null;

        // 所有的res目录的路径
        List<String> resFilePaths = new ArrayList<String>();
        loadResFilePath(rootPath, resFilePaths);
        System.out.println("launch: resFilePaths: " + resFilePaths);

        // 遍历所有的res目录
        for (String resFilePath : resFilePaths) {

            // res目录
            File resFile = new File(resFilePath);
            String resFileName = resFile.getName();
            System.out
                    .println("start resFilePath: " + resFilePath + ", resFileName: " + resFileName);

            // 所有values目录
            File[] valuesListFiles = resFile.listFiles();
            for (File valuesFile : valuesListFiles) {
                String valuesFilePath = valuesFile.getAbsolutePath();
                String valueFileName = valuesFile.getName();
                System.out.println("start valuesFilePath: " + valuesFilePath + ", valueFileName: "
                        + valueFileName);
                // values目录对应的语言
                String locale = getLocale(valueFileName);
                if (locale == null) {
                    return;
                }

                // strings.xml和arrays.xml文件
                File[] stringListFiles = valuesFile.listFiles();
                for (File stringFile : stringListFiles) {
                    String stringFilePath = stringFile.getAbsolutePath();
                    String stringFileName = stringFile.getName();
                    System.out.println(
                            "start stringFilePath: " + stringFilePath + ", stringFileName: "
                                    + stringFileName);
                    if (stringFileName.toLowerCase().contains("string")) {
                        // string.xml文件
                        if (locale.equalsIgnoreCase(LOCALE_EN)) {
                            targetPath = stringFilePath;
                        }

                        // stringFilePath: 是strings.xml文件的路径, 现在开始解析xml文件
                        getLocaleStrings(stringFilePath, targetPath, locale, stringsMap);
                    } else {
                        // arrays.xml文件, 目前没有进行处理
                    }
                } // strings end
            } // values end
        } // res end

		// 获取到的所有string字段
        allData.addAll(stringsMap.values());

        System.out.println("allData:");
        System.out.println(allData.toString());

        // 添加到队列, 生成Excel文件, 使用到poi包
        Workbook workbook = new HSSFWorkbook();
        Sheet sheet = workbook.createSheet("languages");
        sheet.setDefaultColumnWidth(32);
        Row titleRow = sheet.createRow(0);
        // name, en, ca , es, eu, gl, pt, path
        Cell nameCell = titleRow.createCell(0);
        nameCell.setCellValue("name");
        Cell enCell = titleRow.createCell(1);
        enCell.setCellValue("en");
        Cell caCell = titleRow.createCell(2);
        caCell.setCellValue("ca");
        Cell esCell = titleRow.createCell(3);
        esCell.setCellValue("es");
        Cell euCell = titleRow.createCell(4);
        euCell.setCellValue("eu");
        Cell glCell = titleRow.createCell(5);
        glCell.setCellValue("gl");
        Cell ptCell = titleRow.createCell(6);
        ptCell.setCellValue("pt");
        Cell pathCell = titleRow.createCell(7);
        pathCell.setCellValue("path");

        for (int i = 0; i < allData.size(); i++) {
            int index = i + 1;

            titleRow = sheet.createRow(index);

            StringBean bean = allData.get(i);
            nameCell = titleRow.createCell(0);
            nameCell.setCellValue(bean.mName);
            enCell = titleRow.createCell(1);
            enCell.setCellValue(bean.mEnContent);
            caCell = titleRow.createCell(2);
            caCell.setCellValue(bean.mCaContent);
            esCell = titleRow.createCell(3);
            esCell.setCellValue(bean.mEsContent);
            euCell = titleRow.createCell(4);
            euCell.setCellValue(bean.mEuContent);
            glCell = titleRow.createCell(5);
            glCell.setCellValue(bean.mGlContent);
            ptCell = titleRow.createCell(6);
            ptCell.setCellValue(bean.mPtContent);
            pathCell = titleRow.createCell(7);
            pathCell.setCellValue(bean.mTargetPath);
        }

        String excelPath = "F:\\xxxxx\\Language\\language.xls";
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(excelPath);
            workbook.write(outputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                outputStream = null;
            }

            if (workbook != null) {
                try {
                    workbook.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                workbook = null;
            }
        }

    }


    private void loadResFilePath(String filePath, List<String> resFilePaths) {
        File rootFile = new File(filePath);
        File[] rootListFiles = rootFile.listFiles();
        for (File rootListFile : rootListFiles) {
            boolean isDirectory = rootListFile.isDirectory();
            String name = rootListFile.getName();
            System.out.println("getResFilePath: isDirectory: " + isDirectory + ", name: " + name);
            if (isDirectory) {
                if (name.toLowerCase().equals("res")) {
                    File[] listFiles = rootListFile.listFiles();
                    System.out.println("getResFilePath listFiles: " + listFiles.length);
                    if (listFiles.length > 0) {
                        System.out.println("getResFilePath listFiles[0].getName().toLowerCase(): "
                                + listFiles[0].getName().toLowerCase());
                        boolean contains = listFiles[0].getName().toLowerCase().contains("values");
                        System.out.println("getResFilePath contains: " + contains);
                        if (contains) {
                            resFilePaths.add(rootListFile.getAbsolutePath());
                        } else {
                            loadResFilePath(rootListFile.getAbsolutePath(), resFilePaths);
                        }
                    }
                } else {
                    loadResFilePath(rootListFile.getAbsolutePath(), resFilePaths);
                }
            }
        }
    }

    private void getLocaleStrings(String stringFilePath, String targetPath, String locale,
            Map<String, StringBean> stringsMap) {
        System.out.println("getLocaleStrings stringFilePath: " + stringFilePath + ", targetPath: "
                + targetPath);

        // 创建一个SAX解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        // 创建一个SAX转换工具
        try {
            SAXParser saxParser = factory.newSAXParser();
            // 解析XML
            saxParser.parse(new File(stringFilePath), new ParseSAX(stringsMap, targetPath, locale));
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private String getLocale(String fileName) {
        String locale = null;
        if (fileName.toLowerCase().equals("values")) {
            locale = LOCALE_EN;
        } else if (fileName.toLowerCase().replace("values", "").contains(LOCALE_ES)) {
            locale = LOCALE_ES;
        } else if (fileName.toLowerCase().replace("values", "").contains(LOCALE_CA)) {
            locale = LOCALE_CA;
        } else if (fileName.toLowerCase().replace("values", "").contains(LOCALE_EU)) {
            locale = LOCALE_EU;
        } else if (fileName.toLowerCase().replace("values", "").contains(LOCALE_GL)) {
            locale = LOCALE_GL;
        } else if (fileName.toLowerCase().replace("values", "").contains(LOCALE_PT)) {
            locale = LOCALE_PT;
        }
        return locale;
    }

    public static class ParseSAX extends DefaultHandler {
        public static final String Q_STRING = "string";
        public static final String ATTR_NAME = "name";
        public static final String ATTR_TRANSLATABLE = "translatable";
        private Map<String, StringBean> mStringsMap;
        private StringBean mCurrentBean;
        private String mLocale = null;
        private String mTargetPath = null;

        public ParseSAX(Map<String, StringBean> stringsMap, String targetPath, String locale) {
            mStringsMap = stringsMap;
            mTargetPath = targetPath;
            mLocale = locale;
        }

        @Override
        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {
            if (qName.toLowerCase().equalsIgnoreCase(Q_STRING)) {
                String name = attributes.getValue(ATTR_NAME);
                // 有些string字段带有translatable属性,不需要翻译,此处我没有进行排除, 需要进行排除的可以自己判断下
                int index = attributes.getIndex(ATTR_TRANSLATABLE);
                System.out.println("startElement index: "+index);
                if(index != -1) {
                    String value = attributes.getValue(index);
                    System.out.println("startElement value: " + value);
                }
                System.out.println("qName: <" + qName + " name=" + name + ">");
                // 此处使用name + "_" + mTargetPath,是因为整个系统的string字段的name肯定有重复的,加上mTargetPath是为了保证唯一性
                StringBean bean = mStringsMap.get(name + "_" + mTargetPath);
                if (bean == null) {
                    bean = new StringBean();
                }
                mCurrentBean = bean;
                bean.mName = name;
                bean.mTargetPath = mTargetPath;

            } else {
                System.out.println("qName: <" + qName + ">");
            }

        }

        @Override
        public void endElement(String uri, String localName, String qName) throws SAXException {
            System.out.println("qName: <" + qName + ">");
            if (Q_STRING.equals(qName)) {
                mStringsMap.put(mCurrentBean.mName + "_" + mCurrentBean.mTargetPath, mCurrentBean);
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            String str = new String(ch, start, length);
            if (!"\r\n".equals(str) && mCurrentBean != null) {
                System.out.println(str);
                if (LOCALE_EN.equals(mLocale)) {
                    mCurrentBean.mEnContent += str;
                } else if (LOCALE_CA.equals(mLocale)) {
                    mCurrentBean.mCaContent += str;
                } else if (LOCALE_ES.equals(mLocale)) {
                    mCurrentBean.mEsContent += str;
                } else if (LOCALE_EU.equals(mLocale)) {
                    mCurrentBean.mEuContent += str;
                } else if (LOCALE_GL.equals(mLocale)) {
                    mCurrentBean.mGlContent += str;
                } else if (LOCALE_PT.equals(mLocale)) {
                    mCurrentBean.mPtContent += str;
                }
            }
        }
    }
}

public class StringBean {
	public String mName;
	public String mEnContent;
	public String mCaContent;
	public String mEsContent;
	public String mEuContent;
	public String mGlContent;
	public String mPtContent;
	public String mTargetPath;
}

通过上面的方式,可以简单的将所有string字段提取到Excel文件中,待到客户翻译完成后,再想办法把Excel文件中字段还原到strings.xml文件中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值