I implemented a Vigenere encoding and decoding class. Ideally, the program should be able to take any abritrary file, read into an array of byte, and decode it.import java.io.*;class VigenereFilterReader extends FilterReader {    private final char[] key;    private int i = 0;    VigenereFilterReader(Reader in, char[] k) {        super(in);        key = k.clone();    }    VigenereFilterReader(Reader in, String k) {        super(in);        key = k.toCharArray().clone();    }    public int read() throws IOException {        int b1 = super.read();        int b2 = super.read();        if (b1 == -1 || b2 == -1)            return -1;        int b;        b = Integer.parseInt(Character.toString((char) b1) + Character.toString((char) b2), 16);        int out = b ^ key[i];        i ++;        i %= key.length;        return out;    }    public String readString() throws Exception {        StringBuilder out = new StringBuilder();        int c;        while ((c = this.read()) != -1) {            out.append((char) c);        }        return out.toString();    }}class VigenereFilterWriter extends FilterWriter {    private final char[] key;    VigenereFilterWriter(Writer out, String k) {        super(out);        key = k.toCharArray().clone();    }    VigenereFilterWriter(Writer out, char[] k) {        super(out);        key = k.clone();    }    public void write(String s) throws IOException{        this.write(s.toCharArray());    }    public void write(char[] info) throws IOException {        StringBuilder out = new StringBuilder();        for(int i = 0; i < info.length; i++) {            out.append(String.format(%02X,(info[i] ^ key[i % key.length])));        }        super.write(out.toString());    }}class Vigenere {    public static void main(String[] args) throws Exception {        if (args.length != 1) {            throw new Exception(Missing filename);        }        String text = helloworldahelloworld testing a long sequence;        String key =  abcdef;        FileWriter fileEncrypt = new FileWriter(args[0]);        VigenereFilterWriter encrypt = new VigenereFilterWriter(fileEncrypt, key);        encrypt.write(text);        fileEncrypt.close();        FileReader fileIn = new FileReader(args[0]);        VigenereFilterReader in = new VigenereFilterReader(fileIn, key);        System.out.println(in.readString());    }}This implementation use some casting (line 36, 63 etc). Is the cast dangerous?What is a better way to store encoded byte in file? I used hex string (so that encoded file is readable), but it's quite inconvenient (toHexString at the writer, and when read I have to do 2 read char).P/S: Here is my updated version using byte IO. Please feel welcome to criticize this code.import java.io.*;class VigenereFilterInputStream extends FilterInputStream {    private final byte[] key;    private int index = 0;    VigenereFilterInputStream(InputStream in, byte[] k) {        super(in);        key = k.clone();    }    public int read() throws IOException {        int c = super.read();        if (c == -1)             return -1;        int out = c ^ key[index];        index ++;        index %= key.length;        return out;    }    public int read(byte[] b) throws IOException {        int result = in.read(b);        for(int i = 0; i < b.length; i++) {            b[i] = (byte) (b[i] ^ key[i % key.length]);        }        return result;    }}class VigenereFilterOutputStream extends FilterOutputStream {    private final byte[] key;    VigenereFilterOutputStream(OutputStream out, byte[] k) {        super(out);        key = k.clone();    }    public void write(byte[] b) throws IOException {        byte[] out = new byte[b.length];        for(int i = 0; i < b.length; i++) {            out[i] = (byte) (b[i] ^ key[i % key.length]);        }        super.write(out);    }}class Vigenere {    public static void main(String[] args) throws Exception {        if (args.length != 1) {            throw new Exception(Missing filename);        }        File f = new File(args[0]);        byte[] text = hello testing long output!@#)!(!*!(@()asdfasdfljkasdfjlkasdfl.getBytes();        byte[] key = hello.getBytes();        FileOutputStream os = new FileOutputStream(f);        VigenereFilterOutputStream encrypt = new VigenereFilterOutputStream(os, key);        encrypt.write(text);        FileInputStream is = new FileInputStream(f);        BufferedInputStream bis = new BufferedInputStream(is);        VigenereFilterInputStream decrypt = new VigenereFilterInputStream(bis, key);        bis.mark(text.length);        int c;        while((c = decrypt.read()) != -1) {            System.out.print((char) c);        }        System.out.println();        bis.reset();        byte[] b = new byte[text.length];        decrypt.read(b);        for(byte d: b) {            System.out.print((char) d);        }        System.out.println();    }}
Vigenre cipher as an IO filter
java;io;serialization;vigenere cipher