IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

Incoherence StreamWriter et System.Text.Encoding.Default [Débutant]


Sujet :

VB.NET

  1. #1
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut Incoherence StreamWriter et System.Text.Encoding.Default
    Bonsoir à tous,
    J'ai encore un petit soucis :
    J'arrive à lire correctement un fichier texte à partir du StreamReader et du système d'encodage par défaut (voir code Lecture).
    et lorsque j'écrit à partir du StreamWriter (voir code Ecriture) celui-ci encode systématiquement mon fichier en utf8, et bien sûre lorsque je veux le relire il ne s'affiche plus correctement.
    Je sais initialiser un StreamWriter en spécifiant un système d'encodage mais comment se fait t'il que le StreamWriter s'initialise en utf-8 ? (qui est le système d'encodage par défaut du StreamWriter) alors que Encoding.Défaut est dans un autre format ? (j'aimerais bien savoir à quoi correspond cet encodage par défaut d'ailleurs), pourquoi cette incohérence ?

    Code Lecture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim sr As StreamReader = New StreamReader("path", System.Text.Encoding.Default)
    Code Ecriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim sw As New StreamWriter("path")
    Merci beaucoup pour votre réponse.

  2. #2
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 742
    Points
    9 742
    Billets dans le blog
    3
    Par défaut
    Il n'est pas recommandé d'utiliser Encoding.Default, même si au premier abord, ca semble logique. Les raisons principales sont listées ici : Don't Use Encoding.Default. En voici quelques unes traduites :

    Citation Envoyé par Shawn Steele
    Encoding.Default retourne la page de code définie sur l'OS. Si quelqu'un change cette page, ou si les données sont partagées entre différentes machines qui utilisent différentes pages de code, le décodage ne fonctionnera pas. Si vous utilisez des langages latins vous ne vous en rendrez probablement pas compte, mais les problèmes apparaitront dès que vous commencerez à penser global : vous pourrez alors voir des bugs quelque peu étranges.

    Puisque Encoding.Default peut changer selon la machine utilisée, les utilisateurs peuvent rencontrer des difficultés pour envoyer des fichiers ou parce que des fichiers sont corrompus. En réalité ils ne le sont pas, il s'agit juste d'une mauvaise utilisation d'Encoding pour les décoder.

    Encoding.Default fournit une page de code "ANSI", qui ne supporte qu'une toute petite partie des caractères en Unicode, particulièrement pour les langues utilisation un simple byte comme celles utilisées aux US. Cela signifie que les utilisateurs peuvent entrer des caractères qui seront traduits par "?" ou qui causeront une exception.

    Encoding.Default ne fournit aucune information à propos de l'encodage. Si vous l'utilisez, il est nécessaire d'implémenter une sorte de protocole de haut niveau pour déclarer explicitement quel est l'Encoding utilisé. Certains encodages comme UTF-8 ou UTF-16 permettent d'inclure un byte (BOM) qui peut être utilisé comme une signature afin d'être certain de l'encodage à utiliser.
    Bref voilà, en gros il ne faut pas utiliser Encoding.Default mais lui préférer un Encodage explicite. Donc dans ton cas, il vaut mieux initialiser ton StreamReader avec Encoding.UTF8 par exemple. Tu peux aussi vérifier si ton fichier contient un BOM pour savoir avec précision comment initialiser ton StreamReader.

    Si le BOM est présent, la doc MSDN (StreamReader Constructor (String, Encoding)) précise que l'encodage sera automatiquement défini :
    Citation Envoyé par MSDN
    The StreamReader object attempts to detect the encoding by looking at the first three bytes of the stream. It automatically recognizes UTF-8, little-endian Unicode, and big-endian Unicode text if the file starts with the appropriate byte order marks. Otherwise, the user-provided encoding is used.
    Pour réaliser cette détection, ils utilisent la méthode Encoding.GetPreamble.

  3. #3
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Merci beaucoup pour la réponse,

    Donc si je comprends bien on est jamais vraiment sûre du système d'encodage utilisé. Il faut que je regarde ça de plus prêt en faisant des essais ce soir.
    Le truc c'est que je souhaite écrire exactement dans le même format d'encodage que le fichier que je charge dans le StreamReader.
    Je verrais si une propriété du StreamReader peux indiquer le système d'encodage après avoir chargé le fichier plutôt que le spécifier moi-même. Si ça fonctionne je n’aurais plus qu'à écrire dans ce format avec le StreamWriter.

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 742
    Points
    9 742
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par BasicZX81 Voir le message
    Donc si je comprends bien on est jamais vraiment sûre du système d'encodage utilisé. Il faut que je regarde ça de plus prêt en faisant des essais ce soir.
    Exactement.

    Citation Envoyé par BasicZX81 Voir le message
    Le truc c'est que je souhaite écrire exactement dans le même format d'encodage que le fichier que je charge dans le StreamReader.
    Je verrais si une propriété du StreamReader peux indiquer le système d'encodage après avoir chargé le fichier plutôt que le spécifier moi-même. Si ça fonctionne je n’aurais plus qu'à écrire dans ce format avec le StreamWriter.
    Ok comme je l'ai dit dans ma réponse, si le fichier original utiliser certains encodages ET contient un BOM (ce n'est pas toujours le cas, on peut faire de l'UTF-8 avec ou sans BOM...), le StreamReader va déterminer tout seul quel est l'encodage à utiliser. S'il n'est pas capable de déterminer tout seul lequel utiliser, alors il va utiliser celui que tu lui indiques dans le constructeur.

    Si tu souhaites toi-même réaliser cette détection, regarde le dernier lien de mon message précédent (vers la méthode Encoding.GetPreamble).

  5. #5
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Merci DotNetMatt,
    Je m'attendais à pouvoir gérer ce système en automatique et en effet ça ne sera pas possible pour un bon nombre de fichier (ANSI, ASCII et autre fichier sans BOM).
    Le plus raisonnable est de le gérer à la demande en manuel.

  6. #6
    Expert confirmé
    Avatar de Kropernic
    Homme Profil pro
    Analyste / Programmeur / DBA
    Inscrit en
    Juillet 2006
    Messages
    3 932
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Belgique

    Informations professionnelles :
    Activité : Analyste / Programmeur / DBA
    Secteur : Distribution

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 932
    Points : 4 242
    Points
    4 242
    Par défaut
    Hello,

    Cette problématique pourrait m'intéresser dans un futur proche.

    Comment, s'il n'y pas de BOM (et donc pas de détection automatique du format par le streamreader), détecter nous même le format d'encodage du fichier ?

    Est-ce disponible dans une propriété de la classe IO.FileInfo ?

    Quid du format lorsqu'on utilise IO.File.ReadAllLines(path As String) à la place d'un IO.StreamReader ?

  7. #7
    Membre émérite Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528

  8. #8
    Membre averti
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2012
    Messages
    640
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Bâtiment

    Informations forums :
    Inscription : Mars 2012
    Messages : 640
    Points : 372
    Points
    372
    Par défaut
    Bonjour,
    J'ai trouvé ce bout de code si ça peut aider car ça m'interresse aussi. Désolé c'est du C#.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    using System.Text;
    using System.IO;
     
    ....
     
    /// <summary>
    /// Permet de tester l'encodage utilisé pour le fichier texte dont le chemin est fourni
    /// </summary>
    /// <param name="CheminFichier">Chemin du fichier</param>
    /// <returns>Encodage du fichier Texte</returns>
    private Encoding ObtientENcoding(string CheminFichier)
    {
     Encoding enc = null;
     FileStream file = new FileStream(CheminFichier, FileMode.Open, FileAccess.Read, FileShare.Read
     if (file.CanSeek)
     {
      byte[] bom = new byte[4]; // Get the byte-order mark, if there is one
      file.Read(bom, 0, 4);
      if (bom[0] == 0xef && bom[1] == 0xbb && bom[2] == 0xbf) // utf-8
      {
       enc = Encoding.UTF8;
      }
      else if ((bom[0] == 0xff && bom[1] == 0xfe) || // ucs-2le, ucs-4le, and ucs-16le
       (bom[0] == 0 && bom[1] == 0 && bom[2] == 0xfe && bom[3] == 0xff)) // ucs-4
      {
       enc = Encoding.Unicode;
      }
      else if (bom[0] == 0xfe && bom[1] == 0xff) // utf-16 and ucs-2
      {
       enc = Encoding.BigEndianUnicode;
      }
      else // ANSI, Default
      {
       enc = Encoding.Default;
      }
      // Now reposition the file cursor back to the start of the file
      file.Seek(0, SeekOrigin.Begin);
     }
     else
     {
      // The file cannot be randomly accessed, so you need to decide what to set the default to
      // based on the data provided. If you're expecting data from a lot of older applications,
      // default your encoding to Encoding.ASCII. If you're expecting data from a lot of newer
      // applications, default your encoding to Encoding.Unicode. Also, since binary files are
      // single byte-based, so you will want to use Encoding.ASCII, even though you'll probably
      // never need to use the encoding then since the Encoding classes are really meant to get
      // strings from the byte array that is the file.
     
      enc = Encoding.Default;
     }
    return enc;
    }

  9. #9
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 742
    Points
    9 742
    Billets dans le blog
    3
    Par défaut
    Ici il y a une implémentation qui semble pas mal pour réaliser cette détection : Detect Encoding for In- and Outgoing Text.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Delphi 2009, UNICODE et system.text
    Par stgarp dans le forum Débuter
    Réponses: 2
    Dernier message: 14/11/2008, 15h09
  2. Créer un fichier texte encodé en UTF8
    Par jmnicolas dans le forum Entrée/Sortie
    Réponses: 5
    Dernier message: 26/08/2008, 11h23
  3. Condition d'utilisation du type de fichier system.Text
    Par Alain B. dans le forum Langage
    Réponses: 5
    Dernier message: 16/06/2008, 18h55
  4. Créer un fichier Texte encodé en UFT8 ?
    Par lbgl dans le forum C++
    Réponses: 5
    Dernier message: 17/12/2007, 16h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo