83

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

我找到了一个类似这样的方法:

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

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

Locale使用UK、US、ENGLISH 等 s是否安全?当应用于字符串时,它们之间有什么大的区别吗?

s最喜欢Locale哪个String

4

6 回答 6

79

我认为你应该使用 locale ,

例如,土耳其语言环境中的 "TITLE".toLowerCase() 返回 "tıtle",其中 'ı' 是 LATIN SMALL LETTER DOTLESS 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) 并始终将语言环境覆盖为英语。但是你没有国际化。

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

参考 1
参考 2
参考 3


Dotless-i,是没有点的小写“i”。这个字符的大写是通常的“I”。还有一个字符,“I with dot”。这个字符的小写字母是通常的小写字母“i”。

你注意到问题了吗?这种非对称转换会导致编程中的严重问题。我们主要在 Java 应用程序中遇到这个问题,因为(恕我直言)toLowerCase 和 toUpperCase 函数的实现很差。

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

我之前在博客上写过两个严重的例子:名称中带有“i”的脚本库的编译错误以及如果 XPage 位于名称中带有“I”的数据库中,则 XSP 管理器的错误。

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

土耳其几乎没有 beta 测试人员,客户也不会为这些问题打开 PMR。所以这些问题并不是开发团队的首要任务。

甚至 Java 团队也在最新的文档中添加了特别警告:

此方法对语言环境敏感,如果用于旨在独立解释语言环境的字符串,可能会产生意外结果。示例是编程语言标识符、协议键和 HTML 标记。例如,土耳其语言环境中的 "TITLE".toLowerCase() 返回 "tıtle",其中 'ı' 是 LATIN SMALL LETTER DOTLESS I 字符。要获得不区分区域设置的字符串的正确结果,请使用 toLowerCase(Locale.ENGLISH)。

于 2012-06-16T11:51:05.457 回答
14

您可以为您的语言创建适当String的语言环境。

例如:

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

会为土耳其人做的伎俩。

于 2017-04-02T01:31:00.313 回答
6
String str = "CyBeRdRaGoN";

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

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

您的应用程序将选择默认区域设置,因此如果有人使用土耳其语区域设置在土耳其语中运行您的应用程序,他将看到i没有点

于 2012-06-16T11:45:16.847 回答
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 中进行搜索时。我添加了这个答案,它可以帮助有同样问题的人。

于 2017-11-01T07:15:30.677 回答
0

在科特林

private fun changelowertoupper(): String {
        val str = "CyBeRdRaGoN"
        return str.lowercase()
    }
于 2019-09-04T17:03:53.103 回答
0

如果您愿意,可以android:textLocale="tr"在 XML 端使用选项。

<TextView
android:text="inciler"
android:textAllCaps="true"
android:textLocale="tr" />

输出:İNCİLER

于 2021-05-24T07:00:12.523 回答