最近安卓项目开发中遇到一个问题,在使用百度语音合成的功能时,因为文章里面带有拼音注解,导致文字和拼音被重复读了一遍。
中国人民(zhōng guó rén mín )
现在的需求是需要识别文章中的汉语拼音,然后去掉,不让文章拼音被语音合成。那么问题就出现了:Java如何通过代码识别字符串是否是汉语拼音,还是英文单词?
比如:中国人民,这个汉语拼音是zhōng guó rén mín,但是如果写成了zhong guo ren min,经过百度翻译之后的读音是完全不一样的。
我们的实现思路:
1)从字符源头控制住,就是把文章中带拼音标准的地方通过特殊的标识进行切割掉。存在问题:无法确定拼音的切割标识,比如使用括号等方式,编辑无法统一。
2)通过识别字符的编码方式判断字符是不是拼音?还是普通的英文拼音字符或者是中文拼音字符来判断是否进行字符切割。
大概就是上面的两种实现思路,但是第一种因为编辑部门可能编辑会出现不同的拼音的标识,导致我们无法控制内容,所以只能舍弃。只能通过代码的手段来判断字符串是拼音还是英文字符。
说到拼音,我们就不得不引入一个概念:注音符号。注音符号就是带声调的中文拼音字符。
/**
* 字符转化工具类
*/
public class Snippet {
public static void main(String[] args) {
String cn = "ā";
String unicode = "\\u101";
String ch = "a";
String charA = "\\u61";
System.out.println(cnToUnicode(cn));
System.out.println(unicodeToCn(unicode));
System.out.println(cnToUnicode(ch));
System.out.println(unicodeToCn(charA));
// 字符串 : \u5f00\u59cb\u4efb\u52a1 ,由于 \ 在java里是转义字符,要写出下面这种形式
}
private static String unicodeToCn(String unicode) {
/** 以 \ u 分割,因为java注释也能识别unicode,因此中间加了一个空格*/
String[] strs = unicode.split("\\\\u");
String returnStr = "";
// 由于unicode字符串以 \ u 开头,因此分割出的第一个字符是""。
for (int i = 1; i < strs.length; i++) {
returnStr += (char) Integer.valueOf(strs[i], 16).intValue();
}
return returnStr;
}
private static String cnToUnicode(String cn) {
char[] chars = cn.toCharArray();
String returnStr = "";
for (int i = 0; i < chars.length; i++) {
returnStr += "\\u" + Integer.toString(chars[i], 16);
}
return returnStr;
}
}
我们通过调研发现Unicode编码格式,把注音符号和英文拼音字母通过唯一的字符集构成,也就是说注音符号和英文26个字母通过转化成unicode字符,都是唯一的。因为我们的文章是中文,转成unicode之后发现注音符号和汉语拼音字符编码都是唯一的,所以我们可以判断一个字符里面是否有注音符号来判断这个字符串是汉语拼音还是英文字符。
Unicode 和 UTF-8 有什么区别?
但是还有一个问题就是如果文章里面的汉语拼音是不带注音字符的字符集,那么我们通过比对单个字符发现不存在注音符号就会把它识别成英字符,导致识别失败。
最终问题:如何解决文章拼音不带注音符号导致无法识别成汉语拼音?
我们可以通过判断字符里面是否有注音符号来判断字符是不是拼音,但是如果字符串中不带注音符号就会识别失败。
所以目前可以通过工具类删除文章括号里面的内容,工具类代码如下:
private static String deleteSpecialString(String sourceStr){
do{
int fristIndex = 0, lastIndex =0;
if(sourceStr.contains("(")){
fristIndex = sourceStr.indexOf("(");
lastIndex = sourceStr.indexOf(")");
}else if(sourceStr.contains("(")){
fristIndex = sourceStr.indexOf("(");
lastIndex = sourceStr.indexOf(")");
}
String substring = sourceStr.substring(fristIndex, lastIndex+1);
String replaceStr = sourceStr.replace(substring, "");
sourceStr = replaceStr;
}while (sourceStr.contains("(") || sourceStr.contains("(") );
return sourceStr;
}
上面的算法其实可以通过正则表达式来写:利用正则表达式提取括号内内容。
但是这里有一个问题,就是括号里面的内容我们没有做判断,如果括号里面的内容是文字的话,是需要机读的。
上面的是简单的做法,就是不判断文章括号里面的具体内容,都统一删除掉。但是我们如果需要做判断,文章括号里面的是拼音或者是英文。
待解决问题:
1)如何通过中文转成unicode字符码之后,判断字符是不是注音符号来判断字符是不是汉语拼音。
2)是否有工具类可以把一长串的拼音字符,没有分割标识的情况下来正确的分割字符的拼音字符,比如:zhonghuarenmin,这个拼音字符串和chinesepublicpeople这两个字符串,如果正确的分割?
百度语音可以正常的识别,等待解决!