String converteren naar byte array in C #

Ik converteer iets van VB in C #. Het hebben van een probleem met de syntaxis van deze verklaring:

if ((searchResult.Properties["user"].Count > 0))
{
    profile.User = System.Text.Encoding.UTF8.GetString(searchResult.Properties["user"][0]);
}

Ik zie vervolgens de volgende fouten:

Argument 1: kan niet converteren van ‘object’ naar ‘byte []’

De beste overbelaste methode match voor
‘System.text.encodering.getstring (byte [])’ heeft enkele ongeldige argumenten

Ik heb geprobeerd de code op basis van dit post, maar nog steeds geen succes

string User = Encoding.UTF8.GetString("user", 0);

Alle suggesties?


1, Autoriteit 100%

Als u al een byte-array hebt, moet u weten welk type codering werd gebruikt om deze byte-array te maken.

Bijvoorbeeld, als de byte-array zo is gemaakt:

byte[] bytes = Encoding.ASCII.GetBytes(someString);

U moet het als volgt weer in een reeks veranderen:

string someString = Encoding.ASCII.GetString(bytes);

Als u kunt vinden in de geërfde code, de codering die wordt gebruikt om de byte-array te maken, moet u worden ingesteld.


2, Autoriteit 8%

Voeg eerst de System.TextNameSpace

toe

using System.Text;

Gebruik vervolgens deze code

string input = "some text"; 
byte[] array = Encoding.ASCII.GetBytes(input);

Ik hoop het te repareren!


Antwoord 3, autoriteit 3%

U kunt ook een Uitbreidingsmethodeom een methode toe te voegen aan het type Stringzoals hieronder:

static class Helper
{
   public static byte[] ToByteArray(this string str)
   {
      return System.Text.Encoding.ASCII.GetBytes(str);
   }
}

En gebruik het zoals hieronder:

string foo = "bla bla";
byte[] result = foo.ToByteArray();

Antwoord 4, autoriteit 3%

var result = System.Text.Encoding.Unicode.GetBytes(text);

Antwoord 5, autoriteit 3%

Encoding.Default mag niet worden gebruikt…

@Randall’s antwoord gebruikt Encoding.Default, maar Microsoft verhoogt een waarschuwing ervoor:

Verschillende computers kunnen standaard verschillende codering gebruiken en de standaardcodering kan op één computer worden gewijzigd. Als u de standaardcodering gebruikt om gegevens te coderen en te decoderen die tussen computers worden gestreamd of op verschillende tijdstippen op dezelfde computer worden opgehaald, kan het zijn dat deze gegevens onjuist worden vertaald. Bovendien gebruikt de codering die wordt geretourneerd door de eigenschap Default de best passende fallback om niet-ondersteunde tekens toe te wijzen aan tekens die worden ondersteund door de codetabel. Om deze redenen wordt het gebruik van de standaardcodering niet aanbevolen. Om ervoor te zorgen dat gecodeerde bytes correct worden gedecodeerd, moet u een Unicode-codering gebruiken, zoals UTF8Encoding of UnicodeEncoding. U kunt ook een protocol van een hoger niveau gebruiken om ervoor te zorgen dat hetzelfde formaat wordt gebruikt voor het coderen en decoderen.

Om te controleren wat de standaardcodering is, gebruikt u Encoding.Default.WindowsCodePage(1250 in mijn geval – en helaas is er geen vooraf gedefinieerde klasse van CP1250-codering, maar het object kan worden opgehaald als Encoding.GetEncoding(1250)).

…UTF-8-codering moet in plaats daarvan worden gebruikt…

Encoding.ASCIIis 7bit, dus in mijn geval werkt het ook niet:

byte[] pass = Encoding.ASCII.GetBytes("šarže");
Console.WriteLine(Encoding.ASCII.GetString(pass)); // ?ar?e

Op aanbeveling van Microsoft:

var utf8 = new UTF8Encoding();
byte[] pass = utf8.GetBytes("šarže");
Console.WriteLine(utf8.GetString(pass)); // šarže

Encoding.UTF8aanbevolen door anderen is een instantie van UTF-8-codering en kan ook direct of als

worden gebruikt

var utf8 = Encoding.UTF8 as UTF8Encoding;

…maar het wordt niet altijd gebruikt

Standaardcodering is misleidend: .NET gebruikt overal UTF-8 (inclusief strings die hard gecodeerd zijn in de broncode), maar Windows gebruikt in feite 2 andere niet-UTF8 niet-standaard standaardinstellingen: ANSI-codepagina(voor GUI-apps vóór .NET) en OEM-codepagina(ook bekend als DOS-standaard). Deze verschillen van land tot land (de Tsjechische editie van Windows gebruikt bijvoorbeeld CP1250 en CP852) en zijn vaak hardgecodeerd in Windows API-bibliotheken. Dus als je UTF-8 gewoon op console instelt met chcp 65001(zoals .NET impliciet doet en doet alsof het de standaard is) en een gelokaliseerd commando uitvoert (zoals ping), werkt het in de Engelse versie, maar je krijgt tofu-tekst in Tsjechië.

Laat me mijn ervaring uit de echte wereld delen: ik heb de WinForms-toepassing gemaakt om git-scripts voor docenten aan te passen. De uitvoer wordt willekeurig op de achtergrond verkregen door een proces beschreven door Microsoftals (vetgedrukte tekst toegevoegd door mij):

Het woord “shell” in deze context (UseShellExecute)verwijst naar een grafische shell (ANSI CP)(vergelijkbaar met de Windows-shell) in plaats van opdrachtshells (voor bijvoorbeeld bash of sh) (OEM CP)en laat gebruikers grafische toepassingen starten of documenten openen (met rommelige uitvoer in een niet-Amerikaanse omgeving).

GUI is zo effectief de standaardinstellingen voor UTF-8, Proces Standaardinstellingen van CP1250 en Console standaardinstellingen tot 852. Dus de uitvoer is in 852 geïnterpreteerd als UTF-8 geïnterpreteerd als CP1250. Ik heb Tofu-tekst van waaruit ik de originele codepage niet kon afleiden vanwege de dubbele conversie. Ik trekte mijn haar al een week om te achterhalen om expliciet UTF-8 voor het processcript te zetten en de uitvoer van CP1250 naar UTF-8 in de hoofddraad te converteren. Nu werkt het hier in het Oost-Europa, maar West-Europa Windows gebruikt 1252. ANSI CP wordt niet gemakkelijk bepaald zoveel opdrachten zoals systeminfozijn ook gelokaliseerd en andere methoden verschilt van versie naar versie : In een dergelijke omgeving is het op betrouwbare wijze van nationale karakters vrijwel onhaalbaar.

Dus tot de helft van de 21e eeuw, gebruik dan geen “standaard codepagina” en stel het expliciet (tot UTF-8 indien mogelijk).


6, Autoriteit 2%

static byte[] GetBytes(string str)
{
     byte[] bytes = new byte[str.Length * sizeof(char)];
     System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
     return bytes;
}
static string GetString(byte[] bytes)
{
     char[] chars = new char[bytes.Length / sizeof(char)];
     System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
     return new string(chars);
}

7

Building Ali’s antwoord , ik zou een extensie-methode aanraden waarmee u optioneel kunt doorgeven in de codering die u wilt Gebruik:

using System.Text;
public static class StringExtensions
{
    /// <summary>
    /// Creates a byte array from the string, using the 
    /// System.Text.Encoding.Default encoding unless another is specified.
    /// </summary>
    public static byte[] ToByteArray(this string str, Encoding encoding = Encoding.Default)
    {
        return encoding.GetBytes(str);
    }
}

En gebruik het zoals hieronder:

string foo = "bla bla";
// default encoding
byte[] default = foo.ToByteArray();
// custom encoding
byte[] unicode = foo.ToByteArray(Encoding.Unicode);

Antwoord 8

Dit werkte voor mij

byte[] bytes = Convert.FromBase64String(textString);

En omgekeerd:

string str = Convert.ToBase64String(bytes);

Antwoord 9

gebruik dit

byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);

Antwoord 10

De volgende aanpak werkt alleen als de tekens 1 byte zijn. (Standaard unicode werkt niet omdat het 2 bytes is)

public static byte[] ToByteArray(string value)
{            
    char[] charArr = value.ToCharArray();
    byte[] bytes = new byte[charArr.Length];
    for (int i = 0; i < charArr.Length; i++)
    {
        byte current = Convert.ToByte(charArr[i]);
        bytes[i] = current;
    }
    return bytes;
}

Houd het simpel


Antwoord 11

Deze vraag is al vaak genoeg beantwoord, maar met C# 7.2 en de introductie van het Span-type is er een snellere manier om dit in onveilige code te doen:

public static class StringSupport
{
    private static readonly int _charSize = sizeof(char);
    public static unsafe byte[] GetBytes(string str)
    {
        if (str == null) throw new ArgumentNullException(nameof(str));
        if (str.Length == 0) return new byte[0];
        fixed (char* p = str)
        {
            return new Span<byte>(p, str.Length * _charSize).ToArray();
        }
    }
    public static unsafe string GetString(byte[] bytes)
    {
        if (bytes == null) throw new ArgumentNullException(nameof(bytes));
        if (bytes.Length % _charSize != 0) throw new ArgumentException($"Invalid {nameof(bytes)} length");
        if (bytes.Length == 0) return string.Empty;
        fixed (byte* p = bytes)
        {
            return new string(new Span<char>(p, bytes.Length / _charSize));
        }
    }
}

Houd er rekening mee dat de bytes een UTF-16-gecodeerde tekenreeks vertegenwoordigen (‘Unicode’ genoemd in C#-land).

Enkele snelle benchmarking toont aan dat de bovenstaande methoden ongeveer 5x sneller zijn dan hun Encoding.Unicode.GetBytes(…)/GetString(…) implementaties voor middelgrote strings (30-50 tekens), en zelfs sneller voor grotere snaren. Deze methoden lijken ook sneller te zijn dan het gebruik van pointers met Marshal.Copy(..) of Buffer.MemoryCopy(…).


Antwoord 12

Je zou MemoryMarshal kunnen gebruiken APIom zeer snelle en efficiënte conversie uit te voeren. Stringwordt impliciet gecast naar ReadOnlySpan<byte>, aangezien MemoryMarshal.CastSpan<byte>of ReadOnlySpan<byte>als invoerparameter.

public static class StringExtensions
{
    public static byte[] ToByteArray(this string s) => s.ToByteSpan().ToArray(); //  heap allocation, use only when you cannot operate on spans
    public static ReadOnlySpan<byte> ToByteSpan(this string s) => MemoryMarshal.Cast<char, byte>(s);
}

Volgende benchmark toont het verschil:

Input: "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,"
|                       Method |       Mean |     Error |    StdDev |  Gen 0 | Gen 1 | Gen 2 | Allocated |
|----------------------------- |-----------:|----------:|----------:|-------:|------:|------:|----------:|
| UsingEncodingUnicodeGetBytes | 160.042 ns | 3.2864 ns | 6.4099 ns | 0.0780 |     - |     - |     328 B |
| UsingMemoryMarshalAndToArray |  31.977 ns | 0.7177 ns | 1.5753 ns | 0.0781 |     - |     - |     328 B |
|           UsingMemoryMarshal |   1.027 ns | 0.0565 ns | 0.1630 ns |      - |     - |     - |         - |

Antwoord 13

Ziet iemand een reden om dit niet te doen?

mystring.Select(Convert.ToByte).ToArray()

Antwoord 14

Als het resultaat van, ‘SearchResult.Properties [“Gebruiker”] [0]’, is een tekenreeks:

if ( ( searchResult.Properties [ "user" ].Count > 0 ) ) {
   profile.User = System.Text.Encoding.UTF8.GetString ( searchResult.Properties [ "user" ] [ 0 ].ToCharArray ().Select ( character => ( byte ) character ).ToArray () );
}

Het sleutelpunt is dat een tekenreeks omzet naar een byte [] kan worden gedaan met behulp van LINQ:

.ToCharArray ().Select ( character => ( byte ) character ).ToArray () )

en de inverse:

.Select ( character => ( char ) character ).ToArray () )

15

Dit is vrij veel beantwoord, maar voor mij is de enige werkwijze deze:

   public static byte[] StringToByteArray(string str)
    {
        byte[] array = Convert.FromBase64String(str);
        return array;
    }

16

Dit werk voor mij, daarna kon ik mijn foto in een bytea-veld in mijn database converteren.

using (MemoryStream s = new MemoryStream(DirEntry.Properties["thumbnailphoto"].Value as byte[]))
{
    return s.ToArray();
}

Other episodes