10

In .NET è possibile normalizzare (NFC, NFD, NFKC, NFKD) stringhe con String.Normalize() e c'è un enum Text.NormalizationForm.Come si normalizza una stringa?

Nelle app .NET per Windows Store, entrambe non sono disponibili. Ho esaminato la classe String e negli spazi dei nomi System.Text e System.Globalization, ma non ho trovato nulla.

Avere ho perso qualcosa? Come posso normalizzare le stringhe nelle app di Windows Store?

Qualcuno ha un'idea del motivo per cui il metodo Normalize non è stato reso disponibile per le App Store?

+3

'String .Normalize' si basa su funzioni native costruite in normaliz.dll. Ho scavato un po 'e ho scoperto che utilizza la funzione [NormalizeString] (http://msdn.microsoft.com/en-us/library/windows/desktop/dd319093 (v = vs.85) .aspx). Poiché è specifico di Windows, non è disponibile per le app di Windows Store. Sfortunatamente, non ho conoscenza delle alternative. –

+1

@AlexanderManekovskiy Hai torto, ['NormalizeString' è nell'elenco delle funzioni Win32 e COM API utilizzabili nelle app di Windows Store] (http://msdn.microsoft.com/en-us/library/windows/apps/hh452772). – casperOne

+0

@casperOne Wow, dov'erano i miei occhi ?! Grazie per aver puntato su questa lista. –

risposta

7

Come hai fatto notare, lo non è disponibile su String class nelle app di Windows Store.

Tuttavia, questo solo chiama il NormalizeString function nell'API di Windows.

Ancora meglio, questa funzione è in the approved list of Win32 and COM API functions usable in Windows Store apps.

Detto questo, devi fare le seguenti dichiarazioni:

public enum NORM_FORM 
{ 
    NormalizationOther = 0, 
    NormalizationC  = 0x1, 
    NormalizationD  = 0x2, 
    NormalizationKC  = 0x5, 
    NormalizationKD  = 0x6 
}; 

[DllImport("Normaliz.dll", CharSet = CharSet.Unicode, ExactSpelling = true, 
    SetLastError = true) 
public static extern int NormalizeString(NORM_FORM NormForm, 
    string lpSrcString, 
    int cwSrcLength, 
    StringBuilder lpDstString, 
    int cwDstLength); 

Farebbe quindi chiamarlo in questo modo:

// The form. 
NORM_FORM form = ...; 

// String to normalize. 
string unnormalized = "..."; 

// Get the buffer required. 
int bufferSize = 
    NormalizeString(form, unnormalized, unnormalized.Length, null, 0); 

// Allocate the buffer. 
var buffer = new StringBuilder(bufferSize); 

// Normalize. 
NormalizeString(form, unnormalized, unnormalized.Length, buffer, buffer.Length); 

// Check for and act on errors if you want. 
int error = Marshal.GetLastWin32Error(); 
+0

'StringBuffer lpDstString' è corretto, o intendevi' StringBuilder'? –

+1

Sto cercando di farlo funzionare (usando 'StringBuilder' invece di' StringBuffer', che AFAIK non esiste), ma non funziona. 'buffer'is always" empty "(contiene nient'altro che un gruppo di' \ 0'). Qualche idea su cosa sta causando questo? –

+0

@SebastianNegraszus 'StringBuffer' è stato un errore, dovrebbe essere' StringBuilder'. Stai controllando il valore restituito da 'NormalizeString' e dai valori di' Marhsal.GetLastWin32Error'? Ti daranno più informazioni se qualcosa sta andando storto. – casperOne

0

Ciao questo è il mio codice di lavoro, non ho bisogno per tagliare i caratteri di terminazione di stringa in quanto non ce ne sono, ma lo faccio solo nel caso.

Utilizzando -1 invece di una lunghezza specificata sto lasciando che automaticamente trovare il terminatore di stringa e questo è l'unico modo ho potuto farlo funzionare correttamente in una piattaforma WinRT/WinPhoneRT obiettivo

 int bufferSize = NormalizeString(Globals.NORM_FORM.NormalizationKD, toNormalise, -1, null, 0); 

     StringBuilder buffer = new StringBuilder(bufferSize); 

     // Normalize. 
     NormalizeString(Globals.NORM_FORM.NormalizationKD, toNormalise, -1, buffer, buffer.Capacity); 

     // Check for and act on errors if you want. 
     int error = Marshal.GetLastWin32Error(); 

     if(error !=0) 
     { 
      throw (new Exception("A Win32 error with code " + error + " has occured in unmanaged NormalizeString")); 
     } 
     char[] trim = {'\0'}; 

     return buffer.ToString().TrimEnd(trim);