Ich benutze den EncodingHelper, den ich hier gefunden (und ausgebessert) habe: EncodingHelper, Encoding zur Laufzeit auslesen
Nun versuch ich einen Unit-Test zu bauen, der das ganze überprüft:
[TestMethod(true)]
public bool FileEncodingTest(TestContext testContext)
{
string testFile = "test.txt";
Encoding[] encodings = new Encoding[] { Encoding.ASCII };
foreach (Encoding enc in encodings)
{
CreateTestFile(testFile, enc);
testContext.WriteLine("Try to detect Encoding " + enc.ToString() + " is Codepage :" + enc.CodePage.ToString());
Assert.AreEqual(enc.CodePage, Active.Utilities.EncodingHelper.GetFileEncoding(testFile).CodePage);
File.Delete(testFile);
testContext.WriteLine("Successfully detected Encoding " + enc.ToString());
}
return true;
}
private static void CreateTestFile(string path, Encoding encoding)
{
StreamWriter sw = new StreamWriter(path, false, encoding);
sw.WriteLine("Encoding-Übernahme Test");
sw.Close();
}
Ich hab dabei jetzt das Problem, dass das Encoding.ASCII gar nicht mehr erkannt wird, da wie's scheint, die Datei gar nicht in diesem Encoding geschrieben würde. Beim Einlesen kriegt der EncodingHelper nur mehr: Encoding-?bernahme Test, obwohl auch mit Encoding.ASCII eingelesen wird.
Ich hab die Datei mit VS2005 aufgemacht und wenn ich mir dort die Erweiterten Speicheroptionen anschaue, meint VS, dass die Datei in 1252-Codierung gespeichert wurde.
Wo liegt der Fehler, was muss ich anders machen? Bzw. liegt das evtl. am NTFS-Format?
Hallo tkrasinger,
Encoding.ASCII ist fast nie, was man will, weil es nur 7-bit-ASCII ist und somit überhaupt keine Umlaute kennt. Meistens wird Encoding.Default das Gewünschte sein.
herbivore
Es geht hier nicht ums "wollen". Es geht darum den Encoding-Helper zu testen. Dazu will ich eine Datei in .ASCII schreiben und der Helper soll für diese Datei auch .ASCII liefern. Der Helper soll ja dann global zur Verfügung stehen.
(Ich verwende sowieso keine Encoding sondern verlass mich aufs Default-Encoding.)
Hallo tkrasinger,
in deiner Datei kommen doch aber Umlaute vor oder nicht. Und wenn das der Fall ist, dass ist die Codierung eben nicht Encoding.ASCII. Entsprechend ist es korrekt, wenn der Helper nicht Encoding.ASCII ausgibt.
Andersherum ist Encoding.ASCII ein echtes Subset von Encoding.Default und es wäre somit nicht unkorrekt, wenn der Helper eine reine 7-bit-ASCII-Datei als Encoding.Default erkennen würde.
Wie in dem anderen Thread steht, gibt es ohnehin keine Methode mit 100%iger Sicherheit das verwendete Encoding zu ermitteln.
herbivore
Um eine ASCII-Datei zu erkennen, prüfstdu ob jedes Byte (nicht Char!) kleiner als 128 ist. Alles was größer ist, ist kein ASCII, sondern Codepage XYZ oder Unicode
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hm, also einfach gesagt, kann ich ASCII gar nicht erkennen, weil es keinen erkennbaren Unterschied gibt.
Die Dateien sind auch komplett gleich, egal ob ich ASCII oder .Default nehme.
Hallo tkrasinger,
Die Dateien sind auch komplett gleich, egal ob ich ASCII oder .Default nehme.
nicht ganz!
Wenn eine Datei zwar mit Encoding.Default geschrieben wurde, aber keine Zeichen mit Codes größer 127 enthält, dann kannst du in der Tat nicht erkennen, dass beim Schreiben Encoding.Default verwendet wurde. Es kann auch sein, dass Encoding.ASCII verwendet wurde. Und es kommen noch sehr viele andere Encodings in Frage, weil die meisten (8-bit-)Encodings bezüglich der Zeichen mit Codes kleiner 128 gleich definiert sind.
Du kannst natürlich sagen, dass - wie kleines_eichhoernchen vorgeschlagen hat - eine Datei, die keine Zeichen mit Codes größer 127 enthält, per Definition als Encoding.ASCII angesehen wird.
Andersherum ist es so, dass eine Datei, die Zeichen mit Codes größer 127 enthält, kein Encoding.ASCII sein kann.
herbivore
Um eine ASCII-Datei zu erkennen, prüfstdu ob jedes Byte (nicht Char!) kleiner als 128 ist. Alles was größer ist, ist kein ASCII, sondern Codepage XYZ oder Unicode
Hm, wenn ich einen Byte-Code > 128 kann ich bloß sagen, dass es keine ASCII-Datei sein kann. Im Gegensatz kann ich aber nicht sagen, dass es eine ASCII-Datei sein muss, wenn kein Byte über 128 ist. Kann ja sein, dass gar kein Zeichen > 128 vorkommt.
Also wenn ich meinen Test-Text z.b. auf "ABC123abc" ändere, kann ich irgendwie gar nicht mehr feststellen, wie was geschrieben wurde, nur mehr, wie ichs einlesen kann.
Also arbeitet der EncodingHelper korrekt, nur meinen Unit-Test kann ich so nicht durchführen.
Was mich stört ist, dass der StreamWriter bei einer 7-Bit-Codierung keinen Fehler ausgibt, wenn ich ein 8-bit-Zeichen schreibe.
Hallo tkrasinger,
richtig, wie schon gesagt, gibt es eben keine sichere Methode aus dem Inhalt einer Datei auf das Encoding zu schliefen. Du könntest aber, wie ebenfalls schon gesagt, eine Datei, die keine Zeichen mit Codes größer 127 enthält, per Definition als Encoding.ASCII angesehen.
herbivore
Also arbeitet der EncodingHelper korrekt
Das ist wenn dann Zufall. Kann mir nicht vorstellen, dass ich ASCII mit bedacht habe. Wüsste auch nicht warum man ASCII heutzutage noch verwenden soll. Außerdem ist es wie Herbivore schon sagt, völlig Wurst, wenn deine Datei im reinen ASCII vorliegt und du diese mit Codepage XYZ öffnest oder sogar UTF8 (ohne BOM) sollte möglich sein.
Nur bei Zeichen die größer oder gleich 128 sind musst du prüfen, welche Codepage oder UTF8 verwendet wurde.
Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...
Hallo tkrasinger,
Was mich stört ist, dass der StreamWriter bei einer 7-Bit-Codierung keinen Fehler ausgibt, wenn ich ein 8-bit-Zeichen schreibe.
wenn du mit StreamWriter einen C# String schreibst, weiß der Strings nichts von 7- oder 8-bit, sondern ein C# String liegt immer als 16bit Unicode vor. Insofern können in einem C# String auch jede Menge Zeichen enthalten sein, die nicht mal in 8-bit passen. Deshalb ist die Devise von StringWriter immer das beste draus zu machen, also die im C# String enthaltenen Zeichen auf das passendste Zeichen im Ziel-Encoding abzubilden. Und wenn es partout kein passendes Zeichen gibt, dann wird meistens das Fragezeichen verwendet.
Wenn du willst, dass alle Zeichen sauber codiert werden können und das Fragezeichen nicht ins Spiel kommt, dann musst du als Ziel-Encoding ein Unicode-Encoding angeben, also z.B. Unicode (UTF-16), UTF7, UTF8.
herbivore