The FileUtils.writeStringToFile(fileName, text) function of Apache Commons I/O overwrites previous text in a file. I would like to append data to my file. Is there any way I could use Commons I/O for the same? I can do it using normal BufferedWriter from Java but I'm curious regarding the same using Commons I/O.
It has been implemented in 2.1 version of Apache IO.
To append string to the file just pass true as an additional parameter in functions:
FileUtils.writeStringToFile
FileUtils.openOutputStream
FileUtils.write
FileUtils.writeByteArrayToFile
FileUtils.writeLines
ex:
FileUtils.writeStringToFile(file, "String to append", true);
Download the latest version Commons-io 2.1
FileUtils.writeStringToFile(File,Data,append)
set append to true....
Careful. That implementation seems to be leaking a file handle...
public final class AppendUtils {
public static void appendToFile(final InputStream in, final File f) throws IOException {
OutputStream stream = null;
try {
stream = outStream(f);
IOUtils.copy(in, stream);
} finally {
IOUtils.closeQuietly(stream);
}
}
public static void appendToFile(final String in, final File f) throws IOException {
InputStream stream = null;
try {
stream = IOUtils.toInputStream(in);
appendToFile(stream, f);
} finally {
IOUtils.closeQuietly(stream);
}
}
private static OutputStream outStream(final File f) throws IOException {
return new BufferedOutputStream(new FileOutputStream(f, true));
}
private AppendUtils() {}
}
this little thingy should do the trick:
package com.yourpackage;
// you're gonna want to optimize these imports
import java.io.*;
import org.apache.commons.io.*;
public final class AppendUtils {
public static void appendToFile(final InputStream in, final File f)
throws IOException {
IOUtils.copy(in, outStream(f));
}
public static void appendToFile(final String in, final File f)
throws IOException {
appendToFile(IOUtils.toInputStream(in), f);
}
private static OutputStream outStream(final File f) throws IOException {
return new BufferedOutputStream(new FileOutputStream(f, true));
}
private AppendUtils() {
}
}
edit: my eclipse was broken, so it didn't show me the errors earlier. fixed errors
Actually, version 2.4 of apache-commons-io FileUtils now has append mode for collections as well.
Here's the Javadoc
And the maven dependency:
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<type>jar</type>
</dependency>
in version 2.5 you need to pass one extra parameter i.e, encoding.
FileUtils.writeStringToFile(file, "line to append", "UTF-8", true);
public static void writeStringToFile(File file,
String data,
boolean append)
throws IOException
Writes the toString() value of each item in a collection to the specified File line by line. The default VM encoding and the default line ending will be used.
Parameters:
file - the file to write to
lines - the lines to write, null entries produce blank lines
append - if true, then the lines will be added to the end of the file rather than overwriting
Throws:
IOException - in case of an I/O error
Since:
Commons IO 2.1
Related
I'm using html form to take input of a file and uploading it using doPost() method of HTTPservlet. [This part is done in package one] Now function from class Main.java to parse the uploaded file is called in this doPost method. This function resides in the other package. [Moving to the other package-> ] Here the class Main.java calls Integrated.java which has all the instances of class and functions needed to be called in order to parse the file that was uploaded. (I have separate classes for extracting data, chunking, sorting and generating csv out of the data parsed)
After I parse the file, I put values in variables which are initialized in the last file CSVgenerator.java. Values to these variables are added before in the class SortAndOutput.java. To test that I'm getting the right values in my class, I print the variables right before I call the functions writingDatabase() and writingTraining(). These two functions save the values of the variables in CSV files.
I'm using OpenCSV for writing the files. Using apache Tika for extraction of data and lingpipe to parse.
THE BIG PROBLEM:
I (intentionally) write main func in CSVgenerator.java and test it. Both the files are written properly. The missing value columns are left blank. PERFECT! (If i have any of the CSV open separately, it raises an exception like it should)
But when i comment out the main func and run the whole project together on server, the CSVs are not written. Even if the files are opened separately(outside eclipse), it doesn't give an error.
I have tested the whole integrated Java code by putting a main method in Main.java and it runs perfectly. The problem occurs when servlet is run/I run project on server.
I don't know if other files will be helpful or not, I'm posting the hierarchy and CSVgenerator class
Workspace Screenshot
CSVGenerator.java
package com.fypv1.parser;
import java.io.*;
import java.util.*;
import com.opencsv.*;
public class CSVgenerator {
public static String CGPAinitial="-";
public static String universityNameOut="-";
public static String emailIDOut="-";
public static String phoneNoOut="-";
public static String phpKnow="NO";
public static String databaseKnow="NO";
public static String jsKnow="NO";
public static String bootStrapKnow="NO";
public static String aspKnow="NO";
public static String htmlKnow="NO";
public static String cssKnow="NO";
public static String jqueryKnow="NO";
public static String jspKnow="NO";
public static String reactjsKnow="NO";
public static String ajaxKnow="NO";
public static String oopKnow="NO";
public static String javaKnow="NO";
public static String androidKnow="NO";
private int idNumber;
Writer wr;
Scanner scanner;
/*
* public static void main(String[] args) throws IOException {
new CSVgenerator();
}
*/
//DEFAULT CLASS CONSTRUCTOR
CSVgenerator() throws IOException
{
String trainingCSV = "TrainingData.csv";
String databaseCSV = "databaseInfo.csv";
String idNumberFile = "idnum.txt";
try {
scanner = new Scanner(new File(idNumberFile));
SortAndOutput.applicantIDnumber=scanner.nextInt();
idNumber=SortAndOutput.applicantIDnumber;
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
System.out.println("IDnumberFileUnavailable");
}
try {
wr = new FileWriter(idNumberFile);
int newIDNumber=idNumber+1;
wr.write(newIDNumber+"");
wr.close();
} catch (IOException e1) {
//
e1.printStackTrace();
}
//System.out.println( String.valueOf(idNumber)+"+"+universityNameOut+"+"+CGPAinitial+"+"+emailIDOut+"+"+ phoneNoOut+"+"+CGPAinitial+"+"+phpKnow+"+"+ databaseKnow+"+"+ jsKnow+"+"+ bootStrapKnow+"+"+ aspKnow+"+"+ htmlKnow+"+"+ cssKnow+"+"+ jqueryKnow+"+"+ jspKnow+"+"+ reactjsKnow+"+"+ ajaxKnow+"+"+ "?");
writingDatabase(databaseCSV);
writingTraining(trainingCSV);
}//CONSTRUCTOR ENDS
void writingDatabase(String databaseCSV) throws IOException {
CSVWriter dbWriter;
String [] record1={String.valueOf(idNumber),universityNameOut,CGPAinitial,emailIDOut, phoneNoOut };
dbWriter= new CSVWriter(new FileWriter(databaseCSV, true));
dbWriter.writeNext(record1);
dbWriter.close();
}
void writingTraining(String trainingCSV) throws IOException {
CSVWriter trainingWriter;
String [] record={String.valueOf(idNumber),CGPAinitial,phpKnow, databaseKnow, jsKnow, bootStrapKnow, aspKnow, htmlKnow, cssKnow, jqueryKnow, jspKnow, reactjsKnow, ajaxKnow, "?"};
trainingWriter = new CSVWriter(new FileWriter(trainingCSV, true));
trainingWriter.writeNext(record);
trainingWriter.close();
}
}
Integrated.java
ResumeUploadService.java (the servlet)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
try {
Part file = request.getPart("file");
resumeFileName = Paths.get(file.getSubmittedFileName()).getFileName().toString();
file.write(path + resumeFileName);
printOnClient(response, "Upload Successful!");
}
catch (Exception e) {
printOnClient(response, "Upload Failed!");
}
new Main(path,resumeFileName);
}
Please let me know if more code is needed to debug this.
It was updating files both times. When it ran on server, it created files in eclipse folder and when i ran as java application, it updated files in project folder
Your files are written in the application folder unless otherwise specified. This is the relative path to the running application.
Just because you tested the application in Eclipse doesn't mean that the server deployment would write to the same folder.
Ideally, you can specify a configuration parameter to your Servlet for an absolute path where files are to be stored
Error in code:
If that train is removed then also show compiler error as below. I tried a lot to remove that and classify sentence as positive or negative.
An InputStreamFactory in not the same as an InputStream. Here is a simple bit of code that will create an InputStreamFactory for you. (You might say it is an InputStreamFactoryFactory :-) )
public static InputStreamFactory getInputStreamFactory(final File file) throws IOException{
return new InputStreamFactory() {
#Override
public InputStream createInputStream() throws IOException {
return new FileInputStream(file);
}
};
}
see javadocs: https://opennlp.apache.org/documentation/1.7.2/apidocs/opennlp-tools/opennlp/tools/util/InputStreamFactory.html
I'm writting tiny XMPP client as university project.
To generate valid XML markup I use XMLStreamWriter from standard library.
For debugging purposes I want to see all content that was written by it to output stream, i.e both send it via opened socket to the world and log it to stderr. One possible solution I found is to create subclasss of Writer class to construct new XMLStreamWriter.
Something like the following code:
public XMPPWriter(final Writer out) throws XMLStreamException {
XMLOutputFactory factory = XMLOutputFactory.newInstance();
factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
this.writer = factory.createXMLStreamWriter(new Writer() {
#Override
public void flush() throws IOException {
System.err.println("");
out.flush();
}
#Override
public void write(char[] cbuf, int off, int len) throws IOException {
System.err.write(String.valueOf(cbuf, off, len).getBytes());
out.write(cbuf, off, len);
}
#Override
public void close() throws IOException {
out.close();
}
});
}
Of course, it's the simplest case and this solution can be impoved in a lot of ways. But I'm wondering is there any standard well-known way to do such logging?
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.
Is there an existing way to have a FileInputStream delete the underlying file automatically when closed?
I was planning to make my own utility class to extend FileInputStreamand do it myself, but I'm kinda surprised that there isn't something already existing.
edit: Use case is that I have a Struts 2 action that returns an InputStream for file download from a page. As far as I can tell, I don't get notified when the action is finished, or the FileInputStream is not in use anymore, and I don't want the (potentially large) temporary files that are generated to be downloaded left lying around.
The question wasn't Struts 2 specific, so I didn't include that info originally and complicate the question.
There's no such thing in the standard libraries, and not any of the apache-commons libs either , so something like:
public class DeleteOnCloseFileInputStream extends FileInputStream {
private File file;
public DeleteOnCloseFileInputStream(String fileName) throws FileNotFoundException{
this(new File(fileName));
}
public DeleteOnCloseFileInputStream(File file) throws FileNotFoundException{
super(file);
this.file = file;
}
public void close() throws IOException {
try {
super.close();
} finally {
if(file != null) {
file.delete();
file = null;
}
}
}
}
I know this is a fairly old question; however, it's one of the first results in Google, and Java 7+ has this functionality built in:
Path path = Paths.get(filePath);
InputStream fileStream = Files.newInputStream(path, StandardOpenOption.DELETE_ON_CLOSE);
There are a couple caveats with this approach though, they're written up here, but the gist is that the implementation makes a best effort attempt to delete the file when the input stream is closed, and if that fails makes another best effort attempt when the JVM terminates. It is intended for use with temp files that are used solely by a single instance of the JVM. If the application is security sensitive, there are also a few other caveats.
Can you can use File.deleteOnExit() before opening the file ?
EDIT: On you can subclass a FileInputStream that will delete the file on 'close()';
class MyFileInputStream extends FileInputStream
{
File file;
MyFileInputStream(File file) { super(file); this.file=file;}
public void close() { super.close(); file.delete();}
}
I know this is an old question, but I just ran into this issue, and found another answer: javax.ws.rs.core.StreamingOutput.
Here's how I used it:
File downloadFile = ...figure out what file to download...
StreamingOutput so = new StreamingOutput(){
public void write(OutputStream os) throws IOException {
FileUtils.copyFile(downloadFile, os);
downloadFile.delete();
}
ResponseBuilder response = Response.ok(so, mimeType);
response.header("Content-Disposition", "attachment; filename=\""+downloadFile.getName()+"\"");
result = response.build();