Prevent deleting lock file using nio - java

We want to prevent other processes from deleting the temp directory of our running application. That way we create a temp directory and a lock file in it. The only way I found at that prevents deleting this file is by using RandomAccessFile:
tempDirectory = Files.createTempDirectory("myapp");
final Path lockFile = Files.createTempFile(tempDirectory, "lock", null);
randomAccessFile = new RandomAccessFile(lockFile.toFile(), "rw");
Is there a way to achieve the same with nio? I have tried with the following code:
import java.io.*;
import java.nio.channels.*;
import java.nio.file.*;
public class CreateLock {
public static void main(String[] args) throws IOException, InterruptedException {
final Path path = Paths.get("C:/temp/test");
Files.createFile(path);
final FileChannel channel = FileChannel.open(path, StandardOpenOption.WRITE);
channel.lock();
for (int i = 60; i-- > 0; ) {
System.out.println(i);
if (!Files.isRegularFile(path)) {
System.out.println("File is gone");
break;
}
Thread.sleep(10_000);
}
channel.close();
}
}
but a second Java application with this code
import java.io.*;
import java.nio.file.*;
public class DeleteLock {
public static void main(String[] args) throws IOException {
final Path path = Paths.get("C:/temp/test");
Files.delete(path);
}
}
can delete the file.

Please try below:
FileChannel ch = FileChannel.open(lockFile.toAbsolutePath(), StandardOpenOption.WRITE);
ch.lock();

Related

Having issue with getting my file to print to console

I have a data structure assignment were the code has to read the text data from a text file and print it onto the screen. The code that I wrote says that the build was a success but the text file itself doesn't print. What do I do?
import java.util.Scanner;
import java.io.IOException;
import java.io.FileInputStream
public class readFile{
public static void main(String[] args) throws IOException {
FileInputStream fileByteStream = null;
Scanner file = null;
int textFile;
try{
fileByteStream = new FileInputStream("file1.txt");
file = new Scanner(fileByteStream);
while(file.hasNextInt()){
textFile = file.nextInt();
System.out.println("file1.txt");
}
}
catch(IOException e){
}
}
}
Replace System.out.println("file1.txt"); by System.out.println(textFile);.
This should work if you have the "file1.txt" saved in the correct location. As is, you are just passing the String "file1.txt" rather than the file object which was not yet created. (See line 13 of this code below)
import java.util.Scanner;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
public class readFile
{
public static void main(String[] args) throws IOException
{
FileInputStream fileByteStream = null;
Scanner file = null;
int textFile;
File file1 = new File("file1.txt");
try
{
fileByteStream = new FileInputStream(file1);
file = new Scanner(fileByteStream);
System.out.println("Reading file...");
while(file.hasNextInt())
{
textFile = file.nextInt();
System.out.println(textFile);
System.out.println("Scanning a line..");
}
file.close();
}
catch(IOException e)
{
System.out.println("Exception handled");
e.printStackTrace();
}
}
}
You can use print statements to help see where the code is breaking. It looks like you have an IO Exception (input/output). Also, you should want to close the Scanner object.
import java.util.Scanner;
import java.io.IOException;
import java.io.FileInputStream;
public class readFile
{
public static void main(String[] args) throws IOException
{
FileInputStream fileByteStream = null;
Scanner file = null;
int textFile;
try
{
fileByteStream = new FileInputStream("file1.txt");
file = new Scanner(fileByteStream);
System.out.println("Reading file...");
while(file.hasNextInt())
{
textFile = file.nextInt();
System.out.println(textFile);
System.out.println("Scanning a line..");
}
file.close();
}
catch(IOException e)
{
System.out.println("Exception handled");
}
}
}

Java file copy to non empty destination folder

I'm having real difficulties figuring out how this needs to be coded without using FileUtils import. I have found thousands of tutorials on how to move files to empty folders, that's easy. The difficulty is finding out how Java can move files to directories that already have files in the folder. As I understand it the REPLACE_EXISTING parameter means it will overwrite identical file names if detected in the destination directory, but the directory doesn't have a file with a matching name of the file I'm attempting to copy/move. What am I missing? How can I make this happen?
java.nio.file.DirectoryNotEmptyException occuring.
enter code here
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class Move {
static File source = new File("sourcefolderhere");
static File destination = new File("destfolderhere");
public static void move(File src, File dest) throws IOException {
Files.move(src.toPath().toAbsolutePath(), dest.toPath().toAbsolutePath(),
StandardCopyOption.REPLACE_EXISTING);
}
public static void main(String[] args) throws IOException {
try {
if(source.isDirectory() && destination.isDirectory()) {
File[] content = source.listFiles();
for(int i = 0; i < content.length; i++) {
System.out.println(content[i]);
move(source, destination);
}
}
else if (!destination.isDirectory()){
System.out.println("create folder here");
destination.mkdir();
File[] content = source.listFiles();
for(int i = 0; i < content.length; i++) {
move(source, destination);
}
}
}
catch(Exception ex) { System.out.println(ex);
}
finally {
}
}
}
I tried the code in IDE File.move method with parameter StandardCopyOption.REPLACE_EXISTING works only if you have file in the destination folder. otherwise use File.move the normal way. I have also modified your code a little just to avoid code duplication.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
public class Move {
static File source = new File("sourcefolderhere");
static File destination = new File("destfolderhere");
public static void move(File src, File dest) throws IOException {
System.out.println(src.getName());
if(isExist(src.getName()))
Files.move(src.toPath().toAbsolutePath(), Paths.get(destination.getAbsolutePath()+File.separator+src.getName()) , StandardCopyOption.REPLACE_EXISTING);
else
Files.move(src.toPath().toAbsolutePath(), Paths.get(destination.getAbsolutePath()+File.separator+src.getName()));
}
public static boolean isExist(String souceFileName){
//If you are not using java 8 code
/*String[] destFiles = destination.list();
for(String fileName : destFiles){
if(souceFileName.equals(fileName))
return true;
}
return false;*/
return Arrays.stream(destination.list())
.anyMatch(fileName -> fileName.equals(souceFileName));
}
public static void main(String[] args) throws IOException {
try {
if(!source.isDirectory())
throw new IllegalArgumentException("Source Folder doesn't Exist");
if(!destination.exists())
destination.mkdir();
if (source.isDirectory() && destination.isDirectory()) {
File[] content = source.listFiles();
for (int i = 0; i < content.length; i++) {
System.out.println(content[i]);
move(content[i], destination);
}
}
} catch (Exception ex) {
System.out.println(ex);
} finally {
}
}
}```

When is a Windows folder available to Java's `File#list`?

I have some Java code that does this (on a Windows 10 laptop with Windows Defender on):
unzip a .zip file into a folder (using a zip stream)
immediately list the folder's contents (using File#list)
There are ten files in the zip, from 100kB to 40MB. Normally only the first two files are listed -- the other 8 are silently lost. I know they actually make it to the directory because I can see them when I navigate to the directory myself.
I know there are better ways to implement this code, but I'm curious: is this expected? Is "write file into folder" and "file is listed when you list folder contents" not atomic on Windows? Is it a quirk of the underlying file system? Does Windows Defender make the file invisible for some period of time after it's written?
I am not facing the issue you mentioned and my code is able to list all the files correctly:
package com.test;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipTest {
private static final int BUFFER_SIZE = 4096;
private static String INPUT_LOCATION = "C:/temp/zip/test.zip";
private static String OUTPUT_LOCATION = "C:/temp/unzip";
public static void main(String[] args) throws IOException {
unzip(INPUT_LOCATION, OUTPUT_LOCATION);
for (String s : new File(OUTPUT_LOCATION).list()) {
System.out.println(s);
}
}
public static void unzip(String zipFilePath, String destDirectory) throws IOException {
File destDir = new File(destDirectory);
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
extractFile(zipIn, filePath);
} else {
File dir = new File(filePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] bytesIn = new byte[BUFFER_SIZE];
int read = 0;
while ((read = zipIn.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
bos.close();
}
}

Extend filelock even the program is not running

Im having trouble with the files that I want to lock permanently. My program can lock the files but when I exit the program (the program is not running) the lock will be release. I want to lock files even the program is not running, is it possible? here's my code. Please help me
import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import javax.swing.JOptionPane;
import static com.sun.nio.file.ExtendedOpenOption.NOSHARE_DELETE;
import static com.sun.nio.file.ExtendedOpenOption.NOSHARE_READ;
import static com.sun.nio.file.ExtendedOpenOption.NOSHARE_WRITE;
import java.nio.channels.FileLock;
public class LockFile {
public static void ProcessPackageFiles2(File Path) {
try {
File[] files = Path.listFiles();
for (File file : files) {
if (!file.isDirectory()) {
LockDown(file.getCanonicalPath());
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void LockDown(String FilePath) {
try {
Path path = FileSystems.getDefault().getPath(FilePath);
FileChannel locks = FileChannel.open(path, NOSHARE_WRITE, NOSHARE_DELETE, NOSHARE_READ);
FileLock fileLock = locks.tryLock();
if (fileLock != null) {
System.out.println("Locked");
} else {
JOptionPane.showMessageDialog(null, "FAILED");
}
} catch (Exception ex) {
System.out.println(ex);
}
}
public static void main(String[] args) {
ProcessPackageFiles2(new File(path);
}
this is the result when I run the program. The file will be unreadable and
cannot be shared and deleted. But I want to extend it even the program is not
running. But the question is HOW

Read from file inside Eclipse Project

I want to make an application that splits a big text file inside inputfolder into several small XML files to be put inside outputfolder.
This is project outline:
The following code works fine when it comes to getting a file from an outside folder, but when I modified it to read from a folder inside the project, it gave me this error:
Exception in thread "main" java.lang.NullPointerException
at com.zakaria.cut.XmlCutter.cut(XmlCutter.java:45)
at com.zakaria.cut.Main.main(Main.java:8)
[XmlCutter.java]
package com.zakaria.cut;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.MessageFormat;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class XmlCutter {
private static final String OUTPUT_FILE_NAME = "/file";
//private static String USER_HOME = System.getProperty("user.home");
private static final String INPUT_FOLDER = "../inputfolder";
private static String OUTPUT_FOLDER = "../outputfolder";
private static Logger LOG = Logger.getLogger("XmlCutter");
private static long COUNTER = 0;
public XmlCutter() {
super();
// TODO Auto-generated constructor stub
}
public void cut() {
Handler h = new ConsoleHandler();
h.setLevel(Level.FINE);
LOG.addHandler(h);
LOG.setLevel(Level.FINE);
File inputDir = new File(INPUT_FOLDER);
File[] filesInInputDir = inputDir.listFiles();
for (File f : filesInInputDir) {
if ((f.getName()).endsWith(".txt")) {
LOG.fine((MessageFormat.format(
"Found a text file {0}. Processing docs...",
f.getName())));
processFile(f);
}
}
}
private static void processFile(File f) {
StringBuilder out = new StringBuilder();
char prev = '#';
try {
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(f), "UTF8"));
char[] buf = new char[1];
while (br.read(buf) >= 0) {
out.append(buf[0]);
if (prev == '<' && buf[0] == '?') {
LOG.finest((MessageFormat.format(
"Start of XML PI Found: {0}{1}", prev, buf[0])));
if (out.length() > 2) {
flushToFile(out.substring(0, out.length() - 2));
}
out.setLength(2);
}
prev = buf[0];
}
LOG.finest("Writing final file");
flushToFile(out.toString());
br.close();
} catch (IOException e) {
LOG.fine(e.getMessage());
}
LOG.fine(MessageFormat.format("Generated {0} XML Documents", COUNTER));
}
private static void flushToFile(String s) {
File f = new File(OUTPUT_FOLDER + OUTPUT_FILE_NAME + (++COUNTER)
+ ".xml");
LOG.finest(MessageFormat.format("Writing file: {0}", f.getName()));
try {
FileOutputStream fos = new FileOutputStream(f);
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8");
osw.write(s);
osw.flush();
} catch (IOException e) {
LOG.fine(e.getMessage());
}
}
}
[Main.java]
package com.zakaria.cut;
public class Main {
public static void main(String[] args) {
XmlCutter cutter = new XmlCutter();
cutter.cut();
}
}
The problem, I guess, is definitely here:
private static final String INPUT_FOLDER = "../inputfolder";
private static String OUTPUT_FOLDER = "../outputfolder";
How can I fix it?
Do you know what folder the program is executing from? My guess is the relative links are pointing to the wrong spot? Have you tried hard coding the paths and see if they work? If they do you might have to look at the your execution folder and then change the relative paths accordingly?

Categories