Turning off default EBCDIC encoding on output MVS file.

General discussion on the JZOS batch launcher and toolkit
Post Reply
sheltoma
Posts: 2
Joined: Thu Aug 04, 2005 2:55 pm

Turning off default EBCDIC encoding on output MVS file.

Post by sheltoma »

I want the default EBCDIC encoding for stderr, stdout, input files, and most output files. I need to turn off all encoding on an output file so that binary data (already formatted pack decimal data, etc.) and be written natively to the output file. But, the output file is a fixed block record file.

The following code works, but it is ugly!! Is there a way to turn off encoding on a ZFile, so that I don't have to create a stream.

ZFile outFile = new ZFile("//DD:RECORDS","wb,type=record,noseek");
OutputStream os = outFile.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os, ZFile.DEFAULT_ASCII_CODE_PAGE));

// some code.

while (iter.hasNext()) {

// more code.

bw.write(record.getValue().toCharArray());
bw.flush();
outFile.write(new byte[1]);

// The above write had to be done to create a new record

}
outFile.close();
dovetail
Site Admin
Posts: 2025
Joined: Thu Jul 29, 2004 12:12 pm

Post by dovetail »

If you want to write binary data to a MVS dataset, then you probably don't want either an OutputStream or a Writer.

Just open the output dataset:

ZFile outFile = new ZFile("//DD:RECORDS","wb,type=record,noseek");

and write a record to it:

outFile.write(record); // record is a byte array

Refer to the ZFile java doc for more information:
http://jzos.com/docs/javadoc/
sheltoma
Posts: 2
Joined: Thu Aug 04, 2005 2:55 pm

Post by sheltoma »

I tried this, but the output is converted to EBCDIC.

Thanks,
Mark
dovetail
Site Admin
Posts: 2025
Joined: Thu Jul 29, 2004 12:12 pm

Post by dovetail »

The ZFile.write(byte[]) method should just write the bytes that you pass it. Are you sure that the bytes written to the dataset are different than the bytes that you pass to the ZFile.write(byte[]) method? If so, the conversion is somehow being done in the C-library fwrite() routine, which seems unlikely.

FWIW, here's a class that can dump hex bytes:

Code: Select all

//The source code contained herein is licensed under the IBM Public License   
//Version 1.0, which has been approved by the Open Source Initiative.         
//Copyright (C) 2001 Dovetailed Technologies LLC. All rights reserved. 

package com.dovetail.util;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;


/**
 * Static helper class for dumping bytes in Hex
 */
public class HexUtil {
    
    /**
     * Dumps a byte array to System.out
     */
    public static void dumpHex(byte[] bytes, int offset, int len)  {
        
        StringWriter sw = new StringWriter();
        try {
            dumpHex(bytes, offset, len, 32, sw);
        } catch (IOException cantHappen) {}
        System.out.println(sw.toString());
    }
    
    /**
     * Dumps a byte array in hex to a writer
     */
    public static void dumpHex(byte[] bytes, int offset, int len,
                               int bytesPerLine, Writer writer)
                        throws IOException {
        int limit = offset + len;
        int labelDigits = 4;
        if (limit >= 65536) {
            labelDigits = 8;
        }
        boolean firstLine = true;

        for (int i = 0; i < len; i++) {
            if ((i % bytesPerLine) == 0) {
                if (firstLine) {
                    firstLine = false;
                } else {
                    writer.write("\n");
                }
                writer.write("0x");
                writer.write(toHexString(offset + i, labelDigits));
                writer.write(": ");
            } else if ((i % 4) == 0) {
                writer.write(" ");
            }
            writer.write(toHexString(bytes[offset + i], 2));
        }
        writer.write("\n");
    }

    /**
     * A helper method which converts an (unsigned) int to a hex String with a
     * fixed number of digits.
     */
    public static String toHexString(int i, int numDigits) {
        String answer = Integer.toHexString(i);
        int    len = answer.length();
        if (len < numDigits) {
            return "000000000000000000000000000000000000".substring(0,
                                                                    numDigits -
                                                                    len) +
                   answer;
        } else if (len > numDigits) {
            return answer.substring(len - numDigits);
        } else {
            return answer;
        }
    }
    
    /** 
     * A simple test method
     */
    public static void main(String[] args) {
        
        byte[] bytes = new byte[1000];
        for (int i=0; i<bytes.length; i++) {
            bytes[i] = (byte)(i%256);
        }
        dumpHex(bytes, 0, bytes.length);
    }
}
Last edited by dovetail on Wed Aug 10, 2005 10:30 am, edited 1 time in total.
Guest

Post by Guest »

I got this working.

I had to set the follownig JVM option to prevent any conversion to EBCDIC:

-Dfile.encoding=ISO8859-1

I then had to make readers out of all my input files using the following:

InputStreamReader inputStreamReader =
new InputStreamReader(inFile.getInputStream(), ZFile.DEFAULT_EBCDIC_CODE_PAGE);

so that they read EBCDIC.
dovetail
Site Admin
Posts: 2025
Joined: Thu Jul 29, 2004 12:12 pm

Post by dovetail »

The default JVM encoding is used for byte<->char conversions when you don't explicitly give an encoding. You don't need to set it to ISO8859-1 make your example InputStreamReader read EBCDIC.

You can write code to process data in any encoding, irrespective of the default JVM encoding, so long as you explicitly specify an encoding when ever you convert bytes<->characters. Look elsewhere in your code for implicit conversions: readers, writers, String(byte[],..), String.getBytes(), etc.

- You will get better performance if you use a BufferedReader. The FileFactory class has helper methods for creating buffered readers and writers in a way that is portable to non-z/OS platforms.

Code: Select all

    BufferedReader brdr = FileFactory.newBufferedReader("//DD:INPUT");
    BufferedWriter bwtr = FileFactory.newBufferedWriter("//DD:OUTPUT");
    try {
        String line;
        while ((line = brdr.readLine()) != null) {
            bwtr.write(line);
            bwtr.newLine();
        }
    } finally {
        if (brdr != null) brdr.close();
        if (bwtr != null) bwtr.close();
    }
The default encoding for FileFactory, when opening MVS datasets, is the default EBCDIC encoding. For more information, the javadoc:

http://jzos.com/docs/javadoc/com/doveta ... ctory.html
Post Reply