1) In its basic form the maximum length that RSA can encrypt at a time is limited to the size of the RSA modulus (or the modulus length - 11 when using PKCS11 padding by using the default padding as you are doing). One can break the input into blocks of less than this modulus and encrypt them individually but then one has to handle the problem problem that in RSA N bytes of cleartext does not necessarily produce N bytes of ciphertext..
When encrypting more than the RSA length one normally creates a hybrid encryption. In this approach one generates a random key for use with a block cipher such as AES and then uses this to encrypt the actual data. The random block cipher key is encrypted with RSA and sent with the AES cipher text. This approach is presented more formally in section 13.6 pf "Practical Cryptography" by Ferguson and Schneier.
2) In my view CipherInputStream and CipherOutputStream are very poor. They swallow all exceptions so when anything goes wrong one never hears of it.
3) Chaining streams as you have done makes it difficult to read the code and if anything goes wrong it is difficult to work out which term in the chain caused the exception. It costs nothing to use something like
4) I'm never very comfortable with reading and writing just one byte at a time using
I have known this to fail. You would do better to read and write a chunk (say 4K) at a time.