I am using NIO File Channel to manage files, and locking them. So far it works, however when I lock a File using NIO File Lock it locks the file so the file Content cannot be changed. As for example if I try to edit a text file on notepad it will show me the following error message:
And that is the expected result, however if I try to delete the file from windows explorer(I haven't tested on other OS likely will be possible as well) it will allow me, and this is undesired, I would like to know if it is possible to Open a File Handle
Code Used:
private static final byte[] MessageBytes;
static {
byte tmp[];
try {
tmp = "Hello World".getBytes("UTF-8");
} catch (UnsupportedEncodingException ex) {
//if fail get the bytes in whatever the java VM charset sets as default
tmp = "Hello World".getBytes();
}
MessageBytes = tmp;
}
private static final String Filename = "Lock_test.txt";
private static void createFileandLock() {
Path FilePath = Paths.get(Filename);
FileChannel OpenFCh;
try {
OpenFCh = FileChannel.open(FilePath, StandardOpenOption.CREATE,
StandardOpenOption.READ, StandardOpenOption.WRITE
// ,StandardOpenOption.APPEND
);
System.out.println("File Channel is Open.");
} catch (IOException err) {
OpenFCh = null;
}
if (OpenFCh != null) {
FileLock Lock = null;
try {
Lock = OpenFCh.lock();
} catch (IOException err) {
System.out.println("Unable To Lock the File.");
}
try {
OpenFCh.write(ByteBuffer.wrap(MessageBytes));
OpenFCh.force(false);
System.out.println("Message Recorded");
} catch (IOException ex) {
System.out.println("Unable To write data into file");
}
try {
// at this point file still locked and open.
//lets wait for input and meanwhile ask to delete the file.
System.out.print("Please Try to delete file at: ");
System.out.println(FilePath.toString());
System.out.println("Press Enter to Continue");
System.in.read();
} catch (IOException ex) {
}
if (Lock != null) {
try {
Lock.close();
} catch (IOException ex) {
}
}
try {
OpenFCh.close();
} catch (IOException ex) {
}
}
}
After further research I notice that using RandomAccessFile Will lock the file avoiding deletion as it creates a File Descriptor that basically open a Handle on the underline Operative system.
So using the RAF does provide the desired result:
Code Used:
private static void createRAFileandLock() {
RandomAccessFile RAf;
try {
RAf = new RandomAccessFile(Filename, "rw");
} catch (FileNotFoundException ex) {
//since is open as RW shold not trigger.
RAf = null;
}
if (RAf != null) {
FileChannel OpenFCh = RAf.getChannel();
FileLock Lock = null;
try {
Lock = OpenFCh.lock();
} catch (IOException err) {
System.out.println("Unable To Lock the File.");
}
try {
OpenFCh.write(ByteBuffer.wrap(MessageBytes));
OpenFCh.force(false);
System.out.println("Message Recorded");
} catch (IOException ex) {
System.out.println("Unable To write data into file");
}
// at this point file still locked and open.
//lets wait for input and meanwhile ask to delete the file.
try {
System.out.print("Please Try to delete file at: ");
System.out.println(Filename);
System.out.println("Press Enter to Continue");
System.in.read();
} catch (IOException ex) {
}
if (Lock != null) {
try {
Lock.close();
} catch (IOException ex) {
}
}
try {
OpenFCh.close();
RAf.close();
} catch (IOException ex) {
}
}
}
However I would like to know if it is possible to archive this using only NIO. As Random Access File is on IO package.
FileLock isn't specified to prevent deletion. It's only specified to interact with other file locks, so you're already deep into platform-dependent behaviour. If RandomAccessFile somehow does what you want you may be stuck with it, but you can't rely on it.
NB of course FileChannel.open() uses a FileDescriptor, handle, etc.
Related
I want to know how can I use java to confirm a file is a picture file.
I have tried the following code:
public static void main(String[] args) {
// get image format in a file
File file = new File("C:/Users/dell、/Desktop/4.xlsx");
// create an image input stream from the specified fileDD
ImageInputStream iis = null;
try {
iis = ImageIO.createImageInputStream(file);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// get all currently registered readers that recognize the image format
Iterator<ImageReader> iter = ImageIO.getImageReaders(iis);
if (!iter.hasNext()) {
System.out.println("Not a picture file");
throw new RuntimeException("No readers found! Unable to read the uploaded file");
}
// get the first reader
ImageReader reader = iter.next();
try {
System.out.println("Format: " + reader.getFormatName());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// close stream
if (iis != null){
try {
iis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
iis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
But it doesn't work perfectly! It shows an exception once the file is not a picture file, so I want to find a better way.
There are too many image extensions. Maybe the best way to validate if a file is an image, is using Regular Expressions. Something like this...
([^\s]+(\.(?i)(jpg|png|gif|bmp|MORE|IMAGE|EXTENSIONS))$)
Here is a complete example of the implementation.
Use ImageIO#read.
public static boolean isPictureFile(File file){
try{
return ImageIO.read(file) != null;
}catch(Exception ex){
return false;
}
}
Basically, the method ImageIO.read(File) will return a BufferedImage object when it successfully read the image file, a null otherwise. All we have to do is to let ImageIO read the file and check if it returns a null or not, and if there it throws an exception for whatever reason, we can safely assume the file is not a picture file.
I made my own data structure called a User. I am trying to store Users in a .bin file using FileInputStream and FileOutputStream. I am successfully storing a single user when a button is pressed, but then when I close the application and go to read my Users and recognize login info, the .bin file turns blank.
I know that the .bin file is not empty after the program closes, but then when I try to read the file I get a EOFException. Here is my code to read objects from the file:
public void loadUsers() {
try {
ObjectInputStream ois = new ObjectInputStream(fi);
boolean endOfFile = false;
while (!endOfFile) {
try {
System.out.println("loaded a user!");
User person = (User) ois.readObject();
Users.addUser(person);
} catch (EOFException e) {
endOfFile = true;
ois.close();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Here is my code to write objects to the file:
public void storeUser(User person) {
boolean endOfFile = false;
try {
new ObjectInputStream(fi).readObject();
} catch (EOFException e) {
endOfFile = true;
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
if (!endOfFile) {
System.out.println("Appending!");
try {
AppendingObjectOutputStream aos = new AppendingObjectOutputStream(fo);
aos.writeObject(person);
aos.flush();
aos.close();
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Writing a new file!");
try {
ObjectOutputStream oos = new ObjectOutputStream(fo);
oos.writeObject(person);
oos.flush();
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
AppendingObjectOutputStream is just a small subclass of ObjectOutputStream I made that overwrites writeStreamHeader() so that there is no header placed in my file when try to write more users. I don't think this is related to the problem because I have yet to write a User onto a file with Users already written on it.
I try a lot of thinks to find the fail but i don't know how I can do it. my code is:
//DominioLlamadaRedSys.java
Properties d = new Properties();
InputStream entrada = null;
try {
entrada = new FileInputStream("prop/datosApp.properties");
d.load(entrada);
System.out.println(d.getProperty("TXD.endPointUrl"));
} catch (IOException ex) {
System.out.println("ERROR: "+ ex.getMessage());
} finally {
if (entrada != null) {
try {
entrada.close();
} catch (IOException e) {
}
}
}
I call the file inside a class in "com.rsi.secpay.dominio" and this always catch the same exception (don't find the file), I had try to quit "prop/" (just "datosApp.properties" ) with properties files like this:
If your prop package is in your classpath, you can get the stream using the classloader:
InputStream is = DominioLlamadaRedSys.class.getResourceAsStream("/prop/datosApp.properties");
I have tried many examples, but no one works.
I try this but don't work.
I tried also to use the tryLock(). It always returns false. why?
private boolean checkCompleteFile(File f)
{
RandomAccessFile file = null;
FileLock fileLock = null;
try
{
file = new RandomAccessFile(f, "rw");
FileChannel fileChannel = file.getChannel();
fileLock = fileChannel.lock();
if (fileLock != null)
{
fileLock.release();
file.close();
return false;
}
}
catch(Exception e)
{
return false;
}
return true;
}
You catch an exception and return false, thats why you get false all the time, do something with the exception or do not catch it so you know if an exception was thrown, if you catch a general exception a false return value is not really meaningful.
try {
lock = channel.tryLock();
// ...
} catch (OverlappingFileLockException e) {
// File is already locked in this thread or virtual machine
}
lock.release();
channel.close();
You cam just try to access the file and catch an exception if it fails:
boolean isLocked=false;
RandomAccessFile fos=null;
try {
File file = new File(filename);
if(file.exists())
fos=new RandomAccessFile(file,"rw");
}catch (FileNotFoundException e) {
isLocked = true;
}catch (SecurityException e) {
isLocked = true;
}catch (Exception e) {
// handle exception
}finally {
try {
if(fos!=null) {
fos.close();
}
}catch(Exception e) {
//handle exception
}
}
Notice that the RandomAccessFile class throws:
FileNotFoundException -
if the mode is "r" but the given string does
not denote an existing regular file, or if the mode begins with "rw"
but the given string does not denote an existing, writable regular
file and a new regular file of that name cannot be created, or if some
other error occurs while opening or creating the file.
SecurityException -
if a security manager exists and its checkRead
method denies read access to the file or the mode is "rw" and the
security manager's checkWrite method denies write access to the file
Try using this:
try {
#SuppressWarnings("resource")
FileChannel channel = new RandomAccessFile(fileToRead, "rw").getChannel();
//This method blocks until it can retrieve the lock.
FileLock lock = channel.lock(); // Try acquiring the lock without blocking.
try {
lock = channel.tryLock();
} catch (OverlappingFileLockException e){
}
lock.release(); //close the file.
channel.close();
} catch (Exception e) {
}
How about using the linux command ?
lsof -p
The command will show the file open status, you can parse it to check who use it.
How can I delete the content of a file in Java?
How about this:
new RandomAccessFile(fileName).setLength(0);
new FileOutputStream(file, false).close();
You could do this by opening the file for writing and then truncating its content, the following example uses NIO:
import static java.nio.file.StandardOpenOption.*;
Path file = ...;
OutputStream out = null;
try {
out = new BufferedOutputStream(file.newOutputStream(TRUNCATE_EXISTING));
} catch (IOException x) {
System.err.println(x);
} finally {
if (out != null) {
out.flush();
out.close();
}
}
Another way: truncate just the last 20 bytes of the file:
import java.io.RandomAccessFile;
RandomAccessFile file = null;
try {
file = new RandomAccessFile ("filename.ext","rw");
// truncate 20 last bytes of filename.ext
file.setLength(file.length()-20);
} catch (IOException x) {
System.err.println(x);
} finally {
if (file != null) file.close();
}
May problem is this leaves only the head I think and not the tail?
public static void truncateLogFile(String logFile) {
FileChannel outChan = null;
try {
outChan = new FileOutputStream(logFile, true).getChannel();
}
catch (FileNotFoundException e) {
e.printStackTrace();
System.out.println("Warning Logfile Not Found: " + logFile);
}
try {
outChan.truncate(50);
outChan.close();
}
catch (IOException e) {
e.printStackTrace();
System.out.println("Warning Logfile IO Exception: " + logFile);
}
}
Open the file for writing, and save it. It delete the content of the file.
try {
PrintWriter writer = new PrintWriter(file);
writer.print("");
writer.flush();
writer.close();
}catch (Exception e)
{
}
This code will remove the current contents of 'file' and set the length of file to 0.