Dopo essermi
cimentato con caratteri unicode (Cinese, Giapponese e Coreano) a livello di database,
riuscendo a leggere, scrivere e garantendo il round-trip tra diverse
applicazioni e middelware, mi son trovato a dover leggere e scrivere stream files:
scambiare con applicazioni windows i dati presenti sul database.
La sfida dunque era esportare dati verso un file di
testo (.txt .csv) in modalità Unicode, Big Endian Unicode o UTF-8, leggere files analoghi (risultanti da
upload effettuati dall’estero), capire come riconoscere il loro formato ed
importarli in tabelle.
Windows
fornisce il supporto ai formati unicode (la Fig. 1 mostra le opzioni di salvataggio di
Notepad); vediamo in dettaglio i diversi formati supportati
ANSI - non è unicode, rappresenta il character set ASCII
Unicode / Big-endian Unicode - Quando un carattere
occupa più di un byte può essere scritto in due modalità, dipendente
dall’architettura della macchina; col
termine Unicode Windows intende una codifica a 2 byte (quindi l’equivalente di
UCS-2 o UTF-16), differenziando (BE, LE) la posizione dei 2 byte occorrenti
all’identificazione di un carattere
UTF-8 - Questo Encoding prevede l’utilizzo di uno, due o più byte
dipendentemente dal carattere: sono i primi bit del primo carattere che ne
determinano la lunghezza. E’ quindi un sistema ottimizzato per occupare poco
spazio (solo quello che serve) a discapito delle prestazioni.
Vediamo ora
come viene occupata la memoria per scrivere la stringa “CINA” nei diversi Encoding:
Su system-i
è possibile attribuire ad una singola colonna di tabella un determinato CCSID
che determina l’encoding usato; questa caratteristica permette quindi al
sistema di conoscere e trattare opportunamente le informazioni; nella figura un
esempio dei CCSID corrispondenti ad alcuni Encoding.
è necessario quindi, per i file di testo (e per tutti i
flussi non caratterizzati implicitamente da un CCSID) un ulteriore metodo per riconoscere l’Encoding
usato, per preservare quindi le applicazioni legacy e permettere un corretto
uso di unicode.
BOM
Scriviamo ora un file nell’ IFS
Alla luce di quanto detto
risulta estremamente semplice scrivere uno streamfile con formato UTF-8 nell’
integrated file system di system-i.
Per prima cosa occorre creare un file vuoto con la
giusta codepage:
D LogFile
S 640a
D flags
S 10u 0
D mode
S 10u 0
D fd S 10i 0
D codepage
S 10u 0
D O_WRONLY
C 2
D O_CREAT C 8
D O_TRUNC C 64
D O_RDONLY C 1
D O_RDWR C 4
D O_APPEND C 256
D O_CODEPAGE C 8388608
LogFile = '/Temp/testUTF8.txt';
flags =
O_RDONLY;
if open(%trim(LogFile):flags: mode)<0;
// il file NON
Esiste, lo creo
flags = O_CREAT + O_RDWR + O_CODEPAGE + O_TRUNC ;
mode = S_IRUSR + S_IWUSR +
S_IRGRP + S_IROTH;
codepage =
819;
fd =
open(%trim(LogFile):flags: mode: codepage);
// open
Output.
if fd >=
0;
fclose(fd);
endif;
endif;
ora aggiungiamo il BOM
dell’UTF-8, per far riconoscere l’encoding usato a windows
D BOM
S 3a inz(x'EFBBBF')
flags
= O_APPEND + O_RDWR;
mode =
S_IRUSR + S_IWUSR + S_IRGRP +
S_IROTH;
fd = open(%trim(LogFile):flags: mode);
if fd >= 0;
// write to
stream file
fwrite(fd:
%addr(BOM): 3); // per UTF-8: Byte Order
Mark
fclose(fd);
endif;
Prepariamo
un campo unicode direttamente; possiamo usare la bif %UCS2 per convertire una
stringa SBCS in un campo Unicode oppure la notazione U’xxxx’ per generare
valori unicode:
D
Message2 S 10000C
Message2
=%ucs2('[')+U'4E2D56FD' +%ucs2(']')
+U'000D000A';
In questo esempio
viene generata la stringa [中国] seguita da CR+LF (0D16 e 0A16
che nella codifica a 2 byte diventano U’000D’ e U’000A’)
Va ora considerato che un campo Unicode, un campo di
tipo C nelle D-spec, è un campo con CCSID 13488 quindi UCS-2; serve ora
convertirlo in UTF-8; la strada più semplice è quella di usare una funzione del
sistema: iconv() che, a fronte di una stringa di input, ccsid di partenza e di
arrivo, genera una stringa di output; questa funzione è stata incapsulata in
una subprocedure; in questo caso passiamo alla funzione iconv la stringa da
convertire, la sua lunghezza, il suo CCSID (13488) e il CCSID nel quale
vogliamo venga restituita la stringa calcolata (1208 = UTF-8):
D Ou
S 10000a
fd = open(%trim(LogFile):flags: mode);
if fd >= 0;
Ou = my_iconv(Message2:%len(%trim(Message2)):13488:1208);
fwrite(fd:
%addr(Ou): %len(%trim(Ou)));
fclose(fd);
endif;
alla stregua di questo si può leggere una tabella
codificata in Unicode per scrivere il suo contenuto nello streamfile:
for $ii=1 to 10;
read MyFile;
if %eof;
leave;
endif;
fd =
open(%trim(LogFile):flags: mode);
if fd >=
0;
Message2 =
%ucs2(%trim(MyField))
+ U'000D000A';
Ou = my_iconv
(Message2:
%len(%trim(Message2)):
13488:
1208);
fwrite(fd:
%addr(Ou): %len(%trim(Ou)));
fclose(fd);
endif;
endfor;
Verifichiamo ora se tutto ha funzionato come
desiderato: dobbiamo verificare il CCSID del file che abbiamo appena generato,
la corretta scrittura del BOM e la sua leggibilità da parte di un’applicazione
windows.
Col comando WRKLNK navighiamo nell’IFS e troviamo il
nostro file:
Con l’opzione 8=Attributi verifichiamo il CCSID e con
EDTF in modalità HEX verifichiamo il BOM:
Esportiamo ora il file su un client Windows (si può
usare qualsiasi sistema, da iSeriesNavigator a FTP o da SharedFolders).
Apriamo il file con Notepad, dovremmo vedere questo
contenuto:
Se
lanciamo il comando [Salva con nome…] notepad visualizza la modalità di
salvataggio corrispondente all’Encoding corrente, nel nostro caso UTF-8
Nessun commento:
Posta un commento