I'm trying to print out the usernames of a certain program into a file but PrintWriter is not printing anything on my file. I've tried everything mentioned on stackOverFlow none of them worked.
Users Class
private File usersListFile;
private PrintWriter usersListPrintWriter;
private Scanner usersListScanner;
Constructor:
Users(){
try {
this.usersListFile = new File("D:\\Dairy\\usersList.txt");
if(usersListFile.exists()){
this.usersListPrintWriter = new PrintWriter(new BufferedWriter(new FileWriter("D:\\Dairy\\usersList.txt", true)));
this.usersListScanner = new Scanner("D:\\Dairy\\usersList.txt");
}
else
System.err.println("File does not exist !");
}
catch(Exception e){
System.err.println("Error: Users Class!");
}
}
Method:
public void addToUsersList(String username){
usersListPrintWriter.print(username);
}
Main Method:
public static void main(String[] args) {
Users usersObject = new Users();
usersObject.addToUsersList("USERNAME");
}
usersListPrintWriter is buffered, so you need to flush the data (as Alexandro mentioned too).
You also likely will need to change the print into a println so newly added users are output on separate lines.
Your Scanner will not work, since you're scanning the given string, not the file content. Use new Scanner(this.usersListFile) instead.
You should also re-use your File object on the previous line: new FileWriter(this.usersListFile, true)
And I would say that having a Writer and a Scanner open on the same file at the same time is a bad idea, if it even works. You should probably just load all the users into memory and close the scanner before opening the writer, unless you have
public void addToUsersList(String username){
usersListPrintWriter.print(username);
usersListPrintWriter.flush();
}
Then, when you don't need anymore your printwriter, call close().
Related
using java 8, tomcat 8
Hi, i am loading a file using properties, but i have a check before loading which returns the same properties object if its already been loaded (not null). which is a normal case scenario but i want to know if there is any way that if any change occur in target file, and some trigger should be called and refreshes all the properties objects. here is my code.
public static String loadConnectionFile(String keyname) {
String message = "";
getMessageFromConnectionFile();
if (propertiesForConnection.containsKey(keyname))
message = propertiesForConnection.getProperty(keyname);
return message;
}
public static synchronized void getMessageFromConnectionFile() {
if (propertiesForConnection == null) {
FileInputStream fileInput = null;
try {
File file = new File(Constants.GET_CONNECTION_FILE_PATH);
fileInput = new FileInputStream(file);
Reader reader = new InputStreamReader(fileInput, "UTF-8");
propertiesForConnection = new Properties();
propertiesForConnection.load(reader);
} catch (Exception e) {
Utilities.printErrorLog(Utilities.convertStackTraceToString(e), logger);
} finally {
try {
fileInput.close();
} catch (Exception e) {
Utilities.printErrorLog(Utilities.convertStackTraceToString(e), logger);
}
}
}
}
the loadConnectionFile method executes first and calls getMessageFromConnectionFile which has check implemented for "null", now if we remove that check it will definitely load updated file every time but it will slower the performance. i want an alternate way.
hope i explained my question.
thanks in advance.
Java has a file watcher service. It is an API. You can "listen" for changes in files and directories. So you can listen for changes to your properties file, or the directory in which your properties file is located. The Java Tutorials on Oracle's OTN Web site has a section on the watcher service.
Good Luck,
Avi.
I'm trying to make a java program which blocks the facebook page in web browsers. I'm trying to overwrite somehow the hosts file, but the file is disabled to overwriting. I tried to copy him to my desktop, then append a line which blocks the page, and then copy to the etc folder and click to copy (or overwrite) the file. But i can't do it in java, all what i did was create another file in the same folder and append lines to it. But then i can't copy the new file to old, i dont know how to do it, here's my code, i'm waiting for a solutions :)
public class Sandbox {
private final static File zdroj = new File("C:\\Windows\\System32\\drivers\\etc\\hosts");
private final static File ciel = new File("C:\\Windows\\System32\\drivers\\etc\\hostsTemp");
public static void main(String[] args) {
try {
Files.copy(zdroj.toPath(), ciel.toPath());
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(ciel, true)));
writer.append("\n\n127.0.0.1 facebook.com www.facebook.com http://www.facebook.com/ http://facebook.com");
writer.close();
Files.delete(zdroj.toPath());
Files.copy(ciel.toPath(), zdroj.toPath());
} catch (IOException ex) {
Logger.getLogger(Sandbox.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
You will need to run your application with elevated permissions. Try starting it with some administrator user.
I have this code that Reads a file from the file path given.
I have hardcoded F://dom.txt. I need the user to input that filepath instead.
How should i do it? Thanks
import java.io.BufferedReader;
import java.io.FileReader;
public class BuffReader extends Converter {
private static BufferedReader br() throws FileNotFoundException{
return new BufferedReader(new FileReader("F://dom.txt")); //<--filepath
}
static String strTem;
public static String readData(String Message){
try{
System.out.print(Message);
strTem = br().readLine();
}catch(Exception e){
System.err.println("Muling tingan ang iyong numerong ibinigay");
}
return strTem;
}
}
Well you need to give the filename to the oddly-named br() method. For example:
private static BufferedReader br(String path) throws FileNotFoundException {
return new BufferedReader(new FileReader(path));
}
public static String readData(String message){
try{
System.out.print(message);
strTem = br(message).readLine();
}catch(Exception e){
System.err.println("Muling tingan ang iyong numerong ibinigay");
}
return strTem;
}
That's assuming the parameter to readData is actually the file you want to read from... otherwise, you'll need to work out where you are going to get the file name from.
(It would be a good idea to work on exception handling and naming, by the way.)
Assuming you mean the input should come from the console (it could also be command line parameter or a gui or whatever you like really) then you should be able to use System.console().readLine("prompt for input")
(assuming it is a standalone) Change your main method to read the variable args[0].
public static void main (String[] args) {
readData(Message, args[0]);
}
Then change the method signatures for readData() and so on. Basically the above code tells you how to read a string from command line.
If you are asking in the middle of the program:
You can use
System.console().readLine("Enter file name: )
to get the user input.
Also i would suggest to keep this file in a config file and read it from the file in order for the program to be flexible.
I'm running an application from inside another one for testing purposes. I want to redirect the output for the tested app to a file, so I can have a log after each test.
Is there a way to redirect the output of an app to a file from the command line in java?
You can use the output stream redirector that is supported by the Windows command line, *nix shells , e.g.
java -jar myjar.jar > output.txt
Alternatively, as you are running the app from inside the vm, you could redirect System.out from within java itself. You can use the method
System.setOut(PrintStream ps)
Which replaces the standard output stream, so all subsequent calls to System.out go to the stream you specify. You could do this before running your wrapped application, e.g. calling System.setOut(new PrintStream(new BufferedOutputStream(new FileOutputStream("output.txt"))));
If you are using a wrapper that you can't modify, then create your own wrapper. So you have FEST wrapper -> stream redirector wrapper -> tested app.
For example, you can implement a simple wrapper like this:
public class OutputRedirector
{
/* args[0] - class to launch, args[1]/args[2] file to direct System.out/System.err to */
public static void main(String[] args) throws Exception
{ // error checking omitted for brevity
System.setOut(outputFile(args(1));
System.setErr(outputFile(args(2));
Class app = Class.forName(args[0]);
Method main = app.getDeclaredMethod("main", new Class[] { (new String[1]).getClass()});
String[] appArgs = new String[args.length-3];
System.arraycopy(args, 3, appArgs, 0, appArgs.length);
main.invoke(null, appArgs);
}
protected PrintStream outputFile(String name) {
return new PrintStream(new BufferedOutputStream(new FileOutputStream(name)), true);
}
}
You invoke it with 3 additional params - the Main class to run, and the output/error directs.
When using this constructor:
new PrintStream(new BufferedOutputStream(new FileOutputStream("file.txt")));
remember to set autoflushing to true, i.e.:
new PrintStream(new BufferedOutputStream(new FileOutputStream("file.txt")), true);
otherwise you may get empty files even after your program finishes.
Yes you can set your desired file like this.
try {
System.setOut(new PrintStream(new File("output-file.txt")));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println() is used to print messages on the console.
System is a class defined in the java.lang package. out is an instance of PrintStream, which is a public and static member of the class System. As all instances of PrintStream class have a public method println().
System.out is a static PrintStream that writes to the console. We can redirect the output to a different PrintStream using the System.setOut() method which takes a PrintStream as a parameter.
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class SetPrintStream {
public static void main(String[] args) throws FileNotFoundException{
System.out.println("Print on console");
// Store console print stream.
PrintStream ps_console = System.out;
File file = new File("file.txt");
FileOutputStream fos = new FileOutputStream(file);
// Create new print stream for file.
PrintStream ps = new PrintStream(fos);
// Set file print stream.
System.setOut(ps);
System.out.println("Print in the file !!");
// Set console print stream.
System.setOut(ps_console);
System.out.println("Console again !!");
}
}
Output:
Print on console
Console again !!
new file.txt will be created.
For more information see my blog:
http://javaexplorer03.blogspot.in/2016/02/how-do-i-redirect-standard-output-to.html
In order to improve "vijay.shad" response I used the code bellow to direct the file to the Home Directory in Linux or MyDocuments in Windows.
try {
System.setOut(new PrintStream(new File(FileSystemView.getFileSystemView()
.getDefaultDirectory().toString()
+ File.separator + "output-file.txt")));
} catch (Exception e) {
e.printStackTrace();
}
File file = new File("xyz.txt");
PrintStream printStreamToFile = new PrintStream(file);
System.setOut(printStreamToFile);
System.out.println("Hello I am writing to File xyz.txt");
Or you can use Class FileWriter.
I'm trying to configure the Java Logging API's FileHandler to log my server to a file within a folder in my home directory, but I don't want to have to create those directories on every machine it's running.
For example in the logging.properties file I specify:
java.util.logging.FileHandler
java.util.logging.FileHandler.pattern=%h/app-logs/MyApplication/MyApplication_%u-%g.log
This would allow me to collect logs in my home directory (%h) for MyApplication and would rotate them (using the %u, and %g variables).
Log4j supports this when I specify in my log4j.properties:
log4j.appender.rolling.File=${user.home}/app-logs/MyApplication-log4j/MyApplication.log
It looks like there is a bug against the Logging FileHandler:
Bug 6244047: impossible to specify driectorys to logging FileHandler unless they exist
It sounds like they don't plan on fixing it or exposing any properties to work around the issue (beyond having your application parse the logging.properties or hard code the path needed):
It looks like the
java.util.logging.FileHandler does not
expect that the specified directory
may not exist. Normally, it has to
check this condition anyway. Also, it
has to check the directory writing
permissions as well. Another question
is what to do if one of these check
does not pass.
One possibility is to create the
missing directories in the path if the
user has proper permissions. Another
is to throw an IOException with a
clear message what is wrong. The
latter approach looks more consistent.
It seems like log4j version 1.2.15 does it.
Here is the snippet of the code which does it
public
synchronized
void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
throws IOException {
LogLog.debug("setFile called: "+fileName+", "+append);
// It does not make sense to have immediate flush and bufferedIO.
if(bufferedIO) {
setImmediateFlush(false);
}
reset();
FileOutputStream ostream = null;
try {
//
// attempt to create file
//
ostream = new FileOutputStream(fileName, append);
} catch(FileNotFoundException ex) {
//
// if parent directory does not exist then
// attempt to create it and try to create file
// see bug 9150
//
String parentName = new File(fileName).getParent();
if (parentName != null) {
File parentDir = new File(parentName);
if(!parentDir.exists() && parentDir.mkdirs()) {
ostream = new FileOutputStream(fileName, append);
} else {
throw ex;
}
} else {
throw ex;
}
}
Writer fw = createWriter(ostream);
if(bufferedIO) {
fw = new BufferedWriter(fw, bufferSize);
}
this.setQWForFiles(fw);
this.fileName = fileName;
this.fileAppend = append;
this.bufferedIO = bufferedIO;
this.bufferSize = bufferSize;
writeHeader();
LogLog.debug("setFile ended");
}
This piece of code is from FileAppender, RollingFileAppender extends FileAppender.
Here it is not checking whether we have permission to create the parent folders, but if the parent folders is not existing then it will try to create the parent folders.
EDITED
If you want some additional functionalily, you can always extend RollingFileAppender and override the setFile() method.
You can write something like this.
package org.log;
import java.io.IOException;
import org.apache.log4j.RollingFileAppender;
public class MyRollingFileAppender extends RollingFileAppender {
#Override
public synchronized void setFile(String fileName, boolean append,
boolean bufferedIO, int bufferSize) throws IOException {
//Your logic goes here
super.setFile(fileName, append, bufferedIO, bufferSize);
}
}
Then in your configuration
log4j.appender.fileAppender=org.log.MyRollingFileAppender
This works perfectly for me.
To work around the limitations of the Java Logging framework, and the unresolved bug: Bug 6244047: impossible to specify driectorys to logging FileHandler unless they exist
I've come up with 2 approaches (although only the first approach will actually work), both require your static void main() method for your app to initialize the logging system.
e.g.
public static void main(String[] args) {
initLogging();
...
}
The first approach hard-codes the log directories you expect to exist and creates them if they don't exist.
private static void initLogging() {
try {
//Create logging.properties specified directory for logging in home directory
//TODO: If they ever fix this bug (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6244047) in the Java Logging API we wouldn't need this hack
File homeLoggingDir = new File (System.getProperty("user.home")+"/webwars-logs/weblings-gameplatform/");
if (!homeLoggingDir.exists() ) {
homeLoggingDir.mkdirs();
logger.info("Creating missing logging directory: " + homeLoggingDir);
}
} catch(Exception e) {
e.printStackTrace();
}
try {
logger.info("[GamePlatform] : Starting...");
} catch (Exception exc) {
exc.printStackTrace();
}
}
The second approach could catch the IOException and create the directories listed in the exception, the problem with this approach is that the Logging framework has already failed to create the FileHandler so catching and resolving the error still leaves the logging system in a bad state.
As a possible solution I think there are 2 approaches (look at some of the previous answers). I can extend a Java Logging Handler class and write my own custom handler. I could also copy the log4j functionality and adapt it to the Java Logging framework.
Here's an example of copying the basic FileHandler and creating a CustomFileHandler see pastebin for full class:
The key is the openFiles() method where it tries to create a FileOutputStream and checking and creating the parent directory if it doesn't exist (I also had to copy package protected LogManager methods, why did they even make those package protected anyways):
// Private method to open the set of output files, based on the
// configured instance variables.
private void openFiles() throws IOException {
LogManager manager = LogManager.getLogManager();
...
// Create a lock file. This grants us exclusive access
// to our set of output files, as long as we are alive.
int unique = -1;
for (;;) {
unique++;
if (unique > MAX_LOCKS) {
throw new IOException("Couldn't get lock for " + pattern);
}
// Generate a lock file name from the "unique" int.
lockFileName = generate(pattern, 0, unique).toString() + ".lck";
// Now try to lock that filename.
// Because some systems (e.g. Solaris) can only do file locks
// between processes (and not within a process), we first check
// if we ourself already have the file locked.
synchronized (locks) {
if (locks.get(lockFileName) != null) {
// We already own this lock, for a different FileHandler
// object. Try again.
continue;
}
FileChannel fc;
try {
File lockFile = new File(lockFileName);
if (lockFile.getParent() != null) {
File lockParentDir = new File(lockFile.getParent());
// create the log dir if it does not exist
if (!lockParentDir.exists()) {
lockParentDir.mkdirs();
}
}
lockStream = new FileOutputStream(lockFileName);
fc = lockStream.getChannel();
} catch (IOException ix) {
// We got an IOException while trying to open the file.
// Try the next file.
continue;
}
try {
FileLock fl = fc.tryLock();
if (fl == null) {
// We failed to get the lock. Try next file.
continue;
}
// We got the lock OK.
} catch (IOException ix) {
// We got an IOException while trying to get the lock.
// This normally indicates that locking is not supported
// on the target directory. We have to proceed without
// getting a lock. Drop through.
}
// We got the lock. Remember it.
locks.put(lockFileName, lockFileName);
break;
}
}
...
}
I generally try to avoid static code but to work around this limitaton here is my approach that worked on my project just now.
I subclassed java.util.logging.FileHandler and implemented all constructors with their super calls. I put a static block of code in the class that creates the folders for my app in the user.home folder if they don't exist.
In my logging properties file I replaced java.util.logging.FileHandler with my new class.