一、概述
海外APP,经常会翻译国外语言,项目中间突然加入一门新语言,一般海外市场部会提供一个翻译好的Excel表格,里边包含了所有的字符串和对应的翻译,如下所示:
如果项目不断迭代,对应的字符串也可能会有N多个表。手动翻译翻译,需要在项目的strings.xml文件和Excel表格中来回切换,逐条搜索替换,很不方便,使用java语言,来操作Excel表格,代码处理,可以减少了繁琐劳动,降低出错率。
需要考虑的问题很多,大致如下:
1.使用java,怎么操作Excel文件,不仅要读取,匹配好的数据也要放入一个表格里,此时就涉及到了写
2.操作时,对Excel文件的格式有个要求,不同格式的Excel文件处理时,有何不同
3.第一次处理,共用到三个Excel文件:
1). 翻译好的文件,即源文件,ori.xls。里边都是单纯的翻译,不包含
2). 复制strings.xml内容到Excel文件中,需要比对的文件,des.xls。它是含有
3). 以翻译乌克兰语为例,得到ori.xls里C、Q两列的内容后,再获取des.xls中每个单元格的内容,解析出nameStr和contentStr。根据contentStr,和ori.xls里的结果匹配比较,找到contentStr在ori.xls中的行列坐标,这样就可以推知乌克兰语的行列坐标。重新组装为
4. 此时要考虑des.xls中每条string的内容格式和结果文件result.xls的内容格式。
1).怎么截取name和content部分,最终格式为:
2).该条若注释掉了,直接跳过
3).获取到content后,要判断是否被双引号""包围,若没被双引号包围,出现了 ' 要转义为 \'
4).content中若包含非英语形式的特殊符号,如?!-等,要替换处理
5). Excel文件中的&在xml中表示为 &,也要处理
等等。
二、读Excel文件
// 创建file对象
File file = new File(filePath);
// 创建输入流,读取Excel
InputStream is = new FileInputStream(file);
// jxl提供的Workbook类
Workbook wb = Workbook.getWorkbook(is);
//获取第一个sheet
Sheet sheet = wb.getSheet(0);
Log.d(TAG, "readOriExcel: sheet name = "+ sheet.getName());
// 得到所有的行数
int rows = sheet.getRows();
for (int j = 0; j < rows; j++) {
// 得到这行每个单元格的数据
Cell[] cells = sheet.getRow(j);
}
三、写Excel文件
/**
* 将数据写入到excel中
*/
public static void writeExcel() {
//1 创建一个workbook对应一个excel文件
HSSFWorkbook workbook = new HSSFWorkbook();
//2 在workbook中创建一个sheet对应excel中的sheet
HSSFSheet sheet = workbook.createSheet(name);
for (int i = 0; i < desSheetAllData.size(); i++) {
HSSFRow row = sheet.createRow(i);
List rowData = desSheetAllData.get(i);
for (int j = 0; j < rowData.size(); j++) {
//3 创建单元格并设值
row.createCell(j).setCellValue(rowData.get(j));
}
}
FileOutputStream fos = null;
try {
fos = new FileOutputStream(PATH+"/result.xls");
workbook.write(fos);
} catch (IOException e) {
Log.d(TAG, "writeExcel: catch - " + e.getMessage());
} finally {
try {
//数据量较大,使用flush刷新该流的缓冲区
//一般写字符时要用,因为字符是先进入的缓冲区
fos.flush();
//关闭流对象
fos.close();
} catch (IOException e) {
Log.d(TAG, "writeExcel: finally -" + e.getMessage());
}
}
Log.d(TAG, "writeExcel: success!!!");
}
注:此处使用HSSFWorkbook创建的是xls文件,若创建xlsx文件,要用XSSFWorkbook。 HSSFWorkbook和XSSFWorkbook 类都实现了Workbook接口。
四、解析字符串
1.利用正则表达式"<[^>]+>"解析出contentStr。
String str = "contentStr ";
// 定义xml标签的正则表达式
String regExp = "<[^>]+>";
// 过滤xml标签
String contentStr = Pattern.compile(regExp).matcher(str).replaceAll("");
2. 利用"\">"来解析出 根据contentStr找到对应的翻译以后,再把 五、处理要替换的内容contentStr 1. 汉语中的?!- 等,使用replaceAll()方法。注意,调用replaceAll()方法的使用方式: 必须接收一次replaceAll返回的字符串,这样,才是处理后,想要的结果。 2. 若想得到某个字符,如-的ASIIC码用(int)('-')就可以得到。 3. 去掉首尾的引号,使用substring()方法。 str.length()-1为字符串最后一位的下标,它作为substring()的参数2,为开区间,表示不包含最后一位。参数1位闭区间,包含第一位。故: 4. 若contentStr中含有\",比如:open \"location\",在英语和乌克兰语匹配过程中,是以open "location"来匹配的,此时要把\"替换为",即把\去掉 java中,\用\\表示,"用\"表示,\"则用\\\"表示。正则表达式中"\\\\"表示\。 \' 替换 ',\" 替换 ": 5. 去除字符串前后的空格,java的string.trim()只能去英文半角空格 六、其他 2. 为便于查看,Excel中不要空行; 3. 读写SD卡里的文件,打开操作后的Excel,提示: 无法打开文件,可以尝试重启手机、AndroidStudio 七、参考 HSSFworkbook,XSSFworkbook,SXSSFworkbook区别总结 Java 正则匹配html标签 JAVA 正则表达式 (超详细) 正则表达式之分组 group(java版) 浅谈JAVA中流的flush()&close()方法 close()和flush()的区别 八、代码附上content = content.replaceAll("\'", "'");
content = content.substring(1, content.length() - 1);//去掉首尾的引号
String test = "0123456";
Log.d(TAG, "lym12345: " + test.substring(0, test.length()-1));// --> 012345
Log.d(TAG, "lym12345: " + test.substring(1, test.length()-2));// --> 1234
//处理句中的\"
if (content.contains("\\\"")){
content = content.replaceAll("\\\\", "");
}
//没有双引号的时候,遇到'再用\'替换,遇到"再用\"替换
if (content.contains("'")) {
content = content.replace("'", "\\'");
} else if (content.contains("\"")){
content = content.replace("\"", "\\\"");
}
public class StringUtil {
/**普通的英文半角空格Unicode编码*/
private static final int SPACE_32 = 32;
/**中文全角空格Unicode编码(一个中文宽度)*/
private static final int SPACE_12288 = 12288;
/**普通的英文半角空格但不换行Unicode编码(== == == no-break space)*/
private static final int SPACE_160 = 160;
/**半个中文宽度(== == en空格)*/
private static final int SPACE_8194 = 8194;
/**一个中文宽度(== == em空格)*/
private static final int SPACE_8195 = 8195;
/**四分之一中文宽度(四分之一em空格)*/
private static final int SPACE_8197 = 8197;
/**窄空格*/
private static final int SPACE_8201 = 8201;
/**
* 去除字符串前后的空格, 包括半角空格和全角空格(中文)等各种空格, java的string.trim()只能去英文半角空格
* @param str
*/
public static String trim(String str) {
if (TextUtils.isEmpty(str)) {
return str;
}
char[] val = str.toCharArray();
int st = 0;
int len=val.length;
while ((st < len) && isSpace(val[st])) {
st++;
}
while ((st < len) && isSpace(val[len - 1])) {
len--;
}
return ((st > 0) || (len < val.length)) ? str.substring(st, len) : str;
}
private static boolean isSpace(char aChar) {
return aChar == SPACE_32 || aChar == SPACE_12288 || aChar == SPACE_160 || aChar == SPACE_8194
|| aChar == SPACE_8195 || aChar == SPACE_8197 || aChar == SPACE_8201;
}
}
1. 每次写入时有上限,不要多余150行;public class Excel {
private static final String TAG = "lym1234";
private static String PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/xml/";
private static String DES_FILE = "des.xls";
private static String ORI_FILE = "ori.xls";
private static int indexR = 0;
private static int indexC = 0;
private static final int DOT = 1;//.
private static final int QUESTION_MARK = 2;//?
private static final int POINT = 3;//!
private static List
> oriSheetAllData = new ArrayList<>(); // ori所有的数据
private static List
> desSheetAllData = new ArrayList<>(); // des所有的数据
public static void operate() {
try {
oriSheetAllData.clear();
desSheetAllData.clear();
readOriExcel();
readDesExcel();
writeExcel();
} catch (Exception e) {
Log.d(TAG, "e: " + e.getMessage());
}
}
private static void readOriExcel() throws Exception {
// 读取Excel文件
File file = new File(PATH+ORI_FILE);
// 创建输入流,读取Excel
InputStream is = new FileInputStream(file.getAbsolutePath());
// jxl提供的Workbook类
Workbook wb = Workbook.getWorkbook(is);
int sheetNum = wb.getNumberOfSheets();
Log.d(TAG, "readOriExcel: sheetNum = " + sheetNum);
for (int i = 0; i < sheetNum; i++){
Sheet sheet = wb.getSheet(i);//获取每个sheet
Log.d(TAG, "readOriExcel: sheet name = "+ sheet.getName());
// 得到所有的行数
int rows = sheet.getRows();
Log.d(TAG, "readOriExcel: rows = " + rows);
// 越过第一行 它是列名称
for (int j = 1; j < rows; j++) {
List