Overwrite a properties file from the FileOutputStream obtained through FileDescriptor FD

722 views Asked by At

Peculiar problem is When I am using the properties.store code with the FileOutputStream obtained from file path, the above method works all fine but when I do that from FileOutputStream obtained from FileDescriptor the properties file append to it, doesn't overwrite.

Now my constraint is to use the later approach since I am using FileLock and cant get the FileOutputStream through file again.

  1. Is it possible? To do something with the later approach and overwrite and
  2. If not what are my options?

The two piece of code is

First Approach

OutputStream out = null;
    try {
        if (portFile != null && portFile.exists()) {
            out = new FileOutputStream(portFile);
        } else {
            try {
                portFile.createNewFile();
            } catch (IOException e) {
                LOGGER.error("error in creating properties file ", e);
            }
            out = new FileOutputStream(portFile);
        }
    } catch (FileNotFoundException e) {
        LOGGER.error("Not able to get outputstream on properties file ", e);
    }

    try {
        properties.store(out, CJDPluginConstants.PROP_NAME_PORT_MIN);
    } catch (IOException e) {
        LOGGER.error("Not able to save properties file ", e);
    }

Second Approach

// so we move to raf now
    OutputStream out = null;
    if (portFileRandomAccess != null && channel != null) {
        //ByteBuffer buffer = ByteBuffer.allocate(1024);
        try {
            if (buffer != null) {
                //if (buffer != null) {
                buffer.flip();
                LOGGER.info("buffer what we get we are writing ? " + buffer.asCharBuffer());
                out = new ByteBufferBackedOutputStream(buffer);
                FileOutputStream fos = new FileOutputStream(portFileRandomAccess.getFD());
                //fos.flush();
                properties.store(fos, CJDPluginConstants.PROP_NAME_PORT_MIN);
                buffer.clear();
                buffer = null;
                //}
            }
        } catch (IOException e) {
            LOGGER.error("Not able to save properties file ", e);
        }
    }

    //release lock, close channel
    if (lock != null) {
        try {
            lock.release();
        } catch (IOException e) {
            LOGGER.error("Error releasing lock", e);
        }
    }

    if (channel != null) {
        try {
            channel.close();
        } catch (IOException e) {
            LOGGER.error("Error closing channel", e);
        }
    }
2

There are 2 answers

1
Holger On BEST ANSWER

If you have a FileOutputStream, regardless of how you created it, it’s easy to truncate the associated file to a zero length:

fileOutputStream.getChannel().truncate(0);

Then the file is empty and you write new contents to it.

It’s also possible to do a real overwrite, i.e. keeping old contents at regions you don’t write to:

fileOutputStream.getChannel().position(0);

Then the next writes go to the specified position overwriting as much bytes as you really write, but retaining all other bytes.

1
Joni On

Opening a RandomAccessFile doesn't automatically truncate the file like opening a FileOutputStream does. You have to do it manually, after obtaining the lock:

// remove existing contents
portFileRandomAccess.setLength(0);