none
Zeichenfolge in ein Dictionary RRS feed

  • Frage

  • Hallo,
    ich möchte gerne ein 2 dimensionale Liste, Dictionary erstellen.
    Dezimal,   Wert
    0,       &#x0
    1,       &#x1
    2,       &#x2
    ...
    255,
    Wie könnte ich das erreichen?
    Die Sonderzeichen für XML werden vermutlich nicht gehen.
    Könnte man evtl. die 'normalen'  Zeichen ablegen?

    Hintergrund ist. Ein Kunde möchte evtl. als Austausch %03 für ein ETX also char(3) übertragen.
                     Sicher nicht XML konform, wenn er das so will.

    public class Test
    {
    	public Dictionary<string, string> DicValueSpecialCharacter;
    	public string String { get; set; }
    }
    
    var t = new Test
    {
    	DicValueSpecialCharacter = new Dictionary<string,string>(),
    	String = new String(Enumerable.Range(0, 255).Select(x => (Char)x).ToArray())
    };
    
    <?xml version="1.0" encoding="utf-8"?><Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><String>&#x0;&#x1;&#x2;&#x3;&#x4;&#x5;&#x6;&#x7;&#x8;	
    &#xB;&#xC;&#xD;&#xE;&#xF;&#x10;&#x11;&#x12;&#x13;&#x14;&#x15;&#x16;&#x17;&#x18;&#x19;&#x1A;&#x1B;&#x1C;&#x1D;&#x1E;&#x1F; !"#$%&amp;'()*+,-./0123456789:;&lt;=&gt;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~??????????????????????????? ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ</String></Test>
    
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var seri = new XmlSerializer(typeof(Test));
    
    using (var stream = File.OpenWrite("C:\\test.xml"))
    {
    	var settings = new XmlWriterSettings
    	{
    		Encoding = Encoding.UTF8,
    		NewLineHandling = NewLineHandling.Entitize,
    		CheckCharacters = false,
    	};
    	using (var writer = XmlWriter.Create(stream, settings))
    	{
    		seri.Serialize(writer, t);
    	}
    }
    
    using (var stream = File.OpenRead("C:\\test.xml"))
    {
    	var settings = new XmlReaderSettings { CheckCharacters = false, };
    	using (var reader = XmlReader.Create(stream, settings))
    	{
    		var t2 = (Test)seri.Deserialize(reader);
    		Console.WriteLine(t2.String == t.String);//sollte true sein
    	}
    }

    Grüße Sandra

    Dienstag, 7. März 2017 18:10

Antworten

  • Hallo Sandra,

    wenn man die XML-Attribute mit dem XmlReader ausliest, werden die "&#x23" bereits automatisch in das entsprechende Zeichen umgewandelt.

    XmlReader reader = XmlReader.Create(@"d:\VS Community 2017\MyProjects\Test\ConsoleApp1\ConsoleApp1.xml");
    string val;
    
    while (reader.Read())
    {
    	if (reader.NodeType == XmlNodeType.Element && reader.Name == "Project")
    		val = reader.GetAttribute("smth");
    }

    Attribut smth enthält in der XML-Datei: "Inhalt&#x0D;&#x0A;&#x002D;&#x011C;Test&#x0023;".

    val enthält nach Aufruf von Reader.GetAttribute(): "Inhalt
    -ĜTest#"

    Es ist wichtig, daß die Inhalte in der XML-Datei gültige UTF-8-Zeichen enthalten, bzw. die &#x...; gültigen UTF-8-Zeichen entsprechen. Sie müssen dem Encoding entsprechen, das in <?xml version="1.0" encoding="utf-8"?> angegeben ist.

    Gruß
    Heiko

    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Donnerstag, 9. März 2017 19:41
  • Hallo Sandra,

    am grundlegenden Vorgehen ändert sich da nichts. Du hast die Zahl als String vorliegen und könntest diese in einen Integer umwanden und diesen wiederum in ein char casten.

    Ich habe es nicht überprüft, aber die Vorgefertigtn XML-Klassen etc. werden das wohl genauso handhaben.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Freitag, 10. März 2017 00:45
    Moderator
  • Ja ;) probier es mal aus.
    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Sonntag, 12. März 2017 12:23

Alle Antworten

  • Hallo Sandra,

    hier den Begriff einer 2D Liste zu verwenden dürfte eher zu Verwirrung führen, auch wenn es nicht ganz falsch ist. Dictionary oder Liste von Wertpaaren/Tupeln trifft es wohl eher.

    Das wirkliche Problem verstehe ich jedoch noch nicht. Deiner Beispielauflistung nach suchst du nur folgendes:

    int unicodeValue = 13;//Ist ein Zeilenumbruch
    var chr = (char)unicodeValue;
    //chr ist nun das Zeichen mit dem Unicode-Wert 13
    
    Man könnte natürlich auch einen Handstand machen und irgendwie etwas mit XML versuchen, aber so sollte es am einfachsten gehen. Auch anders herum geht das Problemlos:
    var val = (int)'A';
    //val sollte nun 65 sein
    Das ganze geht natürlich immer nur mit einzelnen Zeichen, Strings müsstest du vorher also aufteilen.

    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    Dienstag, 7. März 2017 19:37
    Moderator
  • Hallo Tom,
    nicht ganz.
    Ich bekomme einen Input wie %02, wie %10, wie %13
    Diesen muss ich dann in \x02  \x0A  \x0D umwandeln.
    Danach speichere ich es als XML ab.
    Idee, ist jetzt eine Tabelle zu erstellen, um das zu handeln.
    Wenn ich warum auch immer nur einen String habe, der mir
      das "Inhalt&#x15;&#x1D;Test#x3;" liefert.
    Ich doch es selbst entschlüsseln muss.
    XMLConvert macht das ja auch nicht.
    string[] inputArray = listChars.ToArray<string>();
    var translate = String.Join(string.Empty,
           inputArray.Select(x => x != null && DicDecoding.ContainsKey(x) ? DicDecoding[x].ToString() : x.ToString()));
    private Dictionary<string, string> DicDecoding = new Dictionary<string, string>
    {
      { "%00", "\x00"  },
      { "%01", "\x01"  },
      { "%02", "\x02"  },
      { "%03", "\x03"  }
      // und so weiter
    }

    Vielleicht wird es klarer was ich suche.
    Grüße Sandra
    Mittwoch, 8. März 2017 18:43
  • Hallo Sandra,

    die Schreibweise %02%10%13 verwendet man vor allem, um Sonderzeichen oder Zeichen, die größer als \x7E (und auch größer als 255) sind, in lesbarer Form zu übertragen. In dieser Schreibweise sind Daten üblicherweise UTF8-kodiert (wie z.B. als Parameter in einer URL für den Browser).

    Das heißt, dass die Unicode-Zeichen des C# zunächst zu UTF8-Bytes umgewandelt werden müssen, die Bytes werden ins URL-Format gebracht. Die Gegenstelle muß die Bytes parsen und vom UTF8 zu Unicode zurückwandeln.

    string strA = "abcßâĜ";

    // Kodieren und Senden byte[] bytes = Encoding.UTF8.GetBytes(strA); StringBuilder sb = new StringBuilder(bytes.Length * 3); foreach (byte b in bytes) { if (b >= (byte)'0' && b <= (byte)'9' || b >= (byte)'A' && b <= (byte)'Z' || b >= (byte)'a' && b <= (byte)'z' || b == (byte)'-' || b == (byte)'_' || b == (byte)'.' || b == (byte)'~') sb.Append((char)b); else { sb.Append('%'); sb.Append(b.ToString("X2")); } } // Empfangen und Dekodieren string data = sb.ToString(); List<byte> bytes2 = new List<byte>(); for (int i = 0; i < data.Length;) { if (data[i] == '%') { bytes2.Add((byte)Int32.Parse(data.Substring(i + 1, 2), System.Globalization.NumberStyles.HexNumber)); i += 3; } else { bytes2.Add((byte)data[i]); i++; } } string strB = Encoding.UTF8.GetString(bytes.ToArray()); // Vergleich if (strB == strA) ;


    Einfacher ginge es, wenn man den String zu einem Base64-String umwandelt.
    string strA = "abcßâĜ";
    
    // Kodieren und Senden
    byte[] bytes = Encoding.UTF8.GetBytes(strA);
    
    string base64 = Convert.ToBase64String(bytes);
    
    // Empfangen und Dekodieren
    byte[] bytes3 = Convert.FromBase64String(base64);
    
    strB = Encoding.UTF8.GetString(bytes3.ToArray());
    
    // Vergleich
    if (strB == strA) ;

    Gruß
    Heiko


    Donnerstag, 9. März 2017 13:20
  • Hallo Heiko,
    vielen Dank für Deine Antwort.
    Also, ich bekomme vom Kunden einen Input mit %02 etc. für die Sonderzeichen.
    Diese wandle ich um, speichere es als XML Datei und gebe es weiter.
    Die Antwort ist ein XML, indem ich evtl. nur ein Element auswerten muss.
       wie z.B. Inhalt&#x15;&#x1D;Test#x3
    Wie bekomme ich das jetzt korrekt konvertiert?
    Wenn ich nur den String auslese ist das ja falsch.
    &#15 ist nur ein Zeichen.

    Sicher kompliziert.

    t6


    Grüße Sandra
    Donnerstag, 9. März 2017 17:22
  • Hallo Sandra,

    wenn man die XML-Attribute mit dem XmlReader ausliest, werden die "&#x23" bereits automatisch in das entsprechende Zeichen umgewandelt.

    XmlReader reader = XmlReader.Create(@"d:\VS Community 2017\MyProjects\Test\ConsoleApp1\ConsoleApp1.xml");
    string val;
    
    while (reader.Read())
    {
    	if (reader.NodeType == XmlNodeType.Element && reader.Name == "Project")
    		val = reader.GetAttribute("smth");
    }

    Attribut smth enthält in der XML-Datei: "Inhalt&#x0D;&#x0A;&#x002D;&#x011C;Test&#x0023;".

    val enthält nach Aufruf von Reader.GetAttribute(): "Inhalt
    -ĜTest#"

    Es ist wichtig, daß die Inhalte in der XML-Datei gültige UTF-8-Zeichen enthalten, bzw. die &#x...; gültigen UTF-8-Zeichen entsprechen. Sie müssen dem Encoding entsprechen, das in <?xml version="1.0" encoding="utf-8"?> angegeben ist.

    Gruß
    Heiko

    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Donnerstag, 9. März 2017 19:41
  • Hallo Sandra,

    am grundlegenden Vorgehen ändert sich da nichts. Du hast die Zahl als String vorliegen und könntest diese in einen Integer umwanden und diesen wiederum in ein char casten.

    Ich habe es nicht überprüft, aber die Vorgefertigtn XML-Klassen etc. werden das wohl genauso handhaben.


    Viele Grüße, Tom Lambert - MVP, MCC und MSP
    Wozu Antworten markieren und Posts bewerten? Klicke hier
    Nützliche Links: .NET Quellcode | C#/VB.NET Konverter | GitHub Forum Samples | Account bestätigen (Verify Your Account)
    Ich: Webseite | Facebook | Twitter | Code Snippets | GitHub

    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Freitag, 10. März 2017 00:45
    Moderator
  • Hallo Zusammen,

     reader.GetAttribute("smth");
     Attribut smth enthält in der XML-Datei: "Inhalt&#x0D;&#x0A;&#x002D;&#x011C;Test&#x0023"
     
     val = "Inhalt&#x0D;&#x0A;&#x002D;&#x011C;Test&#x0023"


     D.h., wenn ich das auslese steht in val das obige drin.
     Dann müsste ich das in ein ByteArray wandeln.
     Damit &#x0A; zu char(10) wieder wird.
     
     Quatsch, der Reader stellt das ja schon sicher, richtig?
     
     Ich muss es 'nur' und 'nur' über einen XMLReader laufen lassen, nicht direkt einlesen.
     
    Grüße Sandra
    Samstag, 11. März 2017 11:39
  • Ja ;) probier es mal aus.
    • Als Antwort markiert Sandra Bauer Sonntag, 12. März 2017 15:17
    Sonntag, 12. März 2017 12:23
  • Hallo,
    prinzipiell passt ja alles.
    <book author="j.k.rowling&#xD;&#x2;&#x3;" year="1990">99</book>
    Die Frage kam auf, warum ich das nicht so
    <book author="j.k.rowling&#13;&#02;&#03;" year="1990">99</book>
    abspeichere, also dez.

    Das liegt einfach an der Spezifikation von XML, dem ist doch so?

    Viele Grüße Sandra

    private byte[] StringToByteArray(string str)
    {
    	System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    	return enc.GetBytes(str);
    }
    
    private string ByteArrayToString(byte[] arr)
    {
    	System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    	return enc.GetString(arr);
    }
    
    private void frmExclusiv_Load(object sender, EventArgs e)
    {
    
    	XmlWriterSettings settings = new XmlWriterSettings();
    	settings.Indent = true;
    	settings.IndentChars = "     "; // note: default is two spaces
    	settings.NewLineOnAttributes = false;
    	settings.OmitXmlDeclaration = true;
    	settings.CheckCharacters = false;
    	settings.Encoding = new UTF8Encoding(true);
    	
    	using (XmlWriter writer = XmlWriter.Create("books.xml", settings))
    	{
    
    		writer.WriteStartElement("book");
    		string t1 = "j.k.rowling" + "\x0D" + "\x02" + (char)3;
    		writer.WriteAttributeString("author", t1 );
    		writer.WriteAttributeString("year", "1990");
    		writer.WriteString("99");
    		writer.WriteEndElement();
    
    	}
    
    	XmlReaderSettings settingsReader = new XmlReaderSettings();
    	settingsReader.CheckCharacters = false;
      
    
    	XmlReader reader = XmlReader.Create(@"books.xml", settingsReader);
    	string val;
    
    	while (reader.Read())
    	{
    		if (reader.NodeType == XmlNodeType.Element && reader.Name == "book")
    		{
    			val = reader.GetAttribute("author");
    			byte[] array = StringToByteArray(val);
    		}
    	}
    

    Dienstag, 14. März 2017 17:48
  • Hallo Sandra,

    ob in der XML-Datei die Zeichen hex oder dezimal stehen, macht für den XmlReader keinen Unterschied. Ich habe keine Stelle gefunden, wo man das einstellen könnte. Möchtest du sie dezimal schrieben, könnte man dies mit WriteRaw() realisieren:

    	writer.WriteStartElement("book");
    
    //	string t1 = "j.k.rowling" + "\x0D" + "\x02" + (char)3;
    	string t1 = "j.k.rowling" + "&#13;&#2;&#3;";
    
    //	writer.WriteAttributeString("author", t1 );
    	writer.WriteStartAttribute("author");
    	writer.WriteRaw(t1);
    	writer.WriteEndAttribute();
    
    	writer.WriteAttributeString("year", "1990");
    	writer.WriteString("99");
    	writer.WriteEndElement();

    Falls noch beliebige andere Sonderzeichen vorkommen, könnte man sich eine Umwandlungsmethode dafür schreiben (ähnlich wie weiter oben im Thread).

    Möchtest du wirklich \x02 und (char)3 (was dasselbe wie \x03 ist) schreiben? Falls du ein # meinst, nimm \x23 bzw. "&#x23;" oder "&#35;".

    Gruß
    Heiko

    Mittwoch, 15. März 2017 12:31
  • Hallo Heiko,
    ich will es nicht, die andere Seite (Kunde)gibt mir die andere Formatierung.
    Da kam dann die Frage auf, warum? Vermutlich weil die es evtl. mit HTML Tools schreiben.
    Beide Seiten müssen es halt richtig interpretieren.
    Mal sehen was kommende Woche folgt.
    Vorerst mal dann ausreichend.
    Grüße Sandra
    Mittwoch, 15. März 2017 17:48