Domanda

Devo essere in grado di accettare un input di testo arbitrario che potrebbe avere un marcatore di ordine di byte (BOM) su di esso per contrassegnare la sua codifica e inviarlo come ASCII. Abbiamo alcuni vecchi strumenti che non comprendono le distinte base e devo inviare loro solo dati ASCII.

Ora ho appena finito di scrivere questo codice e non riesco proprio a credere all'inefficienza qui. Quattro copie dei dati, per non parlare di eventuali buffer intermedi internamente in StreamReader. C'è un modo migliore per farlo?

// i_fileBytes is an incoming byte[]

string unicodeString = new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd();
byte[] unicodeBytes  = Encoding.Unicode.GetBytes(unicodeString.ToCharArray());
byte[] ansiBytes     = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes);
string ansiString    = Encoding.ASCII.GetString(ansiBytes);

Ho bisogno di StreamReader () perché ha un rilevatore BOM interno per scegliere la codifica per leggere il resto del file. Quindi il resto è solo per farlo convertire nella stringa ASCII finale.

C'è un modo migliore per farlo?

È stato utile?

Soluzione

Se hai già i_fileBytes in memoria, puoi semplicemente verificare se inizia con una distinta base e quindi convertire l'intero o solo il bit dopo la distinta utilizzando Encoding.Unicode.GetString . (Utilizzare il sovraccarico che consente di specificare un indice e una lunghezza.)

Quindi come codice:

int start = (i_fileBytes[0] == 0xff && i_fileBytes[1] == 0xfe) ? 2 : 0;
string text = Encoding.Unicode.GetString(i_fileBytes, start, i_fileBytes.Length-start);

Nota che ciò presuppone comunque una codifica UTF-16 veramente poco endian. Se hai davvero bisogno di rilevare prima la codifica, potresti reimplementare ciò che fa StreamReader o forse semplicemente creare uno StreamReader dai primi (diciamo) 10 byte e usare la proprietà CurrentEncoding per capire cosa dovresti > utilizzare per la codifica.

EDIT: Ora, come per la conversione in ASCII - se ne hai davvero bisogno solo come stringa .NET, presumibilmente tutto ciò che vuoi fare è sostituire eventuali caratteri non ASCII con "? " o qualcosa di simile. (In alternativa, potrebbe essere meglio lanciare un'eccezione ... dipende da te, ovviamente.)

EDIT: Nota che quando si rileva la codifica, sarebbe una buona idea chiamare Read () una sola volta per leggere un carattere. Non chiamare ReadToEnd () poiché selezionando 10 byte come una quantità arbitraria di dati, potrebbe terminare a metà carattere. Non so con certezza se ciò genererebbe un'eccezione, ma non ha comunque alcun vantaggio ...

Altri suggerimenti

System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

Ciò dovrebbe consentire di risparmiare alcuni round trip.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top