tempfile gives wrong absolutepath after renameto - java

I'm changing contents of a file, therefore I read a file line by line, replace what I want and write line by line to a tempfiles. When the whole file is processed, I delete the original file, and rename the tempfile to the original filename.
like this
File orginialFile = new File("C:\\java\\workspace\\original.xml");
File tempFile = File.createTempFile("tempfile", ".tmp", new File(C:\\java\\workspace\\"));
while ((str_String = reader.readLine()) != null) {
//read lines and replace and write lines
}
orginialFile .delete();
tempFile.renameTo(new File("C:\\java\\workspace\\original.xml"));
After this is done, I request the absolutepath (tempFile.getAbsolutePath();) of the temp file. But this gives me
c:\java\workspace\tempfile3729727953777802965.tmp (the number changes every run of the program) in stead of c:\java\workspace\original.xml
How come?
I debugged it and just before the moment that I request the absolutepath, I checked in c:\java\workspace (windows explorer) and there is no tempfile. Only original file.
So the process runs correctly, I just wanted to know why it is not showing the renamed absolutepath. (I would use it for logging)
Thx

In the documentation of java.io.File, before the Interoperability with java.nio.file package:
Instances of the File class are immutable; that is, once created, the abstract pathname represented by a File object will never change.
So it won't show the renamed absolutepath.

There is a missing reader.close() before the delete. Likely edited out for us. Also you can do:
tempFile.renameTo(originialFile);

Have you checked the return value from renameTo()? I suspect it to be false.
Also pay attention to the api documentation. It states that a lot of things can go wrong - e.g. moving between file systems.
You might be better off with Files.move

Related

In what situation is a file placed in the resources of a JAR, but is not accessible in a class' ClassLoader?

I'm just trying to read in a simple .txt file into my java project using this.class.getResourceAsStream(filename). I have several files within main/resources, and almost all of them return an object when I try to get them as an input stream. The only object I can't read in is my text file.
I have placed the file with all of the other resource files that are readable by the classloader, but it appears this file wasn't placed in the class' classLoader for whatever reason. If I unzip the jar, the file is still included with the jar in the same directory as all of the other resources, so it seems to be being built correctly.
I guess what I'm asking is at what point do I tell Java what files I want to be included as a resource in a class' ClassLoader? Is it something that should be done when the jar is built if things are in the correct place (i.e main/resources)?
Here is what the code looks like, and it's respective return values, when running for the file it can find and the file it can't, that are both located in the same place.
// This is not found. Both are placed at src/main/resources
def tmpDict = this.class.getResourceAsStream("dict.txt")
println tmpDict // null
// This is found
def tmpDict2 = this.class.getResourceAsStream("calc.config")
println tmpDict2 // sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream#2dae5a79
Without more info i'd say the path is wrong. when i used just "file.txt" for the path it got NPE
i used this method to read from the stream. The file was located at \src\main\resources\static\file.txt
This worked in eclipse, packaged into jar and worked there too.
public String getFile() throws Exception {
InputStream in = Controller.class.getClassLoader().getResourceAsStream("static/file.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in, Charset.defaultCharset()));
StringBuilder out = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
out.append(line);
}
return out.toString();
}
Some very Basic checks:
The file must be case-sensitive (as it is not a Windows file), and special characters of the file name might be cumbersome. Also check that the file in your project has the file extension not twice (.txt.txt - Windows hiding the extension).
Check that getResourceAsStream("/a/b/c/A.txt") indeed gives a null.
If not the reading might go wrong on the encoding.

Robovm Read and write to a file

I try to write a text to a file and read this text later. When I use FileWriter I become a NullPointerException?
Is that a permission problem or ...? I also try the PrintWriter but I see the same Exception
.
This my code:
FileWriter fw = new FileWriter(new File("file.file"));
fw.write("XYZ");
best regards
londi
I guess your problem is that you use a relative file path, but that the origin of the relative path is not the one you think.
First of all, try to use an absolute path, that would be, on linux-like machines something like /home/me/myCode/myfile.txt or on windows something like c:/some/path/myfile.txt
Another thing you can do, in order to know what happens is print the origin.
File origin = new File(".");
System.out.println(origin.getAbsolutePath());
Once you know where the origin is, you can see what you need in order to get to your file.
Hope it will help.
Sounds like a permission issue. On iOS your application lives within a security sandbox, so you cannot just randomly read and write files anywhere you want. You could either use File.createTempFile to create a temp file somewhere hidden you your sandbox where nothing else can see it, or use the native api to determine where to dump your files. The following example will give you a file reference to the Documents Directory folder:
NSArray nsa = NSFileManager.defaultManager().URLsForDirectory$inDomains$(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask);
NSURL nsu = (NSURL)nsa.getFirst();
String snsu = nsu.getAbsoluteString() + "MyNewDocument.pdf";
File newFile = new File(new URI(snsu));

WatchService WatchEvent .context() method returns inconsistent relative path for file on ENTRY_MODIFY (goutputstream-####, Linux OS)

In this code, I'm hoping to update a HashMap with the most recent version of a given path's contents, with the absolute path as string being used as the key.
The problem is that WatchEvent's .context() method is giving me a different relative path for the same file on each event.
Here is a snippet of code:
else if(event.kind()==StandardWatchEventKinds.ENTRY_MODIFY)
{
/*Variable path is a Path of "//workspaces", set earlier.*/
Path oldfilepath=path.resolve((Path)event.context()); /*problem line*/
String oldfilepathstring = oldfilepath.toString();
FileReader oldIn = new FileReader(oldfilepathstring);
BufferedReader br = new BufferedReader(oldIn);
String line;
List<String> newfiletext=new LinkedList<>();
while((line = br.readLine())!=null)
newfiletext.add(line);
List<String> previousText=new LinkedList<>();
if((previousText = fileMappings.get(oldfilepathstring))!= null)
{
System.out.println("previoustext:\n"+previousText);
System.out.println("newfiletext:\n"+newfiletext);
}
fileMappings.put(oldfilepathstring, newfiletext);
System.out.println(fileMappings.keySet()+"\n"+fileMappings.values());
}
}
And here is sample output upon modifying the file b.txt in the watched directory from
contents
"abc"
to
"abc
123"
Note that all of this comes simply from opening file /workspaces/b.txt (which already exists) and modifying its contents.):
run:
ENTRY_CREATE:.goutputstream-BRC1HX
ENTRY_MODIFY:.goutputstream-BRC1HX
[/workspaces/.goutputstream-BRC1HX]
[[]]
ENTRY_MODIFY:.goutputstream-BRC1HX
previoustext:
[]
newfiletext:
[abc]
[/workspaces/.goutputstream-BRC1HX]
[[abc]]
ENTRY_CREATE:b.txt~
ENTRY_CREATE:b.txt
ENTRY_CREATE:.goutputstream-MFJ6HX
ENTRY_MODIFY:.goutputstream-MFJ6HX
[/workspaces/.goutputstream-MFJ6HX, /workspaces/.goutputstream-BRC1HX]
[[], [abc]]
ENTRY_MODIFY:.goutputstream-MFJ6HX
previoustext:
[]
newfiletext:
[abc, 123]
[/workspaces/.goutputstream-MFJ6HX, /workspaces/.goutputstream-BRC1HX]
[[abc, 123], [abc]]
ENTRY_CREATE:b.txt~
ENTRY_CREATE:b.txt
The line of interest is
Path oldfilepath=path.resolve((Path)event.context());
Note how oldfilepath has resolved to "/workspaces/.goutputstream-MFJ6HX", and later "/workspaces/.goutputstream-BRC1HX" for the same file.
event.context() is returning a different path for the same file after each modification.
Is this a Linux issue, or a Java issue, and how exactly do I get a standard relative path (in this case, it'd be "b.txt") for this file?
It seems that when I perform a modify, I'm getting a sequence of create/modify/create events, and the ENTRY_CREATEs have the correct filename, wile the ENTRY_MODIFYs have a temp handle (I'm guessing to a temp version of the file used between saves.) I need to be able to capture file modification and pull the correct filename out of that event.
I understand that my filesystem may be doing temp file creation & processing under the hood while I'm just opening, modifying and saving the file, but how exactly do I extract proper filename out of the temp file that the event indicating ENTRY_MODIFY gives me? Is there some sort of method to group the events pertaining to this modify, so that I can just find the enclosing ENTRY_CREATE and get the filename from that? Or somehow traverse upward through the stack of calls leading to this ENTRY_CREATE?
I can see the filename in the enclosing ENTRY_CREATE events, surrounding each ENTRY_MODIFY, but I'm hoping that there's a more elegant way to do this than to somehow (get most recent event that wasn't ENTRY_MODIFY, and then get .context() from that.)
Thanks!
I faced the same question. I think it has nothing to do with any Linux problem or any Java issues. It is just the way the editor of b.txt (I assume gedit) handles the thing.
Upon save it
creates a new temp file ".goutputstream-xxxx" with some random xxxx (the create you see),
writes the new content to this file (the modify you see),
renames the original file to b.txt~ (the create you see),
and renames the temp file to b.txt (the create you see)
So I guess you have to watch out for both ENTRY_MODIFY and ENTRY_CREATE with respect to b.txt to really see all the file modifications.
I have the same issue. I use filter to exclude this problem.
For example: I need all files in the path /home/user/data/in;
Files.walk(Paths.get( System.getProperty("user.home").concat("/data/in")))
.map(Path::toString)
.filter(path -> ! path.endsWith("/in"))
.filter(path -> ! path.startsWith(".goutputstream"))
.collect(Collectors.toList());
This fix for me.

Java: Efficient way to scan a folder for a particular file

I am contacting an external services with my Java app.
The flow is as follow: ->I generate an XML file, and put it in an folder, then the service processes the file and return another file with the same name having an extension .out
Right now after I put the file in the folder I start with a loop, until I get that file back so I can read the result.
Here is the code:
fileName += ".out";
File f = new File(fileName);
do
{
f = new File(fileName);
} while (!f.exists());
response = readResponse(fileName); // got the response now read it
My question comes here, am I doing it in the right way, is there a better/more efficient way to wait for the file?
Some info: I run my app on WinXP, usually it takes the external service less than a second to respond with a file, I send around 200 request per day to this services. The path to the folder with the result file is always the same.
All suggestions are welcome.
Thank you for your time.
There's no reason to recreate the File object. It just represents the file location, whether the file exists or not. Also you probably don't want a loop without at least a short delay, otherwise it'll just max out a processor until the file exists. You probably want something like this instead:
File file = new File(filename);
while (!file.exists()) {
Thread.sleep(100);
}
Edit: Ingo makes a great point in the comments. The file might not be completely there just because it exists. One way to guarantee that it's ready is have the first process create a second file after the first is completely written. Then have the Java program detect that second file, delete it and then safely read the first one.

How to read from a file that has no extension in Java?

So basically say i have a file that is simply called settings, however it has no extension, but contains the data of a text file renamed.
How can i load this into the file() method in java?
simply using the directory and file seems to make java think its just a directory and not a file.
Thanks
In Java, and on unix, and even on the filesystem level on windows, there is no difference in if a file has an extension or not.
Just the Windows Explorer, and maybe its pendants on Linux, use the extension to show an appropriate icon for the file, and to choose the application to start the file with, if it is selected with a double click or in similar ways.
In the filesystem there are only typed nodes, and there can be file nodes like "peter" and "peter.txt", and there can be folder nodes named "peter" and "peter.txt".
So, to conclude, in Java there is really no difference in file handling regarding the extension.
new File("settings") should work fine. Java does not treat files with or without extension differently.
Java doesn't understand file extensions and doesn't treat a file any differently based on its extension, or lack of extension. If Java thinks a File is a directory, then it is a directory. I suspect this is not what is happening. Can you try?
File file = new File(filename);
System.out.println('\'' + filename + "'.isDirectory() is "+file.isDirectory());
System.out.println('\'' +filename + "'.isFile() is "+file.isFile());
BTW: On Unix, a file file. is different to file which is different to FILE. AFAIK on Windows/MS-DOS they are treated as the same.
The extension should not make a difference. Can you post us the code you are using? And the error message please (stack trace).
Something along these lines should do the trick (taken from http://www.kodejava.org/examples/241.html)
//
// Create an instance of File for data file.
//
File file = new File("data");
try {
//
// Create a new Scanner object which will read the data
// from the file passed in. To check if there are more
// line to read from it we check by calling the
// scanner.hasNextLine() method. We then read line one
// by one till all line is read.
//
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}

Categories