489

フランス系カナダ人の文字列を変換しようとしていますが、基本的には、文字を維持したまま、文字のフランス語のアクセント記号を取り出せるようにしたいと考えています。(例: に変換するéecrème brûléeになりますcreme brulee)

これを達成するための最良の方法は何ですか?

4

20 に答える 20

597

私はこの方法を使用していませんが、Michael Kaplanは、発音区別符号の除去について説明している彼のブログ投稿(紛らわしいタイトル付き)で使用する方法を説明しています。間隔がありませんが、一部は他よりも間隔がありません)

static string RemoveDiacritics(string text) 
{
    var normalizedString = text.Normalize(NormalizationForm.FormD);
    var stringBuilder = new StringBuilder(capacity: normalizedString.Length);

    for (int i = 0; i < normalizedString.Length; i++)
    {
        char c = normalizedString[i];
        var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
        if (unicodeCategory != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder
        .ToString()
        .Normalize(NormalizationForm.FormC);
}

これは彼の以前の投稿のフォローアップであることに注意してください:発音区別符号の除去...

このアプローチでは、 String.Normalizeを使用して、入力文字列を構成グリフに分割し(基本的に、「基本」文字を発音区別符号から分離します)、結果をスキャンして基本文字のみを保持します。少し複雑ですが、実際には複雑な問題を見ています。

もちろん、フランス語に限定している場合は、@ David Dibbenが推奨するように、C ++ std::stringでアクセントとチルダを削除する方法の単純なテーブルベースのアプローチでうまくいく可能性があります。

于 2008-10-30T02:29:01.240 に答える
204

これは私にとってはうまくいきました...

string accentedStr;
byte[] tempBytes;
tempBytes = System.Text.Encoding.GetEncoding("ISO-8859-8").GetBytes(accentedStr);
string asciiStr = System.Text.Encoding.UTF8.GetString(tempBytes);

クイック&ショート!

于 2010-01-18T14:16:44.353 に答える
35

誰かが興味を持っている場合に備えて、私は似たようなものを探していて、次のように書き終えました:

public static string NormalizeStringForUrl(string name)
{
    String normalizedString = name.Normalize(NormalizationForm.FormD);
    StringBuilder stringBuilder = new StringBuilder();

    foreach (char c in normalizedString)
    {
        switch (CharUnicodeInfo.GetUnicodeCategory(c))
        {
            case UnicodeCategory.LowercaseLetter:
            case UnicodeCategory.UppercaseLetter:
            case UnicodeCategory.DecimalDigitNumber:
                stringBuilder.Append(c);
                break;
            case UnicodeCategory.SpaceSeparator:
            case UnicodeCategory.ConnectorPunctuation:
            case UnicodeCategory.DashPunctuation:
                stringBuilder.Append('_');
                break;
        }
    }
    string result = stringBuilder.ToString();
    return String.Join("_", result.Split(new char[] { '_' }
        , StringSplitOptions.RemoveEmptyEntries)); // remove duplicate underscores
}
于 2009-04-23T08:32:00.680 に答える
16

ここで見つけた別のバージョンに基づく拡張方法をよく使用します(C#(ascii)での文字の置き換えを参照)簡単な説明:

  • Dを形成するために正規化すると、èのような文字がe間隔の`に分割されます。
  • これから、nospacing文字が削除されます
  • 結果は正規化されてフォームCに戻ります(これが必要かどうかはわかりません)

コード:

using System.Linq;
using System.Text;
using System.Globalization;

// namespace here
public static class Utility
{
    public static string RemoveDiacritics(this string str)
    {
        if (null == str) return null;
        var chars =
            from c in str.Normalize(NormalizationForm.FormD).ToCharArray()
            let uc = CharUnicodeInfo.GetUnicodeCategory(c)
            where uc != UnicodeCategory.NonSpacingMark
            select c;

        var cleanStr = new string(chars.ToArray()).Normalize(NormalizationForm.FormC);

        return cleanStr;
    }

    // or, alternatively
    public static string RemoveDiacritics2(this string str)
    {
        if (null == str) return null;
        var chars = str
            .Normalize(NormalizationForm.FormD)
            .ToCharArray()
            .Where(c=> CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
            .ToArray();

        return new string(chars).Normalize(NormalizationForm.FormC);
    }
}
于 2012-10-31T10:05:38.013 に答える
13

ギリシャ語 (ISO)の CodePage はそれを行うことができます

このコードページに関する情報はSystem.Text.Encoding.GetEncodings(). 詳細については、https ://msdn.microsoft.com/pt-br/library/system.text.encodinginfo.getencoding(v=vs.110).aspx を参照してください。

ギリシャ語 (ISO) のコードページは28597で、名前はiso-8859-7です。

コードに移動... \o/

string text = "Você está numa situação lamentável";

string textEncode = System.Web.HttpUtility.UrlEncode(text, Encoding.GetEncoding("iso-8859-7"));
//result: "Voce+esta+numa+situacao+lamentavel"

string textDecode = System.Web.HttpUtility.UrlDecode(textEncode);
//result: "Voce esta numa situacao lamentavel"

だから、この関数を書いて...

public string RemoveAcentuation(string text)
{
    return
        System.Web.HttpUtility.UrlDecode(
            System.Web.HttpUtility.UrlEncode(
                text, Encoding.GetEncoding("iso-8859-7")));
}

最初が名前で、2 番目が Encoding のコードページであるため、...Encoding.GetEncoding("iso-8859-7")は と同等であることに注意してください。Encoding.GetEncoding(28597)

于 2016-08-05T01:46:49.567 に答える
6

そのような質問は非常に多くの答えを得ることができますが、私の要件に合うものはありません:)周りには非常に多くの言語があり、他の人がFormCまたはFormDが問題を引き起こしていると述べているように、言語にとらわれない完全な解決策は実際には不可能です。

元の質問はフランス語に関連していたので、最も簡単な答えは確かに

    public static string ConvertWesternEuropeanToASCII(this string str)
    {
        return Encoding.ASCII.GetString(Encoding.GetEncoding(1251).GetBytes(str));
    }

1251 は、入力言語のエンコード コードに置き換える必要があります。

ただし、これは1文字のみを1文字に置き換えます。私もドイツ語を入力として作業しているので、手動で変換しました

    public static string LatinizeGermanCharacters(this string str)
    {
        StringBuilder sb = new StringBuilder(str.Length);
        foreach (char c in str)
        {
            switch (c)
            {
                case 'ä':
                    sb.Append("ae");
                    break;
                case 'ö':
                    sb.Append("oe");
                    break;
                case 'ü':
                    sb.Append("ue");
                    break;
                case 'Ä':
                    sb.Append("Ae");
                    break;
                case 'Ö':
                    sb.Append("Oe");
                    break;
                case 'Ü':
                    sb.Append("Ue");
                    break;
                case 'ß':
                    sb.Append("ss");
                    break;
                default:
                    sb.Append(c);
                    break;
            }
        }
        return sb.ToString();
    }

最高のパフォーマンスは得られないかもしれませんが、少なくとも読み取りと拡張は非常に簡単です。正規表現はNO GOであり、文字/文字列よりもはるかに低速です。

スペースを削除する非常に簡単な方法もあります。

    public static string RemoveSpace(this string str)
    {
        return str.Replace(" ", string.Empty);
    }

最終的に、上記の 3 つの拡張機能をすべて組み合わせて使用​​しています。

    public static string LatinizeAndConvertToASCII(this string str, bool keepSpace = false)
    {
        str = str.LatinizeGermanCharacters().ConvertWesternEuropeanToASCII();            
        return keepSpace ? str : str.RemoveSpace();
    }

そして、成功する(網羅的ではない)小さな単体テスト。

    [TestMethod()]
    public void LatinizeAndConvertToASCIITest()
    {
        string europeanStr = "Bonjour ça va? C'est l'été! Ich möchte ä Ä á à â ê é è ë Ë É ï Ï î í ì ó ò ô ö Ö Ü ü ù ú û Û ý Ý ç Ç ñ Ñ";
        string expected = "Bonjourcava?C'estl'ete!IchmoechteaeAeaaaeeeeEEiIiiiooooeOeUeueuuuUyYcCnN";
        string actual = europeanStr.LatinizeAndConvertToASCII();
        Assert.AreEqual(expected, actual);
    }
于 2017-02-06T13:19:11.337 に答える
3

これはVBバージョンです(ギリシャ語で動作します):

System.Textをインポートします

System.Globalizationをインポートします

Public Function RemoveDiacritics(ByVal s As String)
    Dim normalizedString As String
    Dim stringBuilder As New StringBuilder
    normalizedString = s.Normalize(NormalizationForm.FormD)
    Dim i As Integer
    Dim c As Char
    For i = 0 To normalizedString.Length - 1
        c = normalizedString(i)
        If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
            stringBuilder.Append(c)
        End If
    Next
    Return stringBuilder.ToString()
End Function
于 2010-07-28T13:21:20.587 に答える
3

これは、すべての.NETプログラムで分音記号を非分音記号に置き換える方法です

C#:

//Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter 'é' is substituted by an 'e'
public string RemoveDiacritics(string s)
{
    string normalizedString = null;
    StringBuilder stringBuilder = new StringBuilder();
    normalizedString = s.Normalize(NormalizationForm.FormD);
    int i = 0;
    char c = '\0';

    for (i = 0; i <= normalizedString.Length - 1; i++)
    {
        c = normalizedString[i];
        if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
        {
            stringBuilder.Append(c);
        }
    }

    return stringBuilder.ToString().ToLower();
}

VB.NET:

'Transforms the culture of a letter to its equivalent representation in the 0-127 ascii table, such as the letter "é" is substituted by an "e"'
Public Function RemoveDiacritics(ByVal s As String) As String
    Dim normalizedString As String
    Dim stringBuilder As New StringBuilder
    normalizedString = s.Normalize(NormalizationForm.FormD)
    Dim i As Integer
    Dim c As Char

    For i = 0 To normalizedString.Length - 1
        c = normalizedString(i)
        If CharUnicodeInfo.GetUnicodeCategory(c) <> UnicodeCategory.NonSpacingMark Then
            stringBuilder.Append(c)
        End If
    Next
    Return stringBuilder.ToString().ToLower()
End Function
于 2013-08-01T18:55:31.563 に答える
3

まだ検討していない場合は、このライブラリをここにポップします。それにはあらゆる種類の単体テストがあるようです。

https://github.com/thomasgalliker/Diacritics.NET

于 2017-05-21T21:10:25.160 に答える
2

HelperSharp パッケージを試してください。

メソッドRemoveAccentsがあります:

 public static string RemoveAccents(this string source)
 {
     //8 bit characters 
     byte[] b = Encoding.GetEncoding(1251).GetBytes(source);

     // 7 bit characters
     string t = Encoding.ASCII.GetString(b);
     Regex re = new Regex("[^a-zA-Z0-9]=-_/");
     string c = re.Replace(t, " ");
     return c;
 }
于 2013-05-03T02:25:24.463 に答える
1

この人が言ったこと:

Encoding.ASCII.GetString(Encoding.GetEncoding(1251).GetBytes(text));

実際には、 å1 つの文字 (文字 code00E5であり、同じように見える修飾子ではありません) をいくつ の修飾子に分割し、ASCII 変換で修飾子を削除して、 のみを残します。0061030Aaa

于 2015-12-11T17:09:47.823 に答える
1
Imports System.Text
Imports System.Globalization

 Public Function DECODE(ByVal x As String) As String
        Dim sb As New StringBuilder
        For Each c As Char In x.Normalize(NormalizationForm.FormD).Where(Function(a) CharUnicodeInfo.GetUnicodeCategory(a) <> UnicodeCategory.NonSpacingMark)  
            sb.Append(c)
        Next
        Return sb.ToString()
    End Function
于 2015-06-22T13:34:46.837 に答える
1

MMLib.Extensions nuget パッケージの文字列拡張機能を使用できます。

using MMLib.RapidPrototyping.Generators;
public void ExtensionsExample()
{
  string target = "aácčeéií";
  Assert.AreEqual("aacceeii", target.RemoveDiacritics());
} 

Nuget ページ: https://www.nuget.org/packages/MMLib.Extensions/ Codeplex プロジェクト サイトhttps://mmlib.codeplex.com/

于 2013-12-30T10:25:13.883 に答える