Page 1 sur 1

Fichier IFS - UTF-16

Posté : mar. 27 nov. 2018, 09:35:47
par Ponpon
Bonjour,

je rencontre une problématique d'encodage au niveau d'un fichier CSV que je crée et alimente dans l'IFS.

Le client exige que les données soient en UTF-16. J'ai utilisé plusieurs méthodes pour convertir les données (API iconv, fonction %ucs2, fonction disponible sur le dépôt github FrenchIBMi etc.) mais à chaque fois le client me dit que cela n'est pas bon. J'arrive correctement à visualiser le contenu par une session 5250 mais c'est illisible une fois téléchargé sur un environnement Windows.

En utilisant Notepad++ pour obtenir les informations d'encodage, j'obtiens ceci comme informations :
-pour un fichier type que le client a envoyé : Windows (CR LF) et UCS-2 LE BOM. Le fichier se lit correctement.
-pour un fichier que je génère et que je tente de transformer avec les méthodes cité plus haut : Macintosh (CR) et ANSI. Le fichier est illisible, avec plusieurs caractères NUL, EOT, SYN etc.

Auriez-vous une idée du problème ?

Merci d'avance.

Re: Fichier IFS - UTF-16

Posté : mar. 27 nov. 2018, 11:10:49
par vazymimil
Bonjour,

comment transférez-vous le fichier produit vers le client, selon la méthode il peur y avoir conversion de caractère pendant le transfert, par exemple si vous déposer le fichier par FTP chez votre client pour être certain qu'il voit le fichier tel que vous l'avez produit il faut faire un transfert binaire.

(sujet inconnu)

Posté : mar. 27 nov. 2018, 11:50:56
par Ponpon
Bonjour,

je transmet le fichier au client par mail via la commande SNDSMTPEMM. Je rencontre le même problème sur mon poste lorsque je récupère le fichier par ACS ou FTP en mode binaire.

En complément d'information, voici le code source généré, qui utilise les API "standard" de manipulation de fichier

Code : Tout sélectionner

dcl-s chaine varchar(999999) inz;
dcl-s chaineUCS2 ucs2(999999) inz ccsid(1200);

fd=open(nomFichier:O_CREAT+O_WRONLY+O_CCSID:0:1252);
chaineUCS2=%ucs2(%trim(chaine));
callp write(fd: %addr(chaineUCS2):%len(%trimr(chaineUCS2))*2);
callp close(fd);


(sujet inconnu)

Posté : mar. 27 nov. 2018, 14:31:56
par vazymimil
Je pense qu'il faudrait utiliser
open(nomFichier:O_CREAT+O_WRONLY+O_CCSID:0:1200);
pour que le fichier soit créé avec le CCSID 1200 même s'il n'y a pas de conversion (il faut supprimer le fichier pour être sûr s'il existe déjà)

et ajouter un write(fd:x'FFFE':2); avant l'écriture des données qui est le BOM UTF-16BE qui va indiquer à Windows que les données qui suivent sont en UTF-16 big endian (cad le CCSID 1200)

est-ce que ça fonctionne comme ça ?

(sujet inconnu)

Posté : mar. 27 nov. 2018, 15:12:53
par Ponpon
Il y a du progrès !!

C'est une méthode que j'avais auparavant utilisé mais abandonné pour la raison suivante : au niveau des informations renvoyés par Notepad++, je suis bien en Windows (CR LF) et UCS-2 LE BOM. En revanche, si je le consulte dans un environnement Windows (récupéré par transfert FTP en mode binaire), le document est composé de caractères type chinois...

Il ne doit pas manquer grand chose mais quoi ?

Re: (sujet inconnu)

Posté : mar. 27 nov. 2018, 16:05:12
par vazymimil
Oui je me suis trompé, c'est X'FEFF' qu'il faut mettre

(sujet inconnu)

Posté : mar. 27 nov. 2018, 17:21:35
par Ponpon
En modifiant le BOM, le fichier est correctement lisible par Windows. La seule différence c'est que le fichier semble être en UCS-2 BE BOM (et non LE BOM).

Si je remets le BOM FFFE, le fichier devient de nouveau illisible.

J'espère que le client ne sera pas trop exigeant de ce côté là...

Je vous tiens au courant.

Re: (sujet inconnu)

Posté : mar. 27 nov. 2018, 17:54:35
par vazymimil
S'il est exigeant il faudra mettre le BOM UTF16-LE et inverser les octets de deux par deux dans chaineUCS2, je pense que ça devrait suffire

(sujet inconnu)

Posté : mer. 28 nov. 2018, 09:56:42
par Ponpon
vazymimil YOU ARE MY STAR !!!!

Le client a validé le nouveau format de fichier. Il ne manquait pas grand chose finalement.

Merci beaucoup pour votre aide.

Par contre votre dernière remarque a éveillé ma curiosité :
il faudra mettre le BOM UTF16-LE et inverser les octets de deux par deux dans chaineUCS2
Comment procéder de la sorte ?

Re: (sujet inconnu)

Posté : mer. 28 nov. 2018, 12:13:35
par vazymimil
En fait il y a une api pour ça :QlgTransformUCSData

un exemple:

dcl-pr QlgTransformUCSData int(10) extproc(*dclcase);
xformtype int(10) value;
inbuf pointer;
inbytesleft uns(10);
outbuf pointer;
outbytesleft uns(10);
outspacereq uns(10);
end-pr;

dcl-s donneesUTF16LE char(%size(chaineucs2));

dcl-s ret like(QlgTransformUCSData);
dcl-s p_inbuf pointer;
dcl-s inbytesleft uns(10);
dcl-s p_outbuf pointer;
dcl-s outbytesleft uns(10);
dcl-s outspacereq uns(10);

p_inbuf = %addr(chaineUCS2);
inbytesleft = %len(chaineUCS2) * 2;
p_outbuf = %addr(donneesUTF16LE);
outbytesleft = %size(donneesUTF16LE);

ret = QlgTransformUCSData(040052:p_inbuf:inbytesleft:p_outbuf:outbytesleft:outspacereq);
if ret <> 0;
dsply %char(ret);
endif;