I am trying to remove the last line of a CVS file, to do so I need to rename / delete my input file, I tried several things, but I can't get it to work, this is what I got now:
File inputFile = new File((file.getParent() + "/ExportLijst " + dateFormat.format(date) + ".csv"));
inputFile.setWritable(true, true);
File f = (inputFile);
if (!f.exists())
throw new IllegalArgumentException(
"Delete: no such file or directory: " + inputFile);
if (!f.canWrite())
throw new IllegalArgumentException("Delete: write protected: "
+ inputFile);
if (f.isDirectory()) {
String[] files = f.list();
if (files.length > 0)
throw new IllegalArgumentException(
"Delete: directory not empty: " + inputFile);
}
boolean success = f.renameTo(removeFile);
if (!success)
throw new IllegalArgumentException("Delete: deletion failed");
I also tried this, with no result:
public void forceRename(File source, File target) throws IOException
{
if (target.exists())
target.delete();
source.renameTo(target);
}
Most likely you did not close the file, and then the other file operations will not do on Windows.
The code snippets you have put together for us, are in this way not very coherent - of course.
They look fine, though one would need to see the context. A bit much.
So try ensuring a close:
try (PrintWriter csvOut = ...) {
...
} // Automatic close
Related
I was trying to extract the ZIP file from my Linux, I'm able to extract it, but the expected output is failing/wrong. The extract file suddenly has no files inside and the folder extracted has .zip25 extension. I searched on this, and there is saying that it is corrupted. However, I don't think it is corrupted because I am able to open and extract the zip files perfectly in local (Windows directory).
Example:
Zip file: FolderZip.zip
After extract: FolderZip.zip25 (Note: This is already extracted but still has .zip25 extension, also the files inside are missing).
Below is my code, I've worked on this for almost a month, but still can't figure it out. Can someone help me to figure out what did I do wrong?
public void unZipFolder(String zipFile, String outputFolder){
byte[] buffer = new byte[1024];
System.out.println("ZipFileLocation: " + zipFile);
LOG.info(" ZipFileLocation: " + zipFile);
File folder = new File(outputFolder);
if(!folder.exists())folder.mkdirs();
try{
FileInputStream fis = new FileInputStream(zipFile);
ZipInputStream zis = new ZipInputStream(fis);
ZipEntry ze = zis.getNextEntry();
while(ze != null) {
new File(folder.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(folder);
File newFile = new File(outputFolder + FilenameUtils.indexOfLastSeparator(ze.getName()));
if (ze.isDirectory()) {
if (!newFile.isDirectory() && !newFile.mkdirs()) {
throw new IOException("Failed to create directory " + newFile);
}else if(ze.isDirectory()){
newFile.mkdirs();
continue;
}else{
int len;
while ((len = zis.read(buffer)) >= 0) {
fos.write(buffer, 0, len);
}
System.out.println("File Unzip: " + newFile);
LOG.info(" File Unzip: " + newFile);
newFile.mkdirs();
fos.close();
zis.closeEntry();
ze = zis.getNextEntry();
}
}
boolean result = Files.deleteIfExists(Paths.get(zipFile));
if (result) {
System.out.println("ZipFile is deleted....");
} else {
System.out.println("Unable to delete the file.....");
}
}
zis.closeEntry();
zis.close();
fis.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
I'd love to be able to tell you exactly what's wrong with your code, but FileOutputStream fos = new FileOutputStream(folder); throws an exception because, well, folder is, a directory, so you can't write to it.
I'm also scratching my head over what your expecting new File(folder.getParent()).mkdirs(); to do.
I basically threw out your code and started again with...
public void unZipFolder(File zipFile, File outputFolder) throws IOException {
byte[] buffer = new byte[1024];
System.out.println("ZipFileLocation: " + zipFile);
System.out.println("outputFolder = " + outputFolder);
if (!outputFolder.exists() && !outputFolder.mkdirs()) {
throw new IOException("Unable to create output folder: " + outputFolder);
} else if (outputFolder.exists() && !outputFolder.isDirectory()) {
throw new IOException("Output is not a directory: " + outputFolder);
}
try (ZipFile zipper = new ZipFile(zipFile)) {
Enumeration<? extends ZipEntry> entries = zipper.entries();
while (entries.hasMoreElements()) {
ZipEntry ze = entries.nextElement();
File destination = new File(outputFolder, ze.getName());
if (ze.isDirectory()) {
if (!destination.exists() && !destination.mkdirs()) {
throw new IOException("Could not create directory: " + destination);
}
} else {
System.out.println("Writing " + destination);
try (InputStream is = zipper.getInputStream(ze); FileOutputStream fos = new FileOutputStream(destination)) {
// You could use is.transferTo(fos) here but I'm a grump old coder
byte[] bytes = new byte[1024 * 4];
int bytesRead = -1;
while ((bytesRead = is.read(bytes)) != -1) {
fos.write(bytes, 0, bytesRead);
}
}
}
}
}
}
Now, what's important to know about this is, it expects the directory contents of the zip files to be relative (ie no root directory information). If your zip file does contain root directory information (ie C:/... or /...), then you're going to need to clean that up yourself.
Now, if you have trouble with this, I would suggest commenting out the "extraction" portion of the code and placing in more System.out.println statements
transferTo
After reading through the code for transferTo, it's basically doing the same thing that the code example above is doing - so, if you wanted to reduce the code complexity (and reduce the risk of possible bugs), you could use it - been some what old school, I'd probably still do it the "old way" in order to provide support for progress monitoring of some kind - but that's beyond the scope of the question.
"Security issues"
This ones a little harder to tie down, as no solution is 100% safe.
I modified the above code to use something like...
Path parent = outputFolder.toPath().toAbsolutePath();
String name = "../" + ze.getName();
Path child = parent.resolveSibling(new File(outputFolder, name).toPath());
And this ended up throwing a NoSuchFileException, so, at least you could "fail fast", assuming that's what you want.
You might also consider removing .., leading / or leading path specifications in an attempt to make the path "relative", but that could become complicated as something like somePath/../file could still be valid within your use case.
I am programming a basic notepad program and I want it to be able to rename files from the command line. If the user writes "rename" to scanner, the program changes the note's file name according to input, like -rename stack. But if user enter two new note names. Program will error like Invalid note name for renaming. It contains ' '. Enter one word.. If a proposed name is used by an existing file, the program will print File already exists.
How can i do this:
-rename stack
Enter new note name?
stack over
Invalid note name for renaming. It contains 'over'. Enter one word
-rename stack
Enter new note name?
over
File already exists
This is what I've written so far:
...
else if (noteNameSplited[0].equals("rename")) {
File file = new File(noteNameSplited[1]+".ncat");
if(!file.exists()) {
System.out.println("File does not exist !");
}
else {
System.out.println("Enter the new note name");
String data=scan.nextLine();
File file2 = new File(data+".ncat");
file.renameTo(file2);
}
}
This may help you:
https://github.com/openstreetmap/osmosis/blob/master/osmosis-core/src/main/java/org/openstreetmap/osmosis/core/util/AtomicFileCreator.java#L50
if (!tmpFile.exists()) {
throw new OsmosisRuntimeException("Can't rename non-existent file " + tmpFile + ".");
}
// Delete the existing file if it exists.
if (file.exists()) {
if (!file.delete()) {
throw new OsmosisRuntimeException("Unable to delete file " + file + ".");
}
}
// Rename the new file to the existing file.
if (!tmpFile.renameTo(file)) {
throw new OsmosisRuntimeException(
"Unable to rename file " + tmpFile + " to " + file + ".");
}
You can try the following:
public boolean renameTo(File dest) {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkWrite(path);
security.checkWrite(dest.path);
}
return fs.rename(this, dest);
}
I have a piece of code to copy a specific file, I've used this functions for ages and it works properly.
The problem is that right now I'm writing a program with java awt/swing and my copyFile functions only works in debug mode...I can't understand why..
This is the error it throws:
can't copy directory: QQQ.wav
source file is unreadable: QQQ.wav
Error occoured QQQ.wav (The system cannot find the file specified)
But when I run the program in debug mode it works..!!
could anyone help me please???
Function copyFile:
public static void copyFile(File varFromFile, File varToFile) throws IOException {
// First make sure the source file exists, is a file, and is readable.
if (!varFromFile.exists())
System.err.println("no such source file: " + varFromFile);
if (!varFromFile.isFile())
System.err.println("can't copy directory: " + varFromFile);
if (!varFromFile.canRead())
System.err.println("source file is unreadable: " + varFromFile);
// If the destination is a directory, use the source file name
// as the destination file name
if (varToFile.isDirectory())
varToFile = new File(varToFile, varFromFile.getName());
// If the destination exists, make sure it is a writable file
// and ask before overwriting it. If the destination doesn't
// exist, make sure the directory exists and is writable.
if (varToFile.exists()) {
if (!varToFile.canWrite())
System.out.println("destination file is unwriteable: "
+ varToFile);
} else {
// If file doesn't exist, check if directory exists and is
// writable. If getParent() returns null, then the directory is
// the current directory. so look up the user. Directory system
// property to
// find out what that is.
// The destination directory
String varParent = varToFile.getParent();
// If none, use the current directory
if (varParent == null)
varParent = System.getProperty("user.dir");
// Convert it to a file.
File vardir = new File(varParent);
if (!vardir.exists())
System.out.print("destination directory doesn't exist: "
+ varParent);
if (vardir.isFile())
System.out
.print("destination is not a directory: " + varParent);
if (!vardir.canWrite())
System.out.print("destination directory is unwriteable: "
+ varParent);
}
// If we've gotten this far, then everything is okay.
// So we copy the file, a buffer of bytes at a time.
// Stream to read from source
FileInputStream varFromSource = null;
// Stream to write to destination
FileOutputStream VarToDestination = null;
try {
// Create input stream
varFromSource = new FileInputStream(varFromFile);
// Create output stream
VarToDestination = new FileOutputStream(varToFile);
// To hold file contents
byte[] buffer = new byte[4096];
// How many bytes in buffer
int bytes_read;
// Read until EOF
while ((bytes_read = varFromSource.read(buffer)) != -1)
VarToDestination.write(buffer, 0, bytes_read);
//System.out.println("File copied !!!");
} catch (Exception e) {
System.err.println("Error occoured " + e.getMessage());
} finally {
if (varFromSource != null) {
try {
varFromSource.close();
} catch (IOException e) {
System.err.println("Error is " + e.getMessage());
}
}
if (VarToDestination != null) {
try {
VarToDestination.close();
} catch (IOException e) {
System.err.println("Error is " + e.getMessage());
}
}
}
Method below has function to simply move files from the "working" to the "move" directory which paths it receives through the method call. It all works, but for the case when file name has name with two extensions (like .xml.md5) where the .renameTo method returns false. Is there a way to alter the below code so it would work regardless of the OS that it's run on. (Currently it is the Windows)
public void moveToDir(String workDir, String moveDir) throws Exception {
File tempFile = new File(workDir);
File[] filesInWorkingDir = tempFile.listFiles();
for (File file : filesInWorkingDir) {
System.out.println(file.getName());
if (new File(moveDir + File.separator + file.getName()).exists())
new File(moveDir + File.separator + file.getName()).delete();
System.out.println(moveDir + File.separator + file.getName());
Boolean renameSuccessful = file.renameTo(new File(moveDir + File.separator + file.getName()));
if (!renameSuccessful) throw new Exception("Can't move file to " + moveDir +": " + file.getPath());
}
}
I have simplified your code and added a check if delete was successful. Try it.
public void moveToDir(String workDir, String moveDir) {
for (File file : new File(workDir).listFiles()) {
System.out.println(file.getName());
final File toFile = new File(moveDir, file.getName());
if (toFile.exists() && !toFile.delete())
throw new RuntimeException("Cannot delete " + toFile);
System.out.println(toFile);
if (!file.renameTo(toFile))
throw new RuntimeException(
"Can't move file to " + moveDir +": " + file.getPath());
}
}
Could you please suggest how to deal with these situations ? I understand that in the second example, it is very rare that it would happen on unix, is it ? If access rights are alright. Also the file wouldn't be even created. I don't understand why the IOException is there, either it is created or not, why do we have to bother with IOException ?
But in the first example, there will be a corrupted zombie file. Now if you tell the user to upload it again, the same thing may happen. If you can't do that, and the inputstream has no marker. You loose your data ? I really don't like how this is done in Java, I hope the new IO in Java 7 is better
Is it usual to delete it
public void inputStreamToFile(InputStream in, File file) throws SystemException {
OutputStream out;
try {
out = new FileOutputStream(file);
} catch (FileNotFoundException e) {
throw new SystemException("Temporary file created : " + file.getAbsolutePath() + " but not found to be populated", e);
}
boolean fileCorrupted = false;
int read = 0;
byte[] bytes = new byte[1024];
try {
while ((read = in.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
} catch (IOException e) {
fileCorrupted = true;
logger.fatal("IO went wrong for file : " + file.getAbsolutePath(), e);
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
if(fileCorrupted) {
???
}
}
}
public File createTempFile(String fileId, String ext, String root) throws SystemException {
String fileName = fileId + "." + ext;
File dir = new File(root);
if (!dir.exists()) {
if (!dir.mkdirs())
throw new SystemException("Directory " + dir.getAbsolutePath() + " already exists most probably");
}
File file = new File(dir, fileName);
boolean fileCreated = false;
boolean fileCorrupted = false;
try {
fileCreated = file.createNewFile();
} catch (IOException e) {
fileCorrupted = true;
logger.error("Temp file " + file.getAbsolutePath() + " creation fail", e);
} finally {
if (fileCreated)
return file;
else if (!fileCreated && !fileCorrupted)
throw new SystemException("File " + file.getAbsolutePath() + " already exists most probably");
else if (!fileCreated && fileCorrupted) {
}
}
}
I really don't like how this is done in Java, I hope the new IO in Java 7 is better
I'm not sure how Java is different than any other programming language/environment in the way you are using it:
a client sends some data to your over the wire
as you read it, you write it to a local file
Regardless of the language/tools/environment, it's possible for the connection to be interrupted or lost, for the client to go away, for the disk to die, or for any other error to occur. I/O errors can occur in any and all environments.
What you can do in this situation is highly dependent on the situation and the error that occured. For example, is the data structured in some way where you could ask the user to resume uploading from record 1000, for example? However, there is no single solution that fits all here.