Removendo acentos de um string usando C#

Este artigo é uma coletânea de algoritmos que tem o propósito comum de remover acentos de uma string.

Visando facilitar o entendimento, cada algorítimo foi colocado em blocos de código separados, e o programa principal usado em todos eles se encontra abaixo.

using System;
namespace DiacriticsRemover
{
    class Program
    {
        static void Main(string[] args)
        {
            string stringWithDiacritics = "!@# $% ¨&* ºª' aáã eéè iíì oóõ uúù";
            Console.WriteLine(DiacriticsMarksRemoval.DiacriticsClearString(stringWithDiacritics));
        }
    }
}

StringBuilder

Este algoritmo utiliza o StringBuilder para salvar a string carácter por carácter após passarem pelo Normalize e validação de Unicode.

StringBuilder: pode ser usada quando você deseja modificar uma cadeia de caracteres sem criar um novo objeto;
Normalize: Retorna uma nova cadeia de caracteres cujo valor textual é o mesmo que essa cadeia de caracteres, mas cuja representação binária está no formato de normalização Unicode especificado;
CharUnicodeInfo.GetUnicodeCategory: Obtém a categoria Unicode de um caractere Unicode;
UnicodeCategory.NonSpacingMark: Caractere sem espaçamento que indica as modificações de um caractere base;

using System.Globalization;
using System.Text;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(this string text)
        {
            StringBuilder stringRetunr = new StringBuilder();
            var arrayText = text.Normalize(NormalizationForm.FormD).ToCharArray();
            foreach (char letter in arrayText)
            {
                if (CharUnicodeInfo.GetUnicodeCategory(letter) != UnicodeCategory.NonSpacingMark)
                {
                    stringRetunr.Append(letter);
                }
            }
            return stringRetunr.ToString();
        }
    }
}

// => console exit: !@# $% ¨&* ºª' aaa eee iii ooo uuu

Array de comparação

Faz a leitura de todos os caracteres que está na string, e efetua a substituição daqueles que estão na variável withDiacritics pelos que estão na withoutDiacritics.

using System.Globalization;
using System.Text;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(string text)
        {
            string withDiacritics = "ÄÅÁÂÀÃäáâàãÉÊËÈéêëèÍÎÏÌíîïìÖÓÔÒÕöóôòõÜÚÛüúûùÇç";
            string withoutDiacritics = "AAAAAAaaaaaEEEEeeeeIIIIiiiiOOOOOoooooUUUuuuuCc";
            for (int i = 0; i < withDiacritics.Length; i++)
            {
                text = text.Replace(withDiacritics[i].ToString(), withoutDiacritics[i].ToString());
            }
            return text;
        }
    }
}

// => console exit: !@# $% ¨&* ºª' aaa eee iii ooo uuu

LINQ

NormalizationForm.FormD: Indica que uma cadeia de caracteres Unicode é normalizada usando a decomposição canônica completa
UnicodeCategory.NonSpacingMark: Caractere sem espaçamento que indica as modificações de um caractere base;

Juntas são uma forma de representar a string original de forma que marcadores como acentuação, cedilha, entre outros, sejam separadas em caracteres distintos. O caractere base, que é a letra, e o caractere da marcação. O caractere de acentuação, neste caso é chamado de NonSpacingMark, ou seja, marcador sem espaço, significa que é um marcador que não ocupa nenhum espaço, e será aplicado ao caractere anterior.

Usando o LINQ podemos remover estas marcações, deixando apenas os caracteres base, sem as marcações e construímos uma nova string a partir desses caracteres.

using System.Globalization;
using System.Linq;
using System.Text;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(this string text)
        {
            return new string(text
                .Normalize(NormalizationForm.FormD)
                .Where(ch => char.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark)
                .ToArray());
        }
    }
}

// => console exit: !@# $% ¨&* ºª' aaa eee iii ooo uuu

Encoding

GetEncoding: Retorna a codificação associada ao nome da página de código especificada. O parametro “iso-8859-8” é atribuido pois não suporta acento.
Encoding.UTF8.GetString: Codifica a saída para o padrão UTF-8.

using System;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return String.Empty;
            }
            byte[] bytes = System.Text.Encoding.GetEncoding("iso-8859-8").GetBytes(text);
            return System.Text.Encoding.UTF8.GetString(bytes);
        }
    }
}

// => console exit: !@# $% ?&* oa' aaa eee iii ooo uuu

MMLib.Extensions

Uma alternativa é instalar o seguinte pacote nuget MMLib.Extensions então você poderá remover os acentos da seguinte forma

using MMLib.Extensions;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(this string text)
        {
            return text.RemoveDiacritics();
        }
    }
}

// => console exit: !@# $% ¨&* ºª' aaa eee iii ooo uuu

UrlDecode e UrlEncode

UrlDecode: Converte uma cadeia de caracteres codificada para transmissão em uma URL em uma cadeia de caracteres decodificada
UrlEncode: Codifica uma cadeia de caracteres para transmissão de HTTP confiável do servidor Web para um cliente através da URL

O parâmetro “iso-8859-8” é atribuído ao GetEncoding pois este encode não suporta acento.

using System.Web;
using System.Text;
namespace DiacriticsRemover
{
        public static string DiacriticsClearString(string text)
        {
            return HttpUtility.UrlDecode(HttpUtility.UrlEncode(text, Encoding.GetEncoding("iso-8859-7")));
        }
}

// => console exit: !@# $% ?&* oa' aaa eee iii ooo uuu

Regex

Este algoritmo primeiro remove os acentos e usado Encoding, depois utiliza o regex “[^a-zA-Z0-9]=-_/” para remover tudo que não esteja definido na expressão.

using System.Web;
using System.Text;
using System.Text.RegularExpressions;

namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString(this string source)
        {
            var encodeEightBit = Encoding.GetEncoding(1251).GetBytes(source);
            var stringSevenBits = Encoding.ASCII.GetString(encodeEightBit);
            var regex = new Regex("[^a-zA-Z0-9]=-_/");
            return regex.Replace(stringSevenBits, " ");
        }
    }
}

// => console exit: !@# $% ?&* ??' aaa eee iii ooo uuu

Conclusão

Este foram alguns algoritmos que achei na internet. Minha alteração em cada um deles foi basicamente para deixar o exemplo mais simples e funcional.

Montei uma classe unica com todos os métodos para facilitar a referencia e visualização.

using System.Web;
using System.Text;
using System.Text.RegularExpressions;
using MMLib.Extensions;
using System;
using System.Linq;
using System.Globalization;
namespace DiacriticsRemover
{
    public static class DiacriticsMarksRemoval
    {
        public static string DiacriticsClearString_sample1(this string text)
        {
            StringBuilder stringRetunr = new StringBuilder();
            var arrayText = text.Normalize(NormalizationForm.FormD).ToCharArray();
            foreach (char letter in arrayText)
            {
                if (CharUnicodeInfo.GetUnicodeCategory(letter) != UnicodeCategory.NonSpacingMark)
                {
                    stringRetunr.Append(letter);
                }
            }
            return stringRetunr.ToString();
        }

        public static string DiacriticsClearString_sample2(string text)
        {
            string withDiacritics = "ÄÅÁÂÀÃäáâàãÉÊËÈéêëèÍÎÏÌíîïìÖÓÔÒÕöóôòõÜÚÛüúûùÇç";
            string withoutDiacritics = "AAAAAAaaaaaEEEEeeeeIIIIiiiiOOOOOoooooUUUuuuuCc";
            for (int i = 0; i < withDiacritics.Length; i++)
            {
                text = text.Replace(withDiacritics[i].ToString(), withoutDiacritics[i].ToString());
            }
            return text;
        }

        public static string DiacriticsClearString_sample3(this string text)
        {
            return new string(text
                .Normalize(NormalizationForm.FormD)
                .Where(ch => char.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark)
                .ToArray());
        }

        public static string DiacriticsClearString_sample4(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return String.Empty;
            }
            byte[] bytes = System.Text.Encoding.GetEncoding("iso-8859-8").GetBytes(text);
            return System.Text.Encoding.UTF8.GetString(bytes);
        }

        public static string DiacriticsClearString_sample5(this string text)
        {
            return text.RemoveDiacritics();
        }

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

        public static string DiacriticsClearString_sample7(this string source)
        {
            var encodeEightBit = Encoding.GetEncoding(1251).GetBytes(source);
            var stringSevenBits = Encoding.ASCII.GetString(encodeEightBit);
            var regex = new Regex("[^a-zA-Z0-9]=-_/");
            return regex.Replace(stringSevenBits, " ");
        }
    }
}

Qualquer dúvida ou dicas, entre em contato: leandrolt@gmail.com

Principais referências
https://pt.stackoverflow.com/questions/2/como-fa%C3%A7o-para-remover-acentos-em-uma-string
https://docs.microsoft.com/pt-br/dotnet/standard/base-types/stringbuilder
https://docs.microsoft.com/pt-br/dotnet/api/system.string.normalize?view=netframework-4.8
http://www.ninjacode.com.br/post/2011/08/10/Retirar-acentos-de-strings-C.aspx
https://docs.microsoft.com/pt-br/dotnet/api/system.globalization.charunicodeinfo.getunicodecategory?view=netframework-4.8
https://docs.microsoft.com/pt-br/dotnet/api/system.text.encoding.getencoding?view=netframework-4.8
https://docs.microsoft.com/pt-br/dotnet/api/system.text.encoding.getstring?view=netframework-4.8
https://docs.microsoft.com/pt-br/dotnet/api/system.web.httpserverutility.urlencode?view=netframework-4.8
https://docs.microsoft.com/pt-br/dotnet/api/system.web.httputility.urldecode?view=netframework-4.8

Post navigation

Leave a Reply

Your email address will not be published. Required fields are marked *