Access Is Denied using NIO

Hello,

I am attempting to build a file transfer method that transfers a buffer of bytes at a time because I am using modems as my lower layer transfer method. (I dont have a choice on that one.) What happens is when I get disconnected I have to start over with the transfer and I dont want to do that. I want to keep up with the last byte successfully transferred so I can redial the connection, and pick up where I left off. I questioned about this yesterday but really didnt get a whole lot of help.

Here is a method that I have writte to do this job using NIO. I chose NIO because it seems faster and I have to compare files across a modem connection to make sure they have the correct versions of the exectuables.

Never the less this method throws an java.io.IOException: Access is denied exception when it gets the last byte. What I have found is that the last byte is either negative or the last byte has a remainder left over.

So given the file Source file c:\DJ\REMOTE_BIN\dcompres.exe has length of 29656 total bytes. From what I can tell, if this file isnt divisible by 512 then the last byte throws an exection. What doesnt make sense to me is why it throws Access Denied...

I did a small test and discovered that if I change the buffer to a 2, which would make even value length files divisible by 2 transfer just fine without the exception.

I have read through the transferFrom method and did not find where it throws this Access Denied exception.

What am I doing wrong here?

// Upload the package to the system.

publicstaticboolean uploadPackage(String sourceFile,String targetFile){

long bytePosition = 0;

int buffer = 512;

System.out.println("Copying executable " + sourceFile +" " + targetFile);

try{

// Create channel on the source

FileChannel srcChannel =new FileInputStream(sourceFile).getChannel();

// Create channel on the destination

FileChannel dstChannel =new FileOutputStream(targetFile).getChannel();

System.out.println("Source file " + sourceFile +" has length of " + srcChannel.size());

while (srcChannel.position() < srcChannel.size()){

dstChannel.transferFrom(srcChannel, srcChannel.position(), buffer);

// bytePosition = srcChannel.position();

System.out.println("Byte Position " + srcChannel.position());

}

// Close the channels

srcChannel.close();

dstChannel.close();

System.out.println("FILE COPY OKAY");

returntrue;

}catch (IOException e){

vlicMessageDetail ="IO EXCEPTION OCCURRED " + e;

pushRunTimeLog("[UPLOAD PACKAGE] (FATAL) :: IOEXCEPTION " + e);

System.out.println("IO EXCEPTION " + e);

returnfalse;

}

}

Message was edited by:

gsxrJava

[3881 byte] By [gsxrJavaa] at [2007-10-3 3:22:27]
# 1

Your code transfers from one file channel to another file channel, so what have modems got to do with it?

And if somehow you really are using a modem at the lowest layer, any time saving due to NIO will be completely insignificant. You may as well keep it simple and use java.io Input/OutputStreams.

But your problem is that the count you're supplying to transferFrom() never changes - it is always 512. What if the amount left to read < 512?

And why such a small buffer size as 512?

ejpa at 2007-7-14 21:14:57 > top of Java-index,Core,Core APIs...
# 2

The reason why is because I playing with the buffer lengths to see if the buffer had anything to do with the issue and I discovered that it had nothing to do with the issue.

The files that I am sending are large and I am looking to decrease talk time on a long distance phone call. If I can transfer all of the file at one time then that is great, but sometimes I get disconnected, so I need to pick up where I left off and append the next bytes to the bytes already written to the harddrive. Does that make sense?

In my code, If I get disconnected during the uploadPackage method, I will redial() the connection, then continue transferring data to the remote site. What I keep up with in the previous method is the position of the file so that I can start at that position and append the bytes to that file until I have a complete file.

The final problem is that the las amount left is less than 512.

I am thinking that I will go back with trust I/O Streams. I thought about using NIO because I use this method for file comparisons.

I just thought it would be better to use the same Library to do what I needed.

here is the code I use for the file comparison across a modem connection. Not that it really matters but perhaps somebody might be looking for an efficient way to compare files across a low bandwidth connection.

// Check remote machine for the correct executable

public static boolean compareFiles(String sourceFile, String targetFile) {

System.out.println("FILE COMPARE (INFO) :: COMPARING " + sourceFile + " AND " + targetFile");

try {

RandomAccessFile sourceFileRa = new RandomAccessFile(sourceFile,"r");

RandomAccessFile targetFileRa = new RandomAccessFile(targetFile,"r");

FileChannel sourceChannel = sourceFileRa.getChannel();

MappedByteBuffer sourceBuffer = sourceChannel.map(FileChannel.MapMode.READ_ONLY, 0, sourceFileRa.length());

FileChannel targetChannel = targetFileRa.getChannel();

MappedByteBuffer targetBuffer = targetChannel.map(FileChannel.MapMode.READ_ONLY, 0, targetFileRa.length());

while (sourceBuffer.position() < sourceFileRa.length()) {

byte sourceByteArray[] = null;

byte targetByteArray[] = null;

sourceByteArray = new byte[(int)sourceFileRa.length()];

targetByteArray = new byte[(int)targetFileRa.length()];

sourceBuffer.get(sourceByteArray);

targetBuffer.get(targetByteArray);

System.out.println("Source Byte array " + sourceBuffer);

if(sourceByteArray.length != targetByteArray.length) {

return false;

}

else {

for(int x=0; x< sourceByteArray.length; x++) {

//System.out.println("Source Byte Array Bytes " + sourceByteArray[x]);

if(sourceByteArray[x] != targetByteArray[x]) {

sourceChannel.close();

targetChannel.close();

sourceFileRa.close();

targetFileRa.close();

return false;

}

}

}

}

sourceChannel.close();

targetChannel.close();

sourceFileRa.close();

targetFileRa.close();

return true;

} catch (Exception e) {

return false;

}

}

Message was edited by:

gsxrJava

Message was edited by:

gsxrJava

Message was edited by:

gsxrJava

gsxrJavaa at 2007-7-14 21:14:57 > top of Java-index,Core,Core APIs...
# 3

There's no point in using a MappedByteBuffer and then reading the entire thing into another array. Use the get() methods of MappedByteBuffer directly to compare the characters.

Correcting the 512 for the last buffer is a pretty trivial exercise but really I would use ordinary IO for this.

ejpa at 2007-7-14 21:14:57 > top of Java-index,Core,Core APIs...