In Java I want to create a file from and save the data on it. The File name with path is taken from user. Now if user give invalid path like C:\temp\./user\fir/st.csv which is an invalid path because "." and / are in the path and on windows operating system "\" is used as path separator.
Before executing the program(a command line tool), there was no temp folder in C:\ directory, but when I run the program it creates temp folder then in temp it creates user then in user it create fir folder and finally st.csv in it. While I want that if such type of invalid path or file name is given by the user user should be noticed by message "Invalid path or file name".
What should I do? Program code is like below:
public class FileTest {
public static void main(String args[]) {
try {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please enter path:");
String path = br.readLine();
File file = new File(path);
String path1 = file.getParent();
File file2 = new File(path1);
if (!file2.exists()) {
System.out.println("Directory does not exist , So creating directory");
file2.mkdirs();
}
if (!file2.exists()) {
System.out.println("Directory can not be created");
} else {
FileWriter writer = new FileWriter(file);
PrintWriter out = new PrintWriter(writer);
System.out.println("Please enter text to write on the file, print exit at new line to if finished");
String line = "";
while ((line = br.readLine()) != null) {
if (line.equalsIgnoreCase("exit")) {
System.out.println("Thanks for using our system");
System.exit(0);
} else {
out.println(line);
out.flush();
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Now if I give the path as C:\tump\./user\fir/st.csv then it create tump folder in C drive , then user in tump, then fir in user folder then st.csv file in it.
boolean exists = (new File("filename")).exists();
if (exists) {
// File or directory exists
} else {
// File or directory does not exist
}
PLUS: You must never use hard-coded path separators. You're having problems by that, use instead the static attributes
File.separator - string with file separator
File.separatorChar - char with file separator
File.pathSeparator - string with path separator
File.pathSeparatorChar - char with path separator
Looks very similar to this:
Is there a way in Java to determine if a path is valid without attempting to create a file?
There's a link in one of the answers to here:
http://www.thekua.com/atwork/2008/09/javaiofile-setreadonly-and-canwrite-broken-on-windows/
Which details what could possibly work for you:
By Peter Tsenga
public static boolean canWrite(String path) {
File file = new File(path);
if (!file.canWrite()) {
return false;
}
/* Java lies on Windows */
try {
new FileOutputStream(file, true).close();
} catch (IOException e) {
LOGGER.info(path + ” is not writable: ” + e.getLocalizedMessage());
return false;
}
return true;
}
You mention this is a command line tool. Does that mean it will be always run from the command line, or could it be called from an environment that presumes no further user interaction (like batch file or by Ant)?
From a command line, it is possible to pop a JFileChooser. This is a much better way to accept a file name from the user. It is easier for the user, and more reliable for the program.
Here is an example based on your code:
import java.io.*;
import javax.swing.*;
public class FileTest {
public static void main(String args[]) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
JFileChooser fileChooser = new JFileChooser();
int returnVal = fileChooser.showOpenDialog(null);
if (returnVal==JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try {
if (!file.getParentFile().exists()) {
System.out.println("Directory does not exist, creating..");
file.getParentFile().mkdirs();
}
if (!file.getParentFile().exists()) {
System.out.println("Directory can not be created");
} else {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
FileWriter writer = new FileWriter(file);
PrintWriter out = new PrintWriter(writer);
System.out.println("Please enter text to write on the file," +
" print exit at new line to if finished");
String line = "";
while ((line = br.readLine()) != null) {
if (line.equalsIgnoreCase("exit")) {
System.out.println("Thanks for using our system");
System.exit(0);
} else {
out.println(line);
out.flush();
}
}
}
}
catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("Maybe next time..");
}
}
});
}
}
Note that if I were coding this, I'd then go on to get rid of the InputStreamReader and instead show the text in a JTextArea inside a JFrame, JDialog or (easiest) JOptionPane, with a JButton to invoke saving the edited text. I mean, a command line based file editor? This is the 3rd millennium (damn it!).
In my case which I required this works
if(!path.equals(file.getCanonicalPath())){
System.out.println("FAILED:Either invalid filename, directory or volume label , syntax error");
System.exit(0);
}
By adding this code just after File file=new File(path); it will work fine and will notice the user if given path is incorrect
As there is only two options either java will create the file on some path which will be canonical path or if not able to create the file it will give exception. So if there is any mismatch in the path given by the user and canonical path then it means user type wrong path which java can not create on the file system, so we will notice the user, or if java give exception then we can catch it and will notice the user for incorrect path
Related
I have a set of words and an outside file.
I want to check if a word in the set is already present in the outside file. If the word is already in the file, then do nothing, if the word is not in the outside file already, then add it to the outside file.
This is the code I have written:
public static void toFile(Set<String> vocab, String filename)
{
try
{
for(String vocabWord : vocab)
{
File file = new File(filename);
Scanner sc2 = new Scanner(file);
while(sc2.hasNextLine())
{
String docWord = sc2.nextLine();
if (!(vocabWord.equals(docWord)))
{
FileWriter myWriter = new FileWriter(filename, true);
PrintWriter printWriter = new PrintWriter(myWriter);
printWriter.println(vocabWord);
printWriter.close();
}
else
break;
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
I am using three different text documents to test it, have the line "test file one", "test file two", and "test file three".
The output I was expecting was: "test file three" (it is connected with a stop list which one and two are part of, and has been working)
However, when I run it, either with only one of the files or all three consecutively, the file always comes out empty.
I tried changing up things in the method, but nothing has worked, I either get an infinite loop or nothing in the outside file.
I am not sure what I am missing... I would really appreciate any help.
I tried this and added some comments for explanation. I have tested on local machine and it works
public static void toFile(Set<String> vocab, String filename) {
try {
for(String vocabWord : vocab) {
//task for each String in our Set
File file = new File(filename);
Scanner sc2 = new Scanner(file);
boolean exists = false;//lets say it doesn't exist
while(sc2.hasNextLine()) {
//task for each line in the text
//search the whole file first for the word
String docWord = sc2.nextLine();
if (docWord.equals(vocabWord)){
exists = true;
break;
}
}
if (!exists) {
//add the vocabWord only if it doesnt exists
FileWriter myWriter = new FileWriter(filename, true);
PrintWriter printWriter = new PrintWriter(myWriter);
printWriter.println(vocabWord);
printWriter.close();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
To append the missing vocabulary in order of vocab, you can reduce the file operations
as such:
public static void toFile(Set<String> vocab, String filename) {
try {
Charset charset = Charset.defaultCharset();
Path path = Paths.get(filename);
Set<String> existing = Files.lines(path, charset)
.collect(Collectors.toSet());
if (!existing.isEmpty()) {
try (BufferedWriter bw = Files.newBufferedWriter(path, charset,
StandardOpenOption.APPEND);
PrintWriter printWriter = new PrintWriter(bw)) {
vocab.stream()
.filter(word -> !existing.contains(word))
.forEach(word -> printWriter.println(word));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
I have created a program where there is a file called groups.txt. This file contains a list of names. To delete a group, it has to exist within the file. I used the Scanner method to search through each line for the name. If it contains the line, it sets val as 1. Which triggers the val == 1 condition. What I wanted to do during this block, is try to delete groupName from the groups.txt file. To do this, I created a new txt file called TempFile which copies all the names from groups.txt EXCEPT groupName. This file is then renamed to groups.txt and the old groups.txt file is deleted.
Everything works as intended, except the renaming. The temp.txt file still exists and the groups.txt file is unchanged. I checked the boolean success, and it always returns as false. Any ideas how to solve this?
if (method.equals("delete group")){
int val = 0;
String groupName = myClient.readLine();
try {
Scanner file = new Scanner(new File("groups.txt"));
while (file.hasNextLine()){
String line = file.nextLine();
if (line.indexOf(groupName) != -1){
val = 1;
}
}
if (val == 1){
try {
File groupFile = new File("groups.txt");
File tempFile = new File("temp.txt");
BufferedReader reader = new BufferedReader(new FileReader(groupFile));
BufferedWriter writer = new BufferedWriter(new FileWriter(tempFile));
String currentLine;
System.out.println(groupName);
while ((currentLine = reader.readLine()) != null){
String trimLine = currentLine.trim();
if (trimLine.equals(groupName)){
continue;
} else {
writer.write(currentLine + System.getProperty("line.separator"));
}
}
writer.close();
reader.close();
groupFile.delete();
boolean success = tempFile.renameTo("groups.txt");
} catch (IOException f){
System.err.println("File Not Found: " + f.getMessage());
} }
} catch (FileNotFoundException f){
System.err.println("File Not Found Exception: " + f.getMessage());
}
}
CODE BEFORE THE ABOVE:
if (command.equals("group")){
String method = myClient.readLine();
if (method.equals("create group")){
String groupName = myClient.readLine();
int val = 0;
try {
Scanner file = new Scanner(new File("groups.txt"));
while (file.hasNextLine()){
String line = file.nextLine();
if (line.indexOf(groupName) != -1){
Report.error("group name already exists, please pick another");
val = 1;
}
}
} catch (FileNotFoundException f){
System.err.println("File Not Found: " + f.getMessage());
}
if (val == 0){
try {
PrintWriter out = new PrintWriter(new FileWriter("groups.txt", true));
out.println(groupName);
out.close();
} catch (IOException e){
Report.error("IOException: " + e.getMessage());
}
}
In the second part of the code, this is where I originally update the groups.txt file. So every time the user adds a group, it updates the groups.txt file by adding the new groupName to the end of the file. First, I make sure the groupName doesn't already exist using Scanner. myClient is a BufferedReader which reads from another class which stores what the user types in the command line.
Also do not forget to close Scanner. First you should make delete() work and make sure you know your current working directory, and write your filepath relative to it. Check with:
File file = new File("abc.txt");
System.out.println(file.getAbsolutePath());
One thing might be unrelated, also check your environment because
In the Unix'esque O/S's you cannot renameTo() across file systems. This behavior is different than the Unix "mv" command. When crossing file systems mv does a copy and delete which is what you'll have to do if this is the case. The same thing would happen on Windows if you tried to renameTo a different drive, i.e. C: -> D:
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
normally we write the file writer command with provide the file path and also the name of the text file for user.
example: create a assignment text file
FileWriter writer = new FileWriter(".......\assignment");
but is it possible that let my user to name the text file them self?
because my program need let lecturer enter bibliographic details about the key reading for an assignment, so lecturer can name the text file by the name with assignment.
Using a try-with-resources you might pass a user provided String to the FileWriter(String) constructor with something like,
public static void main(String[] args) {
System.out.println("Please enter a file name: ");
Scanner scan = new Scanner(System.in);
String str = scan.next();
try (FileWriter writer = new FileWriter(str)) {
} catch (IOException e) {
e.printStackTrace();
}
}
Edit
To use a file in the user's home directory, you might use
try (FileWriter writer = new FileWriter(new File(
System.getProperty("user.home"), str))) {
} catch (IOException e) {
e.printStackTrace();
}
I guess your writing a console application, not a GUI one.
In this case use something like the following:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;
public class FileChooser {
public static void main(String[] args) throws IOException {
FileWriter writer = new FileWriter(chooseFile());
// Use your FileWriter
}
public static File chooseFile() {
String fname = null;
File file = null;
System.out.println("Please choose file name:");
while (true) {
try (Scanner in = new Scanner(System.in)) {
// Reads a single line from the console
fname = in.nextLine();
file = new File(fname);
if (!file.createNewFile()) {
throw new RuntimeException("File already exist");
}
break;
} catch (Exception ex) {
System.out.println(ex.getMessage() + ", please try again:");
}
}
return file;
}
}
EDIT
If you are writing a Swing GUI, you can use JFileChooser:
//Create a file chooser
final JFileChooser fc = new JFileChooser();
int returnVal = fc.showSaveDialog(parentComponent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
File file = fc.getSelectedFile();
} else {
// User canceled the file chooser.
}
You can use Scanner to get the file name from the keyboard. If you are using command prompt for taking file name then you can use the following code -
Scanner input = new Scanner(System.in);
String fileName = input.next();
Then pass the 'fileName' to the PrintWriter constructor.
PrintWriter writer = new PrintWriter(fileName);
writer.close();
I have a file that contains score data for a game (the player name and their final score.
I want to open the file and have the data contained to be displayed so that it would look something like
PLAYER SCORE
------ -----
John 1000
Steve 2000
The file is definitely saving the data that I want but I cannot get it to display the data.
I have tried various things along the lines of:
public static void loadScores() {
boolean fileIsValid;
String filename = "";
File file;
do {
fileIsValid = true;
clrscr();
System.out.println("\t\t\t\t\t\t\t\t\tLEADERBOARDS");
printWave();
if (!fileIsValid) {
System.out.print("\n\nSorry, commander, your file name: " + filename + " does not exist.");
}
System.out.println("");
filename = "scores.gz";
file = new File(filename);
if (!file.exists()) {
fileIsValid = false;
}
} while (!fileIsValid);
System.out.println(file);
pressKey();
}
This is how I would do it.
public static void loadScores() {
File file = null;
try{
file = new File("scores.gz");
if (!file.exists()) {
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
fileReader.close();
} else {
System.out.print("\n\nSorry, commander, your file name: " + filename + " does not exist.");
}
}
catch(IOException e) {
e.printStackTrace();
}
}
Note: Your original code will sit in an infinite loop until the file is created! Also there is no sleep in your loop, thus you will query the file system continuously without a wait period.
This doesn't require 3rd party libraries but Apache commons has some nice util classes, also for reading files: http://commons.apache.org/proper/commons-io/description.html
I used this code in a different application to write a name and highscore onto the file for my game. Now i'm using this code to get a name and password from a .DAT file and be able to add a new user and password. Here's the .DAT file.
michael123
speaker123
katherine123
motor123
username
password
Here's the code. Reading the file works fine but writing to it does nothing at all and i'm unsure why.
InputStream file;
BufferedReader fileStream;
FileWriter fileWriter;
BufferedWriter fileWrite;
String temp = "";
int users = 0;
public void readUserInfo() throws IOException {
try {
file = Board.class.getResourceAsStream("users.DAT");
fileStream = new BufferedReader(new InputStreamReader(file));
} catch (Exception e) {
System.out.println("File not found");
}
for (int i = 0; i < users; i++) {
temp = fileStream.readLine();
Board.username[i] = temp.trim();
temp = fileStream.readLine();
Board.password[i] = temp.trim();
}
//Close
fileStream.close();
file.close();
}
public void addUser() throws IOException {
fileWriter = new FileWriter(Board.class.getResource("users.DAT").getFile(),true);
fileWrite = new BufferedWriter(fileWriter);
System.out.println("Users : " + users);
//Skip already created users
for (int i = 0; i < users; i++) {
fileWrite.newLine();
fileWrite.append(Board.username[i]);
fileWrite.newLine();
fileWrite.append(Board.password[i]);
}
System.out.println("Adding" + Board.username[users] + " : " + Board.password[users]);
//Add user
fileWrite.newLine();
fileWrite.append(Board.username[users]);
fileWrite.newLine();
fileWrite.append(Board.password[users]);
//Close
fileWrite.close();
System.out.println("Closed fileWrite");
}
I'm using netbeans. The file being read from is in the same package as all the other classes.
Maybe you have packaged your jar with some state of the file users.DAT (a defined set of users) and when you read them from classpath you see only the users from the time you have created the jar. The writing goes then to another file.
You should read the user from the filesystem too.
Check the working directory of your app there should be correct file containing the users added.
Also no need for copying all the user over and over again every time you add one, just open your file in append mode
fileWriter = new FileWriter(new File("users.DAT"), true);
Unless you want to be able to delete users, in that case keep everything in memory and save when you exit the program or explicitly with a save action.
In your reading you use file = Board.class.getResourceAsStream("users.DAT"); in your writing you just create a file new File("users.DAT") what about changing your addUser() to
public void addUser() throws IOException {
fileWriter = new FileWriter(Board.class.getResource("users.DAT").getFile());
....
}
Edit: The problem is that during writing you are not retrieving the same file as before. I would add this method
public File getUserDataFile() {
return new File(Board.class.getResource("").getFile(), "users.DATA");
}
// then use it like this
new FileWriter(getUserDataFile());
// and
new BufferedReader(new InputStreamReader(getUserDataFile()));
then access it whenever you want to read and write to your file. The problem is Board.class.getResourceAsStream("users.DAT") will return null if your file doesnt exist.