0

Goal: Decrypt data from one source and write the decrypted data to a file.

try (FileInputStream fis = new FileInputStream(targetPath.toFile());
        ReadableByteChannel channel = newDecryptedByteChannel(path, associatedData))
{
    FileChannel fc = fis.getChannel();
    long position = 0;
    while (position < ???)
    {
        position += fc.transferFrom(channel, position, CHUNK_SIZE);
    }
}

The implementation of newDecryptedByteChannel(Path,byte[]) should not be of interest, it just returns a ReadableByteChannel.

Problem: What is the condition to end the while loop? When is the "end of the byte channel" reached? Is transferFrom the right choice here?

This question might be related (answer is to just set the count to Long.MAX_VALUE). Unfortunately this doesn't help me because the docs say that up to count bytes may be transfered, depending upon the natures and states of the channels.

Another thought was to just check whether the amount of bytes actually transferred is 0 (returned from transferFrom), but this condition may be true if the source channel is non-blocking and has fewer than count bytes immediately available in its input buffer.

sn42
  • 2,353
  • 1
  • 15
  • 27

2 Answers2

1

It is one of the bizarre features of FileChannel. transferFrom() that it never tells you about end of stream. You have to know the input length independently.

I would just use streams for this: specifically, a CipherInputStream around a BufferedInputStream around a FileInputStream, and a FileOutputStream.

But the code you posted doesn't make any sense anyway. It can't work. You are transferring into the input file, and via a channel that was derived from a FileInputStream, so it is read-only, so transferFrom() will throw an exception.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

As commented by @user207421, as you are reading from ReadableByteChannel, the target channel needs to be derived from FileOutputStream rather than FileInputStream. And the condition for ending loop in your code should be the size of file underlying the ReadableByteChannel which is not possible to get from it unless you are able to get FileChannel and find the size through its size method.

The way I could find for transferring is through ByteBuffer as below.

ByteBuffer buf = ByteBuffer.allocate(1024*8);
while(readableByteChannel.read(buf)!=-1)
{
  buf.flip();
  fc.write(buf);  //fc is FileChannel derived from FileOutputStream
  buf.compact();
}

buf.flip();
while(buf.hasRemainig())
{
  fc.write(buf);
}
shankar_vl
  • 72
  • 6