Finde den Fehler - Windoof, VB oder ich?

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von TheBlackSnitter.

    Finde den Fehler - Windoof, VB oder ich?

    Hallo leute =)

    Ich glaube ich habe gerade das mit abstand besste geschafft, was ich an einem Windoof-PC je zustande gebracht habe.

    also entweder hat windows gefailt und denselben ASCII-Code doppelt belegt - oder VB hat da ne macke (ist ja einerlei - kommt beides vom Microsoft =))


    Also hier: dieses zeichen "Ǿ"
    hat laut meinem Programm den ASCII-Code 63

    Aber wenn man den ASCII-Code 63 wieder zu einem Char macht (ChrW(63))
    dann sagt mir vb eindeutig, dass der Code 63 dem "?" entspricht.


    EDIT: Also hat schonmal was mit der codierung ANSI / Unicode zu tun...

    und noch eine interessante sache: wenn man die buchstaben "fzp" in ASCII-Code übersetzt kommt dabei "102 122 112" heraus.
    wenn man jetzt die erste und die letzte ziffer jedes bytes tauscht -> "201 221 211"
    und das ganze wieder umwandelt erhält man: "ÉÝÓ"

    Schreibt man das in eine Textdatei und speichert es, liest diese datei anschließend mit einem Programm aus und wandelt die ausgelesenen bytes wieder in ASCII-Code um, so erhält man: "ÉÝÓ"

    und wenn man sich den code genau anschaut sieht man, dass er so aussieht: "195 137 195 157 195 147"
    137 = ‰
    157 = 
    147 = “
    warum wird dieser nicht so anezeigt?

    Packt man "ÉÝÓ" das in eine Datei und zerlegt das in bytes erhält man: "239 187 191 195 131 194 137 195 131 194 157 195 131 194 147"
    wenn man das allerdings wieder zurückverwandelt, d.h. in Char -> "ÉÝÓ"

    also ich frage mich jetzt ersnthaft, ob windows mich hier verarschen will und ob das nur mein windows macht - oder passiert das bei euch auch? gibt es bekannte doppelbelegungen "Ǿ = ?" ?

    könnt ihr dem vielleicht irgendein system entnehmen? als mir kommt das vor, als wäre da eine random-variable dabei^^


    wer mir dazu was erklären kann bekommt ein dickes DANKE!


    MfG KnifeHunter

    btw: spielt mal ein bisschen mit ChrW(), IO.File.ReadAllBytes und meiner hier aufgeführten bescheibung herum.
    würde mich interessieren, ob es bei euch auch so ist.


    EDIT: Hat auf jeden fall etwas mit der textcodierung ANSI / Unicode zu tun...
    Du hast ein Unicode-Zeichen (meinetwegen Ǿ). Das speicherst du in eine Datei (ergibt 2 Byte - [C7 BE]). Dann liest du alle Bytes der Datei einzeln ein und konvertierst jedes einzelne Byte mit ChrW in je ein Unicode-Zeichen. Demnach hast du jetzt zwei Zeichen, nämlich ChrW(&HC7) = [C3 87] und ChrW(&HBE) = [irgendwas]. Bei Wiederholung kommen natürlich immer mehr Zeichen dazu.

    Das Problem liegt also hier: "ÉÝÓ" besteht nicht aus Zeichen, die im "alten" ASCII-Zeichensatz enthalten sind (der geht von 0 bis 127, = ASCII 7 Bit), und werden mit 2 Byte codiert (ChrW(201) = [C3 89]). Die Datei enthält dann 6 Byte (3 Unicode-Zeichen á 2 Byte), was deinen 6 Buchstaben (Ã, ‰, Ã, , Ã, “) entspricht, wenn du die Datei mit ASCII-Codierung ausliest.

    Ist eigentlich einfach zu merken: 1 Unicode-Zeichen = 2 Byte, 1 ASCII-Zeichen = 1 Byte. Speicherst du nun als Unicode und liest als ASCII, verdoppeln sich bei jeder Wiederholung dieser prozedur alle Zeichen in der Datei.
    Gruß
    hal2000

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „hal2000“ ()

    In einem Zeichensatz kann es zu keinen Doppelbelegungen kommen. Im ASCII-Zeichensatz wird jedes Zeichen mithilfe einer 7-Bit großen Zahl gespeichert.
    63 bzw. &H3F steht im ASCII-Zeichensatz eindeutig für das Fragezeichen.

    Man sollte aber bedenken, dass Strings in VB.Net nicht im ASCII-Zeichensatz gespeichert werden, sondern im Unicode-Zeichensatz. Hier werden dann auch keine 7, sondern 16-Bit zur Darstellung eines Zeichens verwendet.

    Du hast vielleicht bei deinen Konvertierungen verschiedene Zeichensätze verwendet. Ich verwende zum Konvertieren von Bytes in Strings und umgekehrt immer diese Methode für verschiedene Zeichensätze.

    VB.NET-Quellcode

    1. System.Text.Encoding.ASCII.GetBytes("Bsp.")
    2. System.Text.Encoding.ASCII.GetString(Buffer)

    Damit hatte ich bis jetzt noch nie Probleme. Außer natürlich, wenn ich eben versucht habe, Bytes die z. B. für UTF-8 Zeichen stehen als ASCII Zeichen zu behandeln. Das ist mir einmal passiert, weil eine Datei in verschiedenen "Bereichen" verschiedene Zeichensätze verwendet hat.

    Welcher Zeichensatz bei Chr/ChrW verwendet wird, kannst du hier nachlesen: msdn.microsoft.com/en-us/library/613dxh46(v=vs.71).aspx
    Allerdings würde ich von dieser Funktion zugunsten von Convert.ToChar abraten.

    EDIT: Beim Testen ist mir gerade eine sehr seltsame Eigenschaft von VB aufgefallen. Folgender Code führt in VB zu einem Fehler:

    VB.NET-Quellcode

    1. Dim Zeilenumbruch As Char = DirectCast(13, Char)

    In C# funktioniert er allerdings wunderbar (natürlich die C# Version davon):

    VB.NET-Quellcode

    1. char Zeilenumbruch = (char)13;

    Wenn man den Reflektor verwendet, sieht man auch, dass die Funktion ToChar des Frameworks selbst so funktioniert.

    Nochmal EDIT: Der Threadersteller hat zwar den Thread als erledigt markiert, aber ich bin eben vorhin beim Testen auch noch auf diese Frage gestoßen und es wäre nett wenn ihr trotzdem noch antworten würdet.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Infinity“ ()

    Infinity schrieb:

    sehr seltsame Eigenschaft von VB

    Das ist so in Ordnung. Lies dazu über den Unterschied zwischen DirectCast, CType und Convert.ToX() nach. Achtung: Darüber kursieren viele falsche Informationen im Netz. Der wichtigste Unterschied ist, dass DirectCast eine Vererbungsbeziehung braucht, um ein Objekt umzuwandeln, wärend CType (sofern passend überladen) auch Daten konvertieren / uminterpretieren kann.
    Gruß
    hal2000
    vb-magazin.de/forums/blogs/jan…ive/2008/03/06/15535.aspx
    In diesem Artikel steht, dass der VB Code

    VB.NET-Quellcode

    1. Dim Zeilenumbruch As Char = DirectCast(13, Char)

    und der C# Code

    VB.NET-Quellcode

    1. char Zeilenumbruch = (char)13;

    identisch sind.
    Deswegen meine Frage, wieso es dann unter VB nicht funktioniert und unter C# schon.
    (die Methode Convert.ToChar() aus dem Framework selbst verwendet so einen Cast laut Reflector)

    Und irgendwie wiederspricht sich die Aussage aus dem Artikel auch mit der von MSDN, dass CType inlinie kompiliert wird und dabei keine Prozedur aufgerufen wird:
    msdn.microsoft.com/en-us/library/4x2877xb(v=vs.71).aspx
    Versuchst du, die Zahl 13 in einen Char zu pressen, oder das 13. Ascii-Zeichen rauszukriegen?

    In diesem Artikel steht, dass der VB Code ... identisch sind.
    Wo steht diese Zeile? Ich finde sie nicht.
    Sowohl die VS-IDE als auch der C#-to-VB-Converter bieten die richtige Lösung an.

    VB.NET-Quellcode

    1. Dim Zeilenumbruch As Char = ChrW(13)


    Der Artikel aus deinem zweiten Link ist einige Tage alt. Hier hat sich inzwischen was getan.
    Dieser Code ist nur ein Beispiel. Ich versuche das 13. ASCII-Zeichen rauszukriegen (was in C# mit (char)13 ganz einfach funktioniert).

    Wo steht diese Zeile? Ich finde sie nicht.

    Das steht hier:

    VBs DirectCast ist ein "pures" Casting, es findet also keine Umwandlung statt, und damit ist es equivalent mit dem C# Cast.
    VB
    Dim p As Person = DirectCast(o, Person)
    C#
    1 Person p = (Person)o;


    Aber "Equivalent" habe mit "identisch" falsch interpretiert. Der C#-Cast mit der Klammer und die DirectCast-Funktion in VB sind verschieden nach der Definition von hal2000 der DirectCast-Funktion, nämlich dass sie eine Vererbungsbeziehung benötigt. Das ist bei dem C#-Klammer-Cast nicht der Fall. Möchte man (uint)0.34F in VB übersetzen benötigt man ja beispielsweise auch die CType-Funktion, weil die DirectCast-Funktion ja eine Vererbungsbeziehung benötigt. CType ist allerdings auch nicht identisch mit dem C#-Klammer-Cast. Eigentlich schade, dass es keine einheitliche Übersetzung für den C#-Klammer-Cast gibt.

    Sowohl die VS-IDE als auch der C#-to-VB-Converter bieten die richtige Lösung an.

    Natürlich, aber darum geht es ja nicht. Die ChrW-Funktion ist mir bekannt. Wobei diese ja wieder zu den "bösen" VB-6-Funktionen gehört und deshalb die Convert.ToChar-Funktion besser ist (siehe weiter unten). Die Convert.ToChar-Funktion setzt selbst diesen merkwürdigen Cast ein für den es in VB keine Entsprechung gibt außer die ChrW-Funktion. Eigentlich läuft es bei den meisten Convert.To*-Funktionen auf einen simplen Cast heraus, wenn man sie sich im Reflector anschaut sieht man es z. B. Convert.ToUInt32:

    VB.NET-Quellcode

    1. 'Orginal Quelltext aus dem Reflector (Version 6.8.2.5; Ansicht: Visual Basic)
    2. Public Shared Function ToUInt32(ByVal value As Integer) As UInt32
    3. If (value < 0) Then
    4. Throw New OverflowException(Environment.GetResourceString("Overflow_UInt32"))
    5. End If
    6. Return DirectCast(value, UInt32)
    7. End Function

    Hier liefert der Reflector scheinbar falschen Code, denn statt dem DirectCast müsste ein CType stehen. Also wie auch der VB-Quellcode den der Reflector für die Convert.ToChar-Funktion liefert nicht kompilierbar.

    Laut Reflector schaut die ChrW-Funktion so aus:

    VB.NET-Quellcode

    1. Public Shared Function [ChrW](ByVal CharCode As Integer) As Char
    2. If ((CharCode < -32768) OrElse (CharCode > &HFFFF)) Then
    3. Throw New ArgumentException(Utils.GetResourceString("Argument_RangeTwoBytes1", New String() { "CharCode" }))
    4. End If
    5. Return Convert.ToChar(CInt((CharCode And &HFFFF)))
    6. End Function

    Es wird also letztlich auch nur wieder die Convert.ToChar-Funktion aufgerufen.

    Aber du hast natürlich recht, der Artikel den ich gefunden habe ist wahrscheinlich veraltet und muss auch nicht stimmen.

    Infinity schrieb:

    Dim p As Person = DirectCast(o, Person)
    Person p = (Person)o;

    Diese Zeile habe ich gefunden, und diese passt ja auch.

    Nur ist 13 in einen Char umgewandelt kein Zeilenumbruch.
    Andere Frage: Was ergibt 8, wenn man es in einen Char CASTET? Den Character "8", oder doch das Backspace? Einer von uns Beiden hat hier einen Denkfehler.
    Public Shared Function [ChrW](ByVal CharCode As Integer) As Char


    Infinity schrieb:

    Wobei diese ja wieder zu den "bösen" VB-6-Funktionen gehört

    Was ich von "bösen" Funktionen halte, steht in meiner Signatur (-->Brotschneiden). Wobei aber nicht jede VB6-Funktion alt (=überholt) ist, und viele der Funktionen auch intern von VB verwendet werden.
    Andere Frage: Was ergibt 8, wenn man es in einen Char CASTET? Den Character "8", oder doch das Backspace? Einer von uns Beiden hat hier einen Denkfehler.

    Ich habe es getestet (unter C# und unter VB mit Convert.ToString).
    Ein Caste/Aufruf der ToChar-Funktion/Aufruf der ChrW-Funktion ergibt z. B. 8 ein Backspace. Um den Char "8"c zu erhalten, müsste man erst in String konvertieren und dann z. B. mit CChr nach Char konvertieren.

    Und zu den bösen VB-Funktionen: Im Grunde hast du recht, aber im Falle von ChrW ist es sinnvoller direkt Convert.ToChar aufzurufen, denn ChrW verwendet ja auch wieder nur Convert.ToChar und der direkte Weg ist meistens der beste.

    Ach ja 13 steht in Unicode (was ja das Framework und auch insbesondere die Char-Klasse verwendet) für ein Return. 10 steht für einen Zeilenumbruch. Beides würde z. B. in einer Messagebox zu einem Zeilenumbruch führen.
    vbNewLine ist z. B. so (laut Reflector) definiert:

    VB.NET-Quellcode

    1. Public Const vbNewLine As String = ChrW(13) & ChrW(10)

    bzw.

    VB.NET-Quellcode

    1. public const string vbNewLine = "\r\n";


    EDIT: Mir fällt auf, dass die Funktion ChrW scheinbar in VB Literalstatus hat. Sonst würde das Definieren der Konstante auf diese Weise fehlschlagen. Der Reflector gibt auch wenn die Konstante vbNewLine verwendet wird direkt "ChrW(13) & ChrW(10)" zurück und wenn man die Ansicht auf C# stellt erhält man auch direkt "\r\n". Ich schätze aufgrund des Literalstatus ist die ChrW-Funktion doch besser als Convert.ToChar.
    Aber das ganze ist schon sehr komplex, wenn man genauer hinschaut. Was ich aber trotzdem noch seltsam finde ist, dass man die ChrW-Funktion auch mit dem Reflector im VisualBasic-Namespace findet und auch dekompilieren kann, denn es ist ja scheinbar eine Literalschreibweise.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Infinity“ ()

    Der C#-Cast () ist identisch mit CType, denn beide tun folgendes:

    http://msdn.microsoft.com/en-us/library/0z4503sa%28v=vs.80%29.aspx schrieb:

    A cast explicitly invokes the conversion operator from one type to another; the cast will fail if no such conversion operator is defined.


    Auch interessant: msdn.microsoft.com/en-us/library/8s682k58%28v=vs.80%29.aspx

    CType ist vielseitig - es gibt 3 Möglichkeiten:
    1. Wird in einen impliziten Cast ersetzt (bei Vererbungsbeziehung, = DirectCast)
    2. Ruft eine benutzerdefinierte Überladung auf
    3. Ruft Convert.ToXXX auf.

    DirectCast arbeitet wie 1.

    Sehr aufschlussreich sind die MSDN-Seiten zu DirectCast und CType.
    Gruß
    hal2000
    Hay, habe noch eine Frage ^^

    Wie kann man jetzt ein schon gespeichertes Dokument welches Zeichen wie "" enthält wieder in Klartext umwandeln ?
    Habe das noch nicht ganz verstanden mit dem Wald der 1000 deklarationen :P

    mfg TBS
    Ich hab heute meiner Katze beim spielen
    zugesehen, sie ist die ganze Zeit einem Ball nachgejagt und ich hab mir
    überlegt, das Tier ist echt mit sehr einfachen Dingen zu begeistern...
    Dann ist mir aufgefallen, dass ich 10 Minuten nur meine Katze
    angestarrt habe.
    Wie kann man jetzt ein schon gespeichertes Dokument welches Zeichen wie "" enthält wieder in Klartext umwandeln ?
    Habe das noch nicht ganz verstanden mit dem Wald der 1000 deklarationen :P
    vlt. Begriffe klären.
    "gespeichertes Dokument" - ich nehme an, du meinst eine Text-Datei?

    Dann meinst du sicherlich nicht umwandeln, denn nach der Umwandlung wäres u.U. keine Text-Datei mehr.

    Also Textdateien kannman einlesen, vorzugsweise mit einem StreamReader, weil der wandelt die Byte-Folge gleich in einen String um (bei zeilenweisem Einlesen in mehrere Strings).

    Für diese Umwandlung verwendete der StreamReader einen Umwandlungs-Algorithmus - deshalb muß man ihm ein Encoding-Objekt mitgeben (ansonsten nimmter einfach Encoding.Utf8)

    Nun liegt der Text als String vor, und bei chinesisch oder russisch kann das immer noch unleserlich sein, weil die haben ja annere Buchstaben als unsereiner. Also zB. ein Label kann einen String nur dann korrekt darstellen, wenn es bei der richtigen Darstelllung auch den passenden Font benutzt - meinst du das mit "Klartext"?
    "gespeichertes Dokument" - ich nehme an, du meinst eine Text-Datei?

    True

    Dann meinst du sicherlich nicht umwandeln, denn nach der Umwandlung wäres u.U. keine Text-Datei mehr.
    True

    Also Textdateien kannman einlesen, vorzugsweise mit einem StreamReader,
    weil der wandelt die Byte-Folge gleich in einen String um (bei
    zeilenweisem Einlesen in mehrere Strings).
    Habe ich.

    Für diese Umwandlung verwendete der StreamReader einen
    Umwandlungs-Algorithmus - deshalb muß man ihm ein Encoding-Objekt
    mitgeben (ansonsten nimmter einfach Encoding.Utf8)
    Habe ich, ich habe alle Encoding-Objekte versucht, aber es kommt kein richtiges Ergebniss. Selbst bei "Detect-Encoding" ging es nicht.



    Nun liegt der Text als String vor, und bei chinesisch oder russisch kann
    das immer noch unleserlich sein, weil die haben ja annere Buchstaben
    als unsereiner. Also zB. ein Label kann einen String nur dann korrekt
    darstellen, wenn es bei der richtigen Darstelllung auch den passenden
    Font benutzt
    Ausländisch ist es auf keinen Fall.

    meinst du das mit "Klartext"?
    True

    Msg TBS
    Ich hab heute meiner Katze beim spielen
    zugesehen, sie ist die ganze Zeit einem Ball nachgejagt und ich hab mir
    überlegt, das Tier ist echt mit sehr einfachen Dingen zu begeistern...
    Dann ist mir aufgefallen, dass ich 10 Minuten nur meine Katze
    angestarrt habe.
    Default auch.

    Zerstört kann sie nicht sein, da sie von einem anderen Programm verwendet wird.

    mfg TBS
    Ich hab heute meiner Katze beim spielen
    zugesehen, sie ist die ganze Zeit einem Ball nachgejagt und ich hab mir
    überlegt, das Tier ist echt mit sehr einfachen Dingen zu begeistern...
    Dann ist mir aufgefallen, dass ich 10 Minuten nur meine Katze
    angestarrt habe.
    Wer hat die Datei erstellt? Nur wenn du weißt wie sie erstellt wurde, dann kannst du herausfinden, wie sie zu lesen ist. Ok man kann natürlich auch herumprobieren (was aber mühsam sein kann) oder sich die Spezifikation des Dateiformats anschauen (wenn vorhanden). Es kann z. B. auch möglich sein, dass die Datei keinen reinen Text enthält, sondern die Daten auch stellenweise z. B. als UInteger zu interpretieren sind (wobei es sich dann nicht mehr um eine klassische Textdatei handelt). Manchmal ist es auch so, dass die Datei mehrere Zeichensätze verwendet. Das ist z. B. bei MP4-Dateien der Fall. Hier wird grundsätzlich ASCII verwendet, aber die Tagwerte sind UTF-8. Ich habe deswegen hier auch schon einmal einen Thread erstellt ([VB.NET] Welchen Zeichensatz verwendet die Datei?).

    Noch einmal zum Literalstatus der ChrW-Funktion in VB:
    Sie erhält diesen Status nur dann, wenn auch ein konstanter Wert übergeben wird (macht ja auch Sinn). Wenn nicht, dann wird sie als normale Funktion aufgerufen, dh. sie gibt die Arbeit nur an die Convert.ToChar-Funktion weiter (mit Reflector analysiert, auch die IL-Ansicht ist dabei ganz interessant). Die kann ich natürlich auch selber aufrufen. Deshalb: Wenn man einen konstanten Wert konvertieren will ChrW nehmen, bei einem variablen Wert Convert.ToChar nehmen.
    Kommt ihr zum gleichen Schluss? Vielleicht werde ich das Ganze auch einmal mit einem simplen Geschwindigkeitstest überprüfen, wenn ich Zeit habe.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Infinity“ ()

    Ein Spiel hat die Datei erstellt und enthält Einstellungsdaten. Ich habe herumprobiert, aber warum zum Hänker sollte man eine solche Datei mit einer so hohen Priorität belegen. Es muss etwas einfaches sein, aber ich bin immernochnicht dahinter gestiegen. Es ist das Dateiformat SAV welches ich schon nachgiebig gegoogelt hab. Aber leider verwenden viele Programme/Spiele diese Endung. Ich denke es gibt eine simple Lösung, die ich noch nicht herausgefunden habe ^^

    mfg TBS
    Ich hab heute meiner Katze beim spielen
    zugesehen, sie ist die ganze Zeit einem Ball nachgejagt und ich hab mir
    überlegt, das Tier ist echt mit sehr einfachen Dingen zu begeistern...
    Dann ist mir aufgefallen, dass ich 10 Minuten nur meine Katze
    angestarrt habe.
    Wird wohl auf das Glücksrad hinaus laufen, die meisten Spielehersteller bieten keine Spezifikation ihres Savegame-Formats an (was auch bei jedem Spiel unterschiedlich ist, nur die Endung .sav wird evtl. von mehreren Spielen verwendet). Hier heißt es dann wirklich herumprobieren und die Datei mit einem Hexeditor zu analysieren.
    Um welches Spiel geht es denn? Wenn es in Java oder einer .Net-Sprache geschrieben ist, kannst du es evtl. dekompilieren und so herausfinden, wie die Dateien geschrieben werden (ist aber evtl. auch verboten).