• Post Reply Bookmark Topic Watch Topic
  • New Topic

File truncate / resize

 
Verena Dear
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello everybody,

I try to resize a file and I always get the exception: "The requested operation cannot be performed on a file with a user-mapped section open".

I think I closed everything that I do not need anymore. Here is my code:

public static void cut(RandomAccessFile srcRaf, int offset, int len) {
try {
FileChannel fc = srcRaf.getChannel();
long oldLength = srcRaf.length();
long newLength = oldLength - len;
MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_WRITE, 0, oldLength);

for (int pos = offset; pos < newLength; pos++)
buf.put(pos, buf.get(pos+len));
buf.force();

buf = null;
Runtime.getRuntime().gc(); // just to be sure
fc.truncate(newLength);
} catch (java.io.IOException e){
System.out.println(e.getMessage());
}
}


I also tried setLength() from RandomAccessFile with the same result. What did I miss?

To make it really strange the whole thing works for Linux but not for Windows (2k Pro).

Any ideas?

Thank for help,

--Verena
 
Stefan Wagner
Ranch Hand
Posts: 1923
Linux Postgres Database Scala
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I cannot answer your question, but there are two useless statements:


a) buf is defined in the scope of this method, and marked as ready for garbage-collection at its end. There is no need to set it to null.

b) calling gc() isn't sure at all. It might get invoked or not.
Helping the Garbage-collector isn't the job of a java-programmer.
Remove both lines and wait for help of your main problem

(Running linux too, I don't try to reproduce it either).
[ June 14, 2004: Message edited by: Stefan Wagner ]
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You can't really use a MappedByteBuffer here if you're going to truncate the mapped region. It may work on some systems, but the behavior is undefined. You'd be best off avoiding a mapped buffer altogether for this sort of operation. What I'd probably do: create a new file which has the contents you want. (FileChannel's transferTo() method can do this quite efficiently.) Once it's created, delete the original file, and rename the new file to the old file's name. (Make sure both FileChannels have been closed before you try to delete or move the files.) You could also use a single FileChannel and a ByteBuffer to transfer bytes from one part of the file to another, if you're careful abouthow you do it. But my first suggestion seems simpler, IMO, and probably faster.
 
Verena Dear
Greenhorn
Posts: 18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks for your reply.

@Stefan I know that is is not necessary, but it was my last hope to set the ByteBuffer to null. I will remove this.

@Jim
The problem is, that I can't simply copy the file to another, because it might get very huge (upto 2GB). I know that I also have to think about the copy-thing, because it would anyway take a long time. But double the file in advance would make it even take longer. Any ideas for that?

--Verena
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!