J'ai besoin d'écrire un utilitaire 'simple' pour convertir de ASCII en EBCDIC?
L'Ascii vient de Java, Web et passe à un AS400. J'ai eu un google autour, ne semble pas pouvoir trouver une solution facile (peut-être parce qu'il n'y en a pas un :(). J'espérais un utilitaire opensource ou payé pour un util déjà écrit.
Comme ça peut-être?
Converter.convertToAscii(String textFromAS400)
Converter.convertToEBCDIC(String textFromJava)
Merci,
Scott
JTOpen , la version Open Source d’IBM de leur boîte à outils Java contient un ensemble de classes permettant d’accéder aux objets AS/400, notamment FileReader et FileWriter pour accéder aux fichiers texte AS400 natifs. Cela peut être plus facile à utiliser que d’écrire vos propres classes de conversion.
De la page d'accueil JTOpen:
Voici quelques-unes des nombreuses ressources i5/OS et OS/400 auxquelles vous pouvez accéder à l'aide de JTOpen:
- Base de données - JDBC (SQL) et accès au niveau de l'enregistrement (DDM)
- Système de fichiers intégré
- Appels de programme
- Les commandes
- Files d'attente de données
- Zones de données
- Ressources d'impression/spoule
- Informations sur le produit et le PTF
- Travaux et journaux de travail
- Messages, files de messages, fichiers de messages
- Utilisateurs et groupes
- Espaces utilisateur
- Valeurs du système
- État du système
Veuillez noter qu'une chaîne en Java contient du texte dans le codage natif de Java. Si vous tenez en mémoire une "chaîne" ASCII ou EBCDIC, avant de l'encoder sous forme de chaîne, vous la trouverez sous la forme d'un octet [].
ASCII -> Java: nouvelle chaîne (octets, "ASCII") EBCDIC -> Java: nouvelle chaîne (octets, "Cp1047") Java -> ASCII: chaîne. getBytes ("ASCII") Java -> EBCDIC: string.getBytes ("Cp1047")
package javaapplication1;
import Java.nio.ByteBuffer;
import Java.nio.CharBuffer;
import Java.nio.charset.CharacterCodingException;
import Java.nio.charset.Charset;
import Java.nio.charset.CharsetDecoder;
import Java.nio.charset.CharsetEncoder;
public class ConvertBetweenCharacterSetEncodingsWithCharBuffer {
public static void main(String[] args) {
//String cadena = "@@@@@@@@@@@@@@@ñâæÃÈÄóöó@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÔÁâãÅÙÃÁÙÄ@ÄÅÂÉã@âæÉãÃÈ@@@@@@@@";
String cadena = "ñâæÃÈÄóöó";
System.out.println(Convert(cadena,"CP1047","ISO-8859-1"));
cadena = "1SWCHD363";
System.out.println(Convert(cadena,"ISO-8859-1","CP1047"));
}
public static String Convert (String strToConvert,String in, String out){
try {
Charset charset_in = Charset.forName(out);
Charset charset_out = Charset.forName(in);
CharsetDecoder decoder = charset_out.newDecoder();
CharsetEncoder encoder = charset_in.newEncoder();
CharBuffer uCharBuffer = CharBuffer.wrap(strToConvert);
ByteBuffer bbuf = encoder.encode(uCharBuffer);
CharBuffer cbuf = decoder.decode(bbuf);
String s = cbuf.toString();
//System.out.println("Original String is: " + s);
return s;
} catch (CharacterCodingException e) {
//System.out.println("Character Coding Error: " + e.getMessage());
return "";
}
}
}
Vous devez utiliser le jeu de caractères Java Cp1047 (Java 5) ou Cp500 (JDK 1.3+).
Utilisez le constructeur String: String(byte[] bytes, [int offset, int length,] String enc)
Je crée un code qui transforme facilement les types de données.
public class Converter{
public static void main(String[] args) {
Charset charsetEBCDIC = Charset.forName("CP037");
Charset charsetACSII = Charset.forName("US-ASCII");
String ebcdic = "(((((((";
System.out.println("String EBCDIC: " + ebcdic);
System.out.println("String converted to ASCII: " + convertTO(ebcdic, charsetEBCDIC, charsetACSII));
String ascII = "MMMMMM";
System.out.println("String ASCII: " + ascII);
System.out.println("String converted to EBCDIC: " + convertTO(ascII, charsetACSII, charsetEBCDIC));
}
public static String convertTO(String dados, Charset encondingFrom, Charset encondingTo) {
return new String(dados.getBytes(encondingFrom), encondingTo);
}
}
Vous pouvez en créer un vous-même avec cette table de traduction .
Mais ici est un site qui contient un lien vers un exemple Java.
C'est ce que j'ai utilisé.
public static final int[] ebc2asc = new int[256];
public static final int[] asc2ebc = new int[256];
static
{
byte[] values = new byte[256];
for (int i = 0; i < 256; i++)
values[i] = (byte) i;
try
{
String s = new String (values, "CP1047");
char[] chars = s.toCharArray ();
for (int i = 0; i < 256; i++)
{
int val = chars[i];
ebc2asc[i] = val;
asc2ebc[val] = i;
}
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace ();
}
}
Peut-être que comme moi vous n'utilisiez pas strictement une fonctionnalité JDBC (écriture dans une file de données, dans mon cas), de sorte que l'encodage auto-magical ne s'appliquait pas à vous puisque nous communiquions via plusieurs API.
Mon problème était similaire au problème de @ scottyab avec certains caractères non mappés. Dans mon cas, l'exemple de code que je faisais référence fonctionnait parfaitement, mais écrire une chaîne xml dans une file de données entraînait le remplacement de [par £.
En tant que développeur Web travaillant avec une base de données préexistante avec des décennies d'informations, je n'avais pas simplement la capacité de "corriger" la "configuration erronée" comme le suggère un autre commentateur.
Cependant, j'ai pu voir quel identificateur de jeu de caractères codés l'utilisait probablement en envoyant une commande au 400 pour afficher les informations de champ de fichier sur un fichier correct connu: DSPFFD *LIB*/*FILE*
.
Cela m'a donné de bonnes informations, y compris le jeu spécifique du CCSID:
Après quelques informations recherchées sur les CCSID , je suis tombé sur une page d'IBM pour EBCDIC avec des informations clés imprimées sur la page (car elles ont l'habitude de disparaître):
La version 11.0.0 Le code d'échange décimal codé binaire étendu (EBCDIC) Est un schéma de codage généralement utilisé sur zSeries (z/OS) et ISeries (System i).
Et le plus utile:
Quelques exemples de CCSID EBCDIC sont 37, 500 et 1047.
Puisque j'ai déjà appris de cette question elle-même que Cp1047
est un autre bon jeu de caractères à essayer (cette fois, le £ s'est transformé en un "Y" accentué), j'ai essayé Cp37
de ne voir aucun charsset de ce type, mais tenté Cp037
et obtenu le bon encodage.
Il semble que la clé consiste à trouver quel identificateur de jeu de caractères codés (CCSID) est utilisé dans votre système, et à vous assurer que votre instance jt400 - qui fonctionne autrement se perfectionne - correspond à 100% au codage défini sur le as400, dans mon cas chemin avant ma vie et des décennies de logique commerciale.
Je veux ajouter quelque chose à ce que Kwebble et Shawn S. ont dit. Je peux utiliser JTOpen pour faire cela.
J'avais besoin d'écrire sur un champ qui était 6 0P (6 octets, rien derrière la décimale, emballé). C'est un nombre décimal (11,0) pour ceux d'entre vous qui n'aiment pas DDM.
AS400PackedDecimal convertedCustId = new AS400PackedDecimal(11, 0);
byte[] packedCust = convertedCustId.toBytes((int) custId);
String packedCustStr = new String(packedCust, "Cp037");
StringBuilder jcommData = new StringBuilder();
jcommData.append(String.format("%6s", packedCustStr));
Oui, j'ai utilisé la bibliothèque mentionnée par KWebble. En regardant DSPPFD comme Shawn S l'a mentionné, j'ai découvert que la table utilisait le CCSID 37. Cela a fonctionné.
J'ai d'abord essayé d'utiliser Cp1047, selon la suggestion d'Alan Krueger. Cela semblait fonctionner. Malheureusement, si mon custId se terminait par 5, les données restituées dans le fichier étaient B0 au lieu de 5F. Le changer en Cp037 a corrigé cela.
Il devrait être relativement simple d'écrire une mappe pour le jeu de caractères EBCDIC et une pour le jeu de caractères ASCII, et renvoyer dans chacun la représentation de caractères de l'autre. Ensuite, passez simplement sur la chaîne à traduire, recherchez chaque caractère de la carte et ajoutez-le à une chaîne de sortie.
Je ne sais pas s'il existe des convertisseurs accessibles au public, mais cela ne devrait pas prendre plus d'une heure pour en écrire un.