将语言环境与Java的toLowerCase()和toUpperCase()一起使用


72

我想要代码将Java中字符串中的所有字符都转换为大写或小写。

我发现了这样的方法:

public static String changelowertoupper()
{
         String str = "CyBeRdRaGoN";
         str=str.toLowerCase(Locale.ENGLISH);
         return str;
}

现在,我读到使用某些Locales(例如土耳其语)“返回i(不带点)而不是i(带点)”

使用Locale英国,美国,英语等语言是否安全?应用于字符串时,它们之间有什么大区别吗?

哪个最Locale适合Strings?


1
您是否尝试过完全不使用语言环境?
alaster 2012年

1
我尝试过...它类似于Locale.ENGLISH ...但是仍然我怀疑它是否有任何区别,因为存在土耳其语....所以我们说不使用Locales可以.... ?? ?
Arjun KP 2012年

4
您的应用程序将选择默认语言环境,因此,如果有人使用土耳其语语言环境以土耳其语运行您的应用程序,他将看到i不带点
alaster

这发生在我身上。我用来简化编程的一个技巧使我的程序在Window的土耳其语版本中出现故障。该程序开始搜索“adjectıves.txt”而不是“ adjectives.txt”。
WVrock

Answers:


74

我认为您应该使用语言环境,

例如,在土耳其语区域设置中的“ TITLE” .toLowerCase()返回“tıtle”,其中“ı”是拉丁文小写字母I字符。要获得对语言环境不敏感的字符串的正确结果,请使用toLowerCase(Locale.ENGLISH)。

我将这些链接称为解决您的问题的方法,它在您遇到“土耳其语”时要牢记

**FROM THE LINKS**

toLowerCase()尊重国际化(i18n)。它根据您的语言环境执行大小写转换。当您调用toLowerCase()时,将在内部调用toLowerCase(Locale.getDefault())。它是对语言环境敏感的,因此您不应围绕该语言编写逻辑来独立解释语言环境。

import java.util.Locale;

public class ToLocaleTest {
    public static void main(String[] args) throws Exception {
        Locale.setDefault(new Locale("lt")); //setting Lithuanian as locale
        String str = "\u00cc";
    System.out.println("Before case conversion is "+str+
" and length is "+str.length());// Ì
        String lowerCaseStr = str.toLowerCase();
    System.out.println("Lower case is "+lowerCaseStr+
" and length is "+lowerCaseStr.length());// iı`
    }
}

在上面的程序中,查看转换前后的字符串长度。它将是1和3。是。大小写转换前后的字符串长度不同。当您在这种情况下依赖于字符串长度时,您的逻辑就会折腾。当您的程序在其他环境中执行时,它可能会失败。这将是代码检查中的一个不错的选择。

为了使其更安全,可以使用另一种方法toLowerCase(Locale.English)并将语言环境始终替换为English。但是那时您还没有国际化。

因此,关键是toLowerCase()是特定于语言环境的。

参考1
参考2
参考3


Dotless-i,是不带点的小写字母“ i”。该字符的大写字母是通常的“ I”。还有另一个字符,“我带点”。此字符的小写字母是通常的小写字母“ i”。

您注意到问题了吗?这种不对称的转换在编程中引起了严重的问题。由于(IMHO)toLowerCase和toUpperCase函数的实现较差,我们主要在Java应用程序中遇到此问题。

在Java中,String.toLowerCase()方法根据默认语言环境将字符转换为小写。如果您的应用程序在土耳其语区域设置中工作,尤其是如果您将此函数用于必须遵循特定字符集的文件名或url,则这将导致问题。

我以前在博客中介绍过两个严重的示例:名称为“ i”的脚本库的编译错误,以及如果XPage位于名称为“ I”的数据库中,则是XSP Manager的错误。

正如我所说,历史悠久。例如,在某些R7版本中,如果路由器的名称以“ I”开头,则路由器无法向收件人发送消息。直到R8,消息报告代理才在土耳其语区域中运行。任何具有土耳其语区域设置的人都无法安装Lotus Notes 8.5.1(这是真的!)。清单继续...

土耳其几乎没有beta测试仪,客户也不会针对这些问题打开PMR。因此,这些问题并不是开发团队的首要任务。

甚至Java团队也向最新文档添加了特殊警告:

此方法对语言环境敏感,如果将其用于旨在独立解释语言环境的字符串,则可能会产生意外的结果。示例包括编程语言标识符,协议密钥和HTML标签。例如,在土耳其语区域设置中的“ TITLE” .toLowerCase()返回“tıtle”,其中“ı”是拉丁文小写字母I字符。要获得对语言环境不敏感的字符串的正确结果,请使用toLowerCase(Locale.ENGLISH)。

请阅读我不愿张贴的所有链接“这是对您的评论的答复”


1
所以您说我是否将Locale指定为ENGLISH或简单地使用str.toLowerCase()。那样就可以了……而且我不必担心字符串的长度.... ???
Arjun KP 2012年

@tchrist您的意思是什么意思我的回答带有问号,例如目的
shareef 2012年

1
U + 0131LATIN SMALL LETTER DOTLESS I“ı”,而不是“?”。在答案中加问号是错误的。它表明存在编码错误,而且还特别警告了Unicode标准。在此处放置正确的代码点。您永远不要将不可打印的代码点替换为问号。曾经
tchrist 2012年

1
@tchrist通常,我会同意你的观点,所以我支持你的评论。但是,值得注意的是,在这种情况下,OP直接引用了toUpperCase()andtoLowerCase()方法的Javadoc 。
流行

我自己的约定是使用toLowerCase(Locale.ROOT)。我觉得很有趣,他们特别推荐Locale.ENGLISH,现在我想知道两者之间的区别是什么
Trejkaz 2015年

10

您可以为自己创建合适的语言环境 String的语言。

例如:

toUpperCase(new Locale("tr","TR"));

将为土耳其人解决问题。


6
String str = "CyBeRdRaGoN";

str = str.toLowerCase(); // str = "cyberdragon"

str = str.toUpperCase(); // str = "CYBERDRAGON"

您的应用程序将选择默认语言环境,因此,如果有人使用土耳其语语言环境以土耳其语运行您的应用程序,他将看到i不带点


1

如果您正在使用此功能检查字符串(例如,搜索),则可以使用小写或大写形式的字符串进行检查。您可以这样使用它:

if (mViewData.list.data[i].Name.toLowerCase(new Locale("tr", "TR"))
   .contains(mViewHolder.tctSearch.getText().toString().trim()
                                      .toLowerCase(new Locale("tr", "TR")))) {
    // your code here...
}

我遇到相同的问题,但在listview中进行搜索的情况下。我添加了此答案,它可能会对遇到相同问题的人有所帮助。


0

在科特林

private fun changelowertoupper(): String {
        val str = "CyBeRdRaGoN"
        return str.toLowerCase(Locale.ROOT) // or Locale.getDefault()
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.