Java 删除变音符号
Java remove diacritic
我正在尝试制作将删除变音符号的功能(不想故意使用 Normalizer)。功能看起来像
private static String normalizeCharacter(Character curr) {
String sdiac = "áäčďéěíĺľňóôőöŕšťúůűüýřžÁÄČĎÉĚÍĹĽŇÓÔŐÖŔŠŤÚŮŰÜÝŘŽ";
String bdiac = "aacdeeillnoooorstuuuuyrzAACDEEILLNOOOORSTUUUUYRZ";
char[] s = sdiac.toCharArray();
char[] b = bdiac.toCharArray();
String ret;
for(int i = 0; i < sdiac.length(); i++){
if(curr == s[i])
curr = b[i];
}
ret = curr.toString().toLowerCase();
ret = ret.replace("\n", "").replace("\r","");
return ret;
}
函数是这样调用的(文件中的每个字符都被发送到这个函数)
private static String readFile(String fName) {
File f = new File(fName);
StringBuilder sb = new StringBuilder();
try{
FileInputStream fStream = new FileInputStream(f);
Character curr;
while(fStream.available() > 0){
curr = (char) fStream.read();
sb.append(normalizeCharacter(curr));
System.out.print(normalizeCharacter(curr));
}
}catch(IOException e){
e.printStackTrace();
}
return sb.toString();
}
文件 text.txt
包含以下内容:ľščťžýáíéúäôň
并且我希望程序在 return 中包含 lcstzyaieuaon
但我得到的是预期的字符串 ¾è yaieuaoò
。我知道问题出在编码的某个地方,但不知道在哪里。有什么想法吗?
您正在尝试将字节转换为字符。
然而,字符ľ
不表示为单个字节。它的 unicode 表示是 U+013E,它的 UTF-8 表示是 C4 BE。因此,它由两个字节表示。其他角色也是如此。
假设你的文件编码是UTF-8。然后你读取字节值 C4
,然后你将它转换为 char
。这将为您提供字符 U+00C4 (Ä),not U+013E。然后你读取BE
,它被转换为字符U+00BE (¾).
所以不要混淆字节和字符。不要直接使用 InputStream
,你应该用 Reader
包裹它。 Reader
能够根据其创建时使用的编码读取字符:
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(f), StandardCharsets.UTF_8
)
);
现在,您将能够读取字符甚至整行,并且将直接完成编码。
int readVal;
while ( ( readVal = reader.read() ) != -1 ) {
curr = (char)readVal;
// ... the rest of your code
}
请记住,如果您要使用不带参数的 read()
,您仍在阅读 int
。
我正在尝试制作将删除变音符号的功能(不想故意使用 Normalizer)。功能看起来像
private static String normalizeCharacter(Character curr) {
String sdiac = "áäčďéěíĺľňóôőöŕšťúůűüýřžÁÄČĎÉĚÍĹĽŇÓÔŐÖŔŠŤÚŮŰÜÝŘŽ";
String bdiac = "aacdeeillnoooorstuuuuyrzAACDEEILLNOOOORSTUUUUYRZ";
char[] s = sdiac.toCharArray();
char[] b = bdiac.toCharArray();
String ret;
for(int i = 0; i < sdiac.length(); i++){
if(curr == s[i])
curr = b[i];
}
ret = curr.toString().toLowerCase();
ret = ret.replace("\n", "").replace("\r","");
return ret;
}
函数是这样调用的(文件中的每个字符都被发送到这个函数)
private static String readFile(String fName) {
File f = new File(fName);
StringBuilder sb = new StringBuilder();
try{
FileInputStream fStream = new FileInputStream(f);
Character curr;
while(fStream.available() > 0){
curr = (char) fStream.read();
sb.append(normalizeCharacter(curr));
System.out.print(normalizeCharacter(curr));
}
}catch(IOException e){
e.printStackTrace();
}
return sb.toString();
}
文件 text.txt
包含以下内容:ľščťžýáíéúäôň
并且我希望程序在 return 中包含 lcstzyaieuaon
但我得到的是预期的字符串 ¾è yaieuaoò
。我知道问题出在编码的某个地方,但不知道在哪里。有什么想法吗?
您正在尝试将字节转换为字符。
然而,字符ľ
不表示为单个字节。它的 unicode 表示是 U+013E,它的 UTF-8 表示是 C4 BE。因此,它由两个字节表示。其他角色也是如此。
假设你的文件编码是UTF-8。然后你读取字节值 C4
,然后你将它转换为 char
。这将为您提供字符 U+00C4 (Ä),not U+013E。然后你读取BE
,它被转换为字符U+00BE (¾).
所以不要混淆字节和字符。不要直接使用 InputStream
,你应该用 Reader
包裹它。 Reader
能够根据其创建时使用的编码读取字符:
BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream(f), StandardCharsets.UTF_8
)
);
现在,您将能够读取字符甚至整行,并且将直接完成编码。
int readVal;
while ( ( readVal = reader.read() ) != -1 ) {
curr = (char)readVal;
// ... the rest of your code
}
请记住,如果您要使用不带参数的 read()
,您仍在阅读 int
。