File creating under root directory, strange response - java

This is not actually a question, but I need explanation. I was trying to create directory under C:// drive. So;
try {
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "//");
File parent_z = f_paz.getParentFile();
if (null != parent_z) {
parent_z.mkdirs();
}
if (!f_paz.exists()) {
f_paz.createNewFile();
}
} catch (IOException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
I tried that and it gave me "Access Denied" error, so I tried all the solutions in the web. Nothing happened.
Strangely, I decided to put "space" after there;
File f_paz = new File("c://Ekap_Pazarlik_xml" + file_currentDate + "// ");
here
just after "// ", and it worked. I was able to crate directory like that. I have no idea why it worked like that. Please provide me some explanation. Thanks !

f_paz.createNewFile(); will try to create a new file, not a directory. Many Windows systems won't allow you to create files in directly in C: so that's why you get the exception.
Since you want to create a directory and not a file use f_paz.mkdir(); instead. You don't need the "//" at the end, btw.
What happens if you add the space, i.e. use path "C:/Ekap_xxx/ "? The system will see a path with a blank filename " " and a parent directory name "Ekap_xxx". Now parent_z will refer to "C:/Ekap_xxx" and thus parent_z.mkdirs(); will create directory "Ekap_xxx". Now f_paz.exists() will return true since the filesystem seems to decide a file with an invalid name still exists (I'd have to look for some information on why that is so, it's hidden in the native code).

Related

Writing a file to a specific directory

I've created a simple program that would write a file with a directory using the following codes:
String nameProve = nameField.getText();
String employee = ("C:\\Users\\ALLEN\\workspace32bit\\RETRIEVE_CHECKER1\\RETRIEVE_CHECKED1" + nameProve + ".txt");
PrintWriter outputStream1 = null;
try
{
outputStream1 = new PrintWriter(employeeName);
}
catch(Exception e)
{
JOptionPane.showMessageDialog(null, "Can not write to " + employeeName);
System.exit(0);
}
outputStream1.println("Employee Retrieve Executed");
outputStream1.close();
I've already exported my code to a .jar file and my code works just fine if i execute it in the computer were I've develop my program but when I copied the jar file to other computer and I also created the forlder (manually) that corresponds with the directory in my codes my program doesn't work and my catch block will show the message Can not write to "C:\Users\ALLEN\workspace32bit\RETRIEVE_CHECKER1\RETRIEVE_CHECKED1" + nameProve + ".txt"
Can anybody give me some advice on how to solve this error? Thanks!
Obviously you are the user ALLEN on your machine and run the program as that user, so everithing works fine, because you are the owner of the directory C:\Users\ALLEN.
Then you copy the jar to another machine, where the user ALLEN does not exist and you are logged in as antoher user let's say his name is Bob and create that directory unter C:\Users. You may have noticed that you when you wanted to create that directory as the user Bob windows has warned you that you need admin priviledges in order to compleate this action.
Now you try to run your program with the user Bob who has access only to his own directory C:\Users\Bob and try to write to ALLEN's own directory. So what happens is that you get an IOException telling you access denied which is good so!
You should not attepmt to write to other users private direcotries, this is a security issue.
In your code when dealing with filesystem, never hard code absolute path, always use relative paths, or if you need to defined a direcotry where all the data needed yb you program should be located, then pass ist as argument.
The simplest to do, ist use the following and work with the current working directory
String employee = "RETRIEVE_CHECKER1\\RETRIEVE_CHECKED1" + nameProve + ".txt";
You need to create the directory RETRIEVE_CHECKER1 either by hand in location where you run the program, or better yet in your program using File#mkdir and use it like this:
File employee = new File(dir, "RETRIEVE_CHECKED1" + nameProve + ".txt");
PrintWriter outputStream1 = new PrintWriter(employeeName);
Exception you catch will have all details- like access denied, directory not exist, etc. Currently you loose exception data (message, stacktrace) when catching it.
Please do something like
Do not catch just java.lang.Exception. This is too wide- will catch possible NullPointerException and present misleading message '"Can not write to'. Catch only specific exception instead- ones that are actually thrown from try block. In your case, that will be java.io.FileNotFoundException
Do not loose exception details. Print it to the standard error log, or even better use loging framework
catch block that adresses those issues:
catch(FileNotFoundException e) {
JOptionPane.showMessageDialog(null, e.getMessage());
e.printStackTrace();
}

Java: store configuration variables in a file

I'm developing a program with NetBeans 8.0 and JavaFX Scene Builder 2.0 that need store some variables in a file, where admin users can modify it when needed, (like change server IP address, or a number value from a no editable textfield) and if they close and load again the program, the changes made in variables are kept. Like any settings section of a program.
I just try do it with the Properties file, but i have problems to store it in the same folder as .jar file. When the program execute the line new FileOutputStream("configuration.properties"); the file is created at root of the disk. As the folder of the file can be stored anywhere, i not know how indicate the right path.
Creating the properties file in the package of the main project and using getClass().getResourceAsStream("configuration.properties"); i can read it but then i can not write in for change values of variables.
Is there a better method to create a configuration file? Or properties file is the best option for this case?
My other question is whether it is possible to prevent access to the contents of the file or encrypt the content?
PD: I've been testing this part of the code in Linux operating system currently, but the program will be used in Windows 7 when ready.
If you use Maven, you can store your property files in your resources folder, say resources/properties/. When you need to load them, do this:
private Properties createProps(String name)
{
Properties prop = new Properties();
InputStream in = null;
try
{
in = getClass().getResourceAsStream(name);
prop.load(in);
}
catch (IOException ex)
{
System.err.println("failed to load \"" + name + "\": " + ex);
}
finally
{
try
{
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
System.err.println("failed to close InputStream for \"" + name + "\":\n" + FXUtils.extractStackTrace(ex));
}
}
return prop;
}
Where name is the full path to your properties file within your resources folder. For example, if you store props.properties in resources/properties/, then you would pass in properties/props.properties.
I am not 100% sure if you can carry over this exact procedure to a non-Maven project. You'd need to instruct whatever compiler tool you are using to also include your property files.
As far as your final question goes, in regards to encrypting your properties, I would consider posting that as a separate question (after having done thorough research to try to discover an existing solution that works for you).
At last i found how obtain the absolute path from folder where is .jar file to create properties file in, and read/write it. Here is the code:
File file = new File(System.getProperty("java.class.path"));
File filePath = file.getAbsoluteFile().getParentFile();
String strPath = filePath.toString();
File testFile = new File(strPath+"/configuration.properties");
Tested in Ubuntu 13.04 And Windows 7 and it works.
For encrypt the properties values i found this thread that answer how do it.

Reading .txt File From Relative Path in Java

I know this question has been asked in a myriad of variations, but today I wish to emphasize one particular scenario when one wishes to read from a .txt file without specifying the absolute path.
Suppose we have the following set up in Eclipse.
projectName/packageName/subPackage/
and we have a class named Read.java inside the subPackage. The class will be attempting to read from the input1.txt.
We also have input1.txt inside the very same subPackage.
If one uses absolute paths, the code inside Read.java will be something of the following (let's assume now that input1.txt is placed on my Desktop for illustration purposes):
// Create a list to store the list of strings from each line of the input1.txt.
LinkedList<String> inputStrings = new LinkedList<String>();
BufferedReader bufferedTextIn = null;
try {
String line;
// Specify the file
String fileName = "C:" + File.separator
+ "Users" + File.separator
+ "Kevin" + File.separator
+ "Desktop" + File.separator
+ "input1.txt";
bufferedTextIn = new BufferedReader(new FileReader(fileName));
while ((line = bufferedTextIn.readLine()) != null) {
inputStrings.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedTextIn != null) {
bufferedTextIn.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
The problem with the above is the use of absolute paths to my desktop. If I passed the code to my friend, he would need to manually change the path to his desktop. Even if I put input1.txt in my project folder, my friend would still need to manually change the path to make it work.
Note that using File.separator is a good practice because different OS interprets separators a bit differently, but it is still insufficient.
So what do we do instead?
Here is my solution.
String fileName = Read.class.getResource("input1.txt").getPath();
System.out.println(fileName);
bufferedTextIn = new BufferedReader(new FileReader(fileName));
Let's recap the scenario. We have our input1.txt file placed in the SAME FOLDER as the Read.java. So, the code above attempts to go to where Read.class exists (which is somewhere in the bin folder in Eclipse), and look for input1.txt. This is the path RELATIVE to where Read.class is located (in this case, it is trivially in the same folder, but you could very well specify another folder relative to where Read.class is located). The print statement lets you know exactly where it is located and is a good practice while debugging.
When you build in Eclipse, the .java files in the src folder would be compiled into .class files and be placed in the bin folder. The neat thing is that input1.txt is ALSO copied over the bin folder (and all the package hierarchies are maintained).
An important thing to note is to use getPath() rather than toString(), because the latter will add some extra text to the front of the path (I only knew that because I printed it out) and thus you get a NULL pointer exception because the fileName was not formatted correctly.
Another important thing to note is that I used Read.class.getResource("input1.txt").getPath(); instead of this.getClass().getResource("input1.txt").getPath(); because the code was called in a static context (in my main method). If you create an object, then feel free to use the latter.
If you're interested in more advanced features, you can check out the link below:
What is the difference between Class.getResource() and ClassLoader.getResource()?
I hope this helps!
Edit:
You could use the following to get the directory where Read.class resides in also.
String fileName = Read.class.getResource(".").getPath();
Specifying getResource("..") would go to the parent directory.
String fileName = Read.class.getResource("..").getPath();
The above may be useful if you want to have more control specifying the path (e.g. if you want to create output.txt inside the directory where Read.class resides, use
String fileName = Read.class.getResource(".").getPath() + "output.txt";
If you knew the file was going to be located in the same folder in each system this program was run on, you could use system variables to ensure any path defined would still work with different users. For windows, I've used:
String user = new com.sun.security.auth.module.NTSystem().getName();
to get a user name. This could then be substituted in your example to be:
String fileName = "C:" + File.separator
+ "Users" + File.separator
+ user + File.separator
+ "Desktop" + File.separator
+ "input1.txt";
I'm not sure how this would work outside of Windows however.

Java 7 zipfs: File is also a folder

I've been using Java 7's ZipFS support.
https://gist.github.com/stain/5591420
shows the behaviour, which I find a bit odd. Basically you can create a ZIP file system, make a file with a given name, and then also make a folder with the same name.
The reason for this seems to be that internally the folder gets "/" appended to its name - however this new name is not returned, therefore you end up in a strange situation where Files.isDirectory() returns false immediately after a successful Files.createDirectory().
try (FileSystem fs = tempZipFS()) {
Path folder = fs.getPath("folder");
Files.createFile(folder);
assertTrue(Files.isRegularFile(folder));
assertFalse(Files.isDirectory(folder));
// try {
Files.createDirectory(folder);
// } catch (FileAlreadyExistsException ex) {
// Is not thrown!
// }
// but a second createDirectory() fails correctly
try {
Files.createDirectory(folder);
} catch (FileAlreadyExistsException ex) {
}
// Look, it's both a file and folder!
Path child = folder.resolve("child");
Files.createFile(child);
// Can this be tested?
assertTrue(Files.isRegularFile(folder));
// Yes, if you include the final /
assertTrue(Files.isDirectory(fs.getPath("folder/")));
// But not the parent
// assertTrue(Files.isDirectory(child.getParent()));
// Or the original Path
// assertTrue(Files.isDirectory(folder));
}
So as long as you have the "/" as the suffix, you can even work with both, and that's how they are listed if you do a directory listing of the root.
Now the ZIP format itself allows this as it only deals with entries in a ZIP file (even allowing multiple entries with the same name), however normal use of a "FileSystem" would normally not allow multiple entries with the same name ; as can be seen when I try to create the folder twice.
The produced ZIP file can be browsed correctly with infozip, 7Zip and Windows 8; but trying to unzip will obviously fail because the native file system don't support such duality.
So is this a feature, bug or something in between?

where to place sound files relative to a java project?

This is the first time I've implemented sounds but I can't figure out where to actually place the sounds to play them. I am using Eclipse as my IDE and I've put my sounds in a folder called sounds.
The following code is what I've used to create one of the audioclip objects:
private final String background = "." + slash + "sounds" + slash + "background.wav";
main(....){
try {
backgroundClip = Applet.newAudioClip(new File(background).toURI().toURL());
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I don't hear anything. When I remove the try/catch I get an error saying that it is unable to find the file. I placed my sound folder in both /src and /bin but neither can find it. where do I put it?
The base for your project is the level above the src folder. So using . will put you at your project folder.
Basically,
. = project_root
./src = default_package
./src/packagename = inside the package named "packagename"
./sounds/background.wav = a .wav file in the sounds folder, in the project_root
Using your current path, you need to put your .wav file in the sounds folder in the project_root.
The path will end up being project_root/sounds/background.wav.
See this thread to understand why application resources should be obtained by URL obtained from getResource(), rather than a File converted to an URL.

Categories

Resources