piège (non)-binaire

Le
Méta-MCI \(MVP\)
Bonjour !

Considérez le code suivant (sous un Windows-Vista en français) :

tt="aabb"
for c in tt: print ord(c),
print
open("toto",'w').write(tt)

t=open("toto",'r').read()
for c in t: print ord(c),
print

Il affiche ça :
> 97 97 13 10 98 98
> 97 97 13 10 98 98

Mais, en réalité, le fichier "toto" contient :
97 97 13 13 10 98 98 00 (visualisé avec un éditeur binaire)


Autrement dit, les ont été remplacés par des


Solution : ouvrir le fichier en binaire, comme ça :
open("toto",'wb').write(tt)

ce petit 'b' supplémentaire évite quelques interventions intempestives
de Python. Je ne comprenais plus pourquoi certaines pages HTML étaient
de plus en plus espacées, à chaque modification, et, après avoir galéré
quelques temps avec cp1252, utf-8, utf-16, les locales, je me suis
brusquement rappelé ça


@-salutations
--
Michel Claveau
Questions / Réponses high-tech
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Eric Brunel
Le #676315
On Wed, 23 Jan 2008 15:59:48 +0100, Méta-MCI (MVP)

Bonjour !

Considérez le code suivant (sous un Windows-Vista en français) :

tt="aarnbb"
for c in tt: print ord(c),
print
open("toto",'w').write(tt)

t=open("toto",'r').read()
for c in t: print ord(c),
print

Il affiche ça :
97 97 13 10 98 98
97 97 13 10 98 98


Mais, en réalité, le fichier "toto" contient :
97 97 13 13 10 98 98 00 (visualisé avec un éditeur binaire)


Autrement dit, les rn ont été remplacés par des rrn


Plus exactement, les n ont été remplacés par des rn, et ce pour
respecter les conventions de fins de ligne Windows. En C comme en Python,
la convention pour terminer une ligne, c'est n, et rien de plus. Ca
assure la portabilité du code entre les plateformes.

Solution : ouvrir le fichier en binaire, comme ça :
open("toto",'wb').write(tt)

ce petit 'b' supplémentaire évite quelques interventions intempestives
de Python.


Ca n'a rien à voir avec Python: c'est la libc qui fait ça. Python ne fait
que l'appeler... Si tu fais exactement le même programme en C, ça donnera
exactement le même résultat...

A noter par ailleurs que, toujours pour des questions de portabilité, le
mode binaire est également supporté sous Unix, mais vu que la convention
de fin de ligne est la même que celle de C ou Python, ce mode n'a en fait
aucun impact.

HTH
--
python -c "print ''.join([chr(154 - ord(c)) for c in
'U(17zX(%,5.zmz5(17l8(%,5.Z*(93-965$l7+-'])"


Méta-MCI (MVP)
Le #676010
Bonsoir !

les n ont été remplacés par des rn, et ce pour respecter les
conventions de fins de ligne Windows.


Ok ; mais, il y a un problème, dans cette histoire de "respect des
conventions de fins de ligne" :
- soit la chaine "aarnbb" située dans un fichier.
- si on la (lit + écrit) 10 fois la chaîne dans un fichier, on
obtient, à la fin : "aarrrrrrrrrrrnbb"
Ce qui est pour le moins curieux, comme respect...

Et puis, remplacer un (saut-de-ligne) par (retour-chariot +
saut-de-ligne) cela me semble douteux. Parce que, cela empêche
d'utiliser le retour-chariot seul, pour superposer des lignes. (Cette
technique était utilisée, par exemple, dans la petite animation des
réseaux NetWare, la "ligne qui tourne").

@+

Michel Claveau

NicolasP
Le #676009
Bonsoir !

les n ont été remplacés par des rn, et ce pour respecter les
conventions de fins de ligne Windows.


Ok ; mais, il y a un problème, dans cette histoire de "respect des
conventions de fins de ligne" :
- soit la chaine "aarnbb" située dans un fichier.
- si on la (lit + écrit) 10 fois la chaîne dans un fichier, on
obtient, à la fin : "aarrrrrrrrrrrnbb"
Ce qui est pour le moins curieux, comme respect...
C'est vrai si tu lis le fichier en mode binaire et que tu l'écrit en mode texte.

Si tu lis le fichier en mode texte, pas de problème.


Et puis, remplacer un (saut-de-ligne) par (retour-chariot +
saut-de-ligne) cela me semble douteux.
Peut-être mais sous Windows, tous les Windows, et même DOS (chez Microsoft en fait), c'est comme ça.


Pour résumer, une fin de ligne c'est :
Microsoft : rn
Apple : r
Unix : n

Python a un mode "universal read line" pour gérer tous les types de retour ligne (pas essayé).

Parce que, cela empêche
d'utiliser le retour-chariot seul, pour superposer des lignes. (Cette
technique était utilisée, par exemple, dans la petite animation des
réseaux NetWare, la "ligne qui tourne").
Pas de problème :

r permet de revenir en début de ligne.
n permet de sauter une ligne ET de revenir en début de ligne.


Nicolas


Mihamina Rakotomandimby
Le #676008
Méta-MCI (MVP) wrote:
d'utiliser le retour-chariot seul, pour superposer des lignes. (Cette
technique était utilisée, par exemple, dans la petite animation des
réseaux NetWare, la "ligne qui tourne").


Dans n'importe quelle application qui a une barre de progression et/ou
un affichage de taux de progression aussi, non?
Ah, oui! C'est vrai tu es sous Windows, c'est beaucoup plus féquent sous
Linux et autres Unices.

Pierre Maurette
Le #676006

[...]

J'ai été confronté à un "bug" marrant. Pour écrire des plugins en
Python pour OOo, on place un .py dans (sur m machine XP):
C:Documents and SettingsNomUtilisateurApplication
DataOpenOffice.org2userScriptspython
Ce fichier est parsé à la recherche d'un:
g_exportedScripts = [fonctions]
ou je crois en son absence à la recherche des fonctions directement.

Or, pas moyen sous XP, avec Eclipse + Pydev, de créer un tel fichier,
aucune fonction n'apparaissait dans lanceur de scripts. Il fallait
impérativement dupliquer un fichier "qui marche", installé avec OOo,
quitte à en effacer entièrement le contenu. Aujourd'hui, je ne
comprends pas que l'explication ne m'est pas sauté aux yeux, à ce
moment-là j'étais pressé et j'ai utilisé la solution du fichier
dupliqué. Et puis c'est reparti en galère, suite je crois à une reprise
du fichier par PSPad. Et là je me suis intéressé au problème et suis
assez vite arrivé à l'explication, somme toute évidente.

Eclipse crée ses fichier au format de fin de ligne de la plateforme. En
revanche, en bon outil orienté vers le multiplateforme, il conserve
celui des fichiers existants. On pourrait d'ailleurs envisager une
création systématique au format Unix, ça ne pose aucun problème sous
Windows, en revanche je ne sais pas pour MacOS.

Et bien évidemment le parseur d'OOo doit être programmé un peu "léger",
et attend un format Unix. A vrai dire autant je simule mentalement le
bug inverse, autant dans ce sens je ne vois pas trop. C'est peut-être
d'ailleurs un problème Java, je suis crade dans ce langage, peu
importe.

A partir de là, je me suis fait un outil qui sur un fichier ou une
arborescence, avec filtres, analyse, convertit et corrige plusieurs
souci de cet ordre. Les doubles sauts de ligne également, qui doivent
venir de copié-collé à partir d'internet. J'ai certainement réinventé
la roue, en fait. Vous avez d'ailleurs un
PythonDirToolsScriptscrlf.py dans les distributions Python.

Extrait de mon script:

"""
Rappels:

Caractères:

n hexa: 0A
decimal: 10
ASCII: LF (LineFeed, saut de ligne)
r hexa: 0D
decimal: 13
ASCII: CR (Carriage Return, retour à la ligne)

Fins de lignes:

DOS/WINDOWS: rn 0D0A CRLF
UNIX: n 0A LF
MAC OS: r AD CR

"""

--
Pierre Maurette
NicolasP
Le #676005

[...]

J'ai été confronté à un "bug" marrant. Pour écrire des plugins en Python
pour OOo, on place un .py dans (sur m machine XP):
C:Documents and SettingsNomUtilisateurApplication
DataOpenOffice.org2userScriptspython
Ce fichier est parsé à la recherche d'un:
g_exportedScripts = [fonctions]
ou je crois en son absence à la recherche des fonctions directement.

Or, pas moyen sous XP, avec Eclipse + Pydev, de créer un tel fichier,
aucune fonction n'apparaissait dans lanceur de scripts. Il fallait
impérativement dupliquer un fichier "qui marche", installé avec OOo,
quitte à en effacer entièrement le contenu. Aujourd'hui, je ne comprends
pas que l'explication ne m'est pas sauté aux yeux, à ce moment-là
j'étais pressé et j'ai utilisé la solution du fichier dupliqué. Et puis
c'est reparti en galère, suite je crois à une reprise du fichier par
PSPad. Et là je me suis intéressé au problème et suis assez vite arrivé
à l'explication, somme toute évidente.

Eclipse crée ses fichier au format de fin de ligne de la plateforme. En
revanche, en bon outil orienté vers le multiplateforme, il conserve
celui des fichiers existants. On pourrait d'ailleurs envisager une
création systématique au format Unix, ça ne pose aucun problème sous
Windows, en revanche je ne sais pas pour MacOS.

Et bien évidemment le parseur d'OOo doit être programmé un peu "léger",
et attend un format Unix. A vrai dire autant je simule mentalement le
bug inverse, autant dans ce sens je ne vois pas trop. C'est peut-être
d'ailleurs un problème Java, je suis crade dans ce langage, peu importe.

A partir de là, je me suis fait un outil qui sur un fichier ou une
arborescence, avec filtres, analyse, convertit et corrige plusieurs
souci de cet ordre. Les doubles sauts de ligne également, qui doivent
venir de copié-collé à partir d'internet. J'ai certainement réinventé la
roue, en fait. Vous avez d'ailleurs un PythonDirToolsScriptscrlf.py
dans les distributions Python.

Extrait de mon script:

"""
Rappels:

Caractères:

n hexa: 0A
decimal: 10
ASCII: LF (LineFeed, saut de ligne)
r hexa: 0D
decimal: 13
ASCII: CR (Carriage Return, retour à la ligne)

Fins de lignes:

DOS/WINDOWS: rn 0D0A CRLF
UNIX: n 0A LF
MAC OS: r AD CR

"""



Et n'oublions pas de sur Eclipse, on peut choisir le type de fins de lignes :
File/Convert Line Delimiters To/...

Nicolas

Pierre Maurette
Le #676004

[...]

Et n'oublions pas de sur Eclipse, on peut choisir le type de fins de lignes :
File/Convert Line Delimiters To/...


Merci, je ne l'avais pas vu. Pas beaucoup cherché, à vrai dire, et
plutôt une option globale, dans l'usine à gaz:
Window/Preferences

Sinon, PSPAd est puissant sur ces sujets, mais avec une ergonomie un
peu étrange.

--
Pierre Maurette

Publicité
Poster une réponse
Anonyme