javamultithreadingniofilechannelfilelock

ObjectInputStream throws ioexception inside the filelock lock section


I have a function, that has to put key value pair into map stored in file. If file does not exist, I have to create it. I try to lock the file, when I work with it with Filelock lock(). But when I try to write into it( Inside of the locked section), I get IO exception: Suppressed: java.io.IOException: The process cannot access the file because another process has locked a portion of the file I, probably, don't use the lock() right. Here is my function:

        private void createDataSet(String key, String data) throws IOException, ClassNotFoundException{

                final   String path = (fileName);
    //            1. Check if file exists
    //            2. If file exists, write/override key/value.
                Path nPath = Paths.get(path);
                HashMap<String, List<String>> map = new HashMap<String, List<String>>();
    //            createFile is atomic, no need to check if exists.
                    try(FileChannel fileChannel = FileChannel.open(nPath,StandardOpenOption.WRITE,StandardOpenOption.APPEND
                            , StandardOpenOption.CREATE);
                        FileOutputStream fos= new FileOutputStream(path, false);
                        ObjectOutputStream oos= new ObjectOutputStream(fos);

                        ){
                        FileLock lock = fileChannel.lock();
                        if(fileChannel.size()==4){
                            map.put(key, values);
                            oos.writeObject(map);
                        }else{
                            ObjectInputStream objectIn = new ObjectInputStream(Channels.newInputStream(fileChannel));
                            Object obj = objectIn.readObject();
                            map = (HashMap<String, List<String>>) obj;
                            map.put(key, values);
// In this row exception being throwed:
                            oos.writeObject(map); 
                        }
                        oos.close();
                        fos.close();
                        lock.release();
                    }
                    return;

Solution

  • You open the file twice - once via FileChannel, another via FileOutputStream. You then lock the file via FileChannel but try to write to it via FileOutputStream. That's why the stream is blocked by the lock by the channel.

    FileChannel has its own read/write methods. Use either channel or stream, but not both.

    [Edit] the file lock is to prevent another process from writing to it, so unless you know there is some other process that might try to write to your file, there is generally no need to explicitly lock a file before writing to it.