2010-04-07 24 views
15

Wysyłane są pliki tekstowe zapisane w formacie ISO 88591-1, które zawierają znaki akcentowane z zakresu Latin-1 (jak również jako normalny ASCII az itd.). Jak przekonwertować te pliki na UTF-8 używając C#, aby jednobajtowe znaki akcentowane w ISO 8859-1 stały się poprawnymi znakami UTF-8?Korzystanie z platformy .NET do konwersji plików tekstowych zakodowanych w ISO 8859-1 zawierających znaki akcentowane Latin-1 do UTF-8

Próbowałem użyć StreamReader z ASCIIEncoding, a następnie przekształcając ciąg ASCII na UTF-8 przez instancji kodowanie ascii i kodowanie utf8 a następnie za pomocą Encoding.Convert(ascii, utf8, ascii.GetBytes(asciiString)) — ale akcentowane znaki są renderowane jako znaki zapytania.

Jakiego kroku brakuje?

+0

Czy próbowali za pomocą StreamWriter z kodowaniem UTF8 napisać asciiString zewnątrz do plik tekstowy? Czy to się dzieje? – Task

+0

@Task: Jego problemem jest to, że nigdy nie wyciąga łańcucha z 8859-1, nie, że nie może go zapisać w UTF-8. –

+0

Och, to całkowicie jego problem, bez wątpienia. Po prostu łatwiej jest debugować konwersję tekstu za pomocą pary StreamReader/StreamWriter (dzięki czemu mogę zobaczyć pliki wejściowe/wyjściowe), a nie za pomocą wywołania Encoding.Convert. To może być tylko ja. – Task

Odpowiedz

32

Musisz uzyskać odpowiedni obiekt Encoding. ASCII ma taką samą nazwę: ASCII, co oznacza, że ​​obsługuje tylko 7-bitowe znaki ASCII. Jeśli chcesz konwertować pliki, najprawdopodobniej jest to łatwiejsze niż radzenie sobie bezpośrednio z tablicami bajtów.

using (System.IO.StreamReader reader = new System.IO.StreamReader(fileName, 
             Encoding.GetEncoding("iso-8859-1"))) 
{ 
    using (System.IO.StreamWriter writer = new System.IO.StreamWriter(
              outFileName, Encoding.UTF8)) 
    { 
     writer.Write(reader.ReadToEnd()); 
    } 
} 

Jednak jeśli chcesz mieć tablic bajtowych się, że to dość łatwe do zrobienia z Encoding.Convert.

byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), 
    Encoding.UTF8, data); 

Ważne jest, aby pamiętać, tutaj jednak, że jeśli chcesz iść tą drogą to należy nie użyć czytnika ciąg kodowania opartego jak StreamReader dla pliku IO. FileStream byłby lepiej dopasowany, ponieważ będzie czytał rzeczywiste bajty plików.

W interesie pełni odkrywania problem, coś jak to będzie działać:

using (System.IO.FileStream input = new System.IO.FileStream(fileName, 
            System.IO.FileMode.Open, 
            System.IO.FileAccess.Read)) 
{ 
    byte[] buffer = new byte[input.Length]; 

    int readLength = 0; 

    while (readLength < buffer.Length) 
     readLength += input.Read(buffer, readLength, buffer.Length - readLength); 

    byte[] converted = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), 
         Encoding.UTF8, buffer); 

    using (System.IO.FileStream output = new System.IO.FileStream(outFileName, 
             System.IO.FileMode.Create, 
             System.IO.FileAccess.Write)) 
    { 
     output.Write(converted, 0, converted.Length); 
    } 
} 

W tym przykładzie zmienna buffer zostanie wypełniona rzeczywistych danych w pliku jako byte[], więc konwersja nie jest Gotowe. Encoding.Convert określa kodowanie źródłowe i docelowe, a następnie przechowuje przeliczone bajty w zmiennej o nazwie ... converted. To jest następnie zapisywane bezpośrednio w pliku wyjściowym.

Tak jak powiedziałem, pierwsza opcja z użyciem StreamReader i StreamWriter będzie znacznie prostsza, jeśli to wszystko, co robisz, ale ten drugi przykład powinien dać ci więcej wskazówek, co się właściwie dzieje.

+0

dziękuję wszystkim za pomoc i esp @Adam za jego dokładną odpowiedź – Tim

10

Jeśli pliki są stosunkowo małe (powiedzmy ~ 10 MB), trzeba tylko dwie linie kodu:

string txt = System.IO.File.ReadAllText(inpPath, Encoding.GetEncoding("iso-8859-1")); 
    System.IO.File.WriteAllText(outPath, txt); 
+0

pracował dla mnie .. –

+0

Dla mnie również. – Cheloide