Build CSV dynamically in JSF 2 - java

Basically what I want to do is this : http://www.mkyong.com/java/how-to-export-data-to-csv-file-java/
Except at the end serve it as a download to the user.
Obviously I can't use FileWriter as I'm using JSF,but I tried doing something similar by getting the output stream from the external context and then making a buffered writer using the output stream(code below).According to my logs this does execute completely till the end,but no save as dialog pops up.I am using JSF 2(MyFaces) and RichFaces 4.3,if there is a better way to do this using a component please tell me.
externalContext.responseReset();
externalContext.setResponseHeader("Content-Disposition", "attachment; filename=test.csv");
externalContext.setResponseContentType("text/csv");
try {
OutputStream csvOut = externalContext.getResponseOutputStream();
BufferedWriter csvWriter = new BufferedWriter(new OutputStreamWriter(csvOut, "UTF-8"));
csvWriter.append("data,data,data,data");
csvWriter.flush();
csvWriter.close();
csvOut.close();
facesContext.responseComplete();
}catch(Exception ex){
System.out.println(ex.toString());
}
Any suggestions will help alot,been struggling with this for some time now.

Firstly thanks to uzvar for pointing me to Forcing a save as dialogue from any web browser from JSF application It's what helped me get mine working.
Basically all I did was instead of an OutputStream I declared an BufferedOutputStream with the externalContext.getResponseOutputStream(); as argument.So it looks like :
BufferedOutputStream csvOut = new BufferedOutputStream(externalContext.getResponseOutputStream());
The rest of the code stays the same.
If there is a better way to do this please post an answer/comment.

Related

Best strategy to add lines of text to a text file

I'm using txt files, creating them with the class PrintWriter. This allows me to print inside a txt file some content using println(...) method.
But now I need to add some content at the end of the list that I created. Like this:
PrintWriter writer = new PrintWriter("File.txt", "UTF-8");
writer.println("Hello");
writer.println("Josh!");
writer.close();
the result is a file like this:
Hello
Josh!
but what if I would like to add new words at the bottom of the text? I would prefer an overwriting of the file "File.txt" with the content updated?
Hello
Josh!
How are you?
I was thinking on something like, "Ok I have to add another line at the end, so read all the file, and write another file (with the same name and content) adding a new line at the end", but it seems too strange to do, I feel like there is another simple way to do it. Any other idea?
You could simply use a FileWriter instead, it has an append mode that you can enable:
FileWriter writer = new FileWriter("File.txt");
writer.write("Hello\n");
writer.write("Josh!\n");
writer.close();
writer = new FileWriter("File.txt", true);
writer.append("Great!");
writer.close();
Your suspicions are correct.
You should use try with resources (Java 7+):
try(PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("File.txt", true)))) {
out.println("How are you?");
}catch (IOException e) {
//exception handling left as an exercise for the reader
}
The second parameter to the FileWriter constructor will tell it to append to the file (as opposed to clearing the file). Using a BufferedWriter is recommended for an expensive writer (i.e. a FileWriter), and using a PrintWriter gives you access to println syntax that you're probably used to from System.out. But the BufferedWriter and PrintWriter wrappers are not strictly necessary.
Also this allows you to append to a file, rather than replacing the whole file, on every run. Lastly, try with resources means you do not have to call .close(), it's done for you! Grabbed from here

Open file content in new tab in browser

I want to show the file content in new tab in browser. What i have done is this:
int BUFF_SIZE = 102400;
FileInputStream is = null;
byte[] buffer = new byte[BUFF_SIZE];
int a = -1;
try
{
is = new FileInputStream(file);
ByteArrayOutputStream out = new ByteArrayOutputStream();
while((a = is.read(buffer)) != -1)
{
out.write(buffer);
}
out.flush();
out.close();
ServletOutputStream os = null;
os = response.getOutputStream();
os.write(out.toByteArray());
os.close();
is.close();
}
catch(Exception e)
{
// Exception handling
}
But this is leading to download of the file instead of opening the file-content in new tab.
I am not able to find what i am doing wrong.
Any help would be great!!
Actually, all you should need to do now is add JQuery to your webpage, and use JQUery.get. Once you get the html from the servlet, use jquery or javascript to set the text in your tab.
BTW, you might want to set other details on the servlet output stream, like file type, length etc. Just a thought
You could also try this with the omnifaces library
Faces.sendFile(file, false);//true makes it as an attachment
more information on http://omnifaces.org/docs/javadoc/1.8/org/omnifaces/util/Faces.html#sendFile(java.io.File,%20boolean)
A web application might not even know what is a brower. It receives requests through HTTP protocol and send responses through same protocol. The protocol by itsels knows nothing about browsers and tabs.
You must use javascript for anything that happens at browser level. Other answers adviced you to use jQuery. It is a well known javascript library that hides differences between browsers, but there are others around (dojo, extJs, ...) : Google and make your choice.
By the way, if all you want is open an URL in a new tab, that's one of the very few operations that you can do at HTML level. Just look at this example
from W3Schools.com :
Visit W3Schools!
that opens www.w3schools.com in a new tab (if browser has tabs what is now common) or a new window.

Why is my attempt to append text to a file not responding?

I'm simply trying to add a new line of text to my *.txt file, but nothing happens at all. The file is packed with a .war, so I use a ClassLoader to access the file. Also, both my eclipse IDE, and the contents of the file, use UTF-8 encoding.
I've used these for inspiration:
How to add a new line of text to an existing file in Java?
Java BufferedWriter object with utf-8
Now my code is mainly based on the last post, and looks like this:
public class test {
public static void main(String[] args){
URL url = Thread.currentThread().getContextClassLoader().getResource("MilestoneExport.txt");
File file = new File(url.getFile());
System.out.println(file.canRead()); //true
System.out.println(file.canWrite()); //true
try {
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));
out.append("new line");
out.append("new line 2");
out.append("new line 3");
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
I've confirmed that the file is in fact found, and it reads fine. I've been able to output the entire content of it to the console through the use of a BufferedReader. The path of the file is also correct, but absolutely no text is added to the file. I've made sure that I have refreshed and updated every time I've run the program.
Also, I've tried to create a simple empty file called foo.txt, which is located in the same directory as test.java. I added the following code to the main method, as provided by the BufferedWriter API, at http://docs.oracle.com/javase/7/docs/api/java/io/BufferedWriter.html
PrintWriter out2 = new PrintWriter(
new BufferedWriter(new FileWriter("foo.txt")));
out2.println("new Line");
out2.close();
What am i missing here? Why are there no error messages, and no responses or feedbacks whatsoever?
EVERYTHING BELOW IS ONLY ADDITIONAL INFO ABOUT WHAT I'VE TRIED. NO FEEDBACK IN ANY CASES:
Not this one: Why is BufferedWriter not writing to file?
Not this one: why is bufferedwriter not writing in the file?
Not this one: Unable to write to file using BufferedWriter
Yet another "remember to close/flush": Java : Problems accessing and writing to file
Defining the BufferedWriter outside the try block makes no difference, but I tried it anyway, due to How to write detail into file using BufferedWriter and FileWriter in Java?
Also, this code, from this answer, does nothing as well...
try {
BufferedWriter output = new BufferedWriter(new FileWriter(new File("house.txt")));
output.write("text");
output.close();
}
catch (IOException e) {
e.printStackTrace();
}
last but not least, I suspected that it might have something to do with the packaging of my Web-App, and differences between the source and target-folders. So I copied the code to a brand new clean project, but it still does nothing at all...
EDIT:
this code:
System.out.println(file.exists());
System.out.println(file.getAbsolutePath());
System.out.println(file.getCanonicalPath());
System.out.println(file.getName());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
System.out.println(file.setLastModified(new GregorianCalendar().getTimeInMillis()));
gives these outputs:
true
D:\Data\myworkspace\MyProject\target\classes\MilestoneExport.txt
D:\Data\myworkspace\MyProject\target\classes\MilestoneExport.txt
MilestoneExport.txt
false
true
true
Am I completely misunderstanding the use of java's File-objects, and it's uses with FileWriters? The file is clearly 100% confirmed the correct file.
You should use the other constructor of FileOutputStream in order to open the file in append mode :
FileOutputStream(File file, boolean append)
I.e,
new FileOutputStream(file, true)
Since I can't comment, you might not be saving the file back into the archive it came from (I'm not sure if java supports writing to the internal structures of archives by editing the files that are included, however you might want to try to store the file externally to the archive to see if that is the place the issue comes from).
The cause of what you posted in the comments is that your IDE won't extract the resource file from a compiled program, if you want to sync the internal data you might be able to setup a client-server connection using sockets and creating a program that writes the data to the local file from data packets send to your web-app, otherwise retrieving the edited file from where you are hosting might be less complicated (or if you are deploying from the same PC you might be able to get away with a symbolic or hard link)
I've tried this code that is very similar to yours and it's working nicely,
so i think the problem is the way you are picking the path of the file.
public static void main(String[] args){
File file = new File("./localtest.txt");
System.out.println(file.canRead()); //true
System.out.println(file.canWrite()); //true
try {
BufferedWriter out = new BufferedWriter
(new OutputStreamWriter(new FileOutputStream(file),"UTF-8"));
out.append("new line");
out.append("new line 2");
out.append("new line 3");
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
this works
PrintWriter pw= new PrintWriter(
new BufferedWriter(new FileWriter("C:\\foo.txt")));
pw.println("line 1");
pw.close();

Outputting byte[] to a .txt file

I'm trying to output a byte array to a file. The String that I create displays correctly when I call System.out.println(ouput_stream). Hover, it does not output correctly when I use a FileOutputStream. Here's what I've got so far. Any suggestions?
FileOutputStream fos = new FileOutputStream("outputFile.txt");
OutputStreamWriter out = new OutputStreamWriter(fos, "UTF-8");
String received_string = new String(rPacket.getData(), 0, rPacket.getLength(), "UTF-8");
System.out.println(received_string);
out.write(received_string, 0, received_string.length());
The console displays the information the information when I call the System.out.println(received_string. However, it doesn't output the file correctly. I asked a similar question earlier, but now am struggling on the output. Thanks for any help.
Have a look at Apache Commons FileUtils.writeByteArrayToFile
Should do what you need
Your code looks a bit weird (do you want bytes or Strings), but should be okay.
What did you find in the file? Did you close the stream/writer before looking at it? If not, it is likely still being buffered somewhere.
Try to avoid the conversion to String, though, if you really want to just pipe that packet to a file.
Don't use a String or a Writer at all. Just copy the bytes directly from the packet to the file:
fos.write(rPacket.getData(), rPacket.getOffset(), rPacket.getLength());
Then you can't possibly corrupt the data.
Try using BufferedWriter ..
BufferedWriter writer = new BufferedWriter(new FileWriter("outfile"));
writer.write(received_string);

Deny access to a file for all other processes?

I'm writing an application (for educational purposes), which needs to use database management system (I wrote my own extremely primitive DBMS, it is part of the task). And I want to ensure that at any time my application is running contents of all tables are correct. For that purposes I wrote method, which looks through each file and make necessary checks. The problem is that I want to call this method only once, when application starts and deny access to files to ensure that nobody changed their contents while my program is working.
I use the following approach. When application starts, I initialize InputStreamReader and OutputStreamWriter, store them and close them only when my application is terminated.
Part of initialization method:
FileInputStream fis = new FileInputStream(file);
FileOutputStream fos = new FileOutputStream(file, true);
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
this.tables.get(table).put("fis", fis);
this.tables.get(table).put("fos", fos);
this.tables.get(table).put("isr", isr);
this.tables.get(table).put("osw", osw);
Close method:
try {
for(Map<String, Object> table_map: tables.values()) {
OutputStreamWriter osw = (OutputStreamWriter)table_map.get("osw");
InputStreamReader isr = (InputStreamReader)table_map.get("isr");
if (osw != null)
osw.close();
if (isr != null)
isr.close();
}
}
catch (IOException e) {
throw new DBException("Closing error");
}
Partly, this approach works, because when I try to modify any of these files using MS Notepad, I get the following error
"The process cannot access the file because it is being used by
another process"
That's what I want to see. But if I use Notepad++, I can make any modifications when my application is running, that's not what I expect to see. So what can I do to ensure that no other process can modify my files?
I tried to use FileLock, but it denies access only for my process, if I'm not mistaken.
Sorry for my poor English, hope you will understand my question anyway.
I'm not sure this is a problem worth solving. Whatever approach you take, someone with the correct privileges can probably undo your file protection and could make changes anyway.
It is best to focus on gracefully handling invalid data and otherwise trusting what is in the file. Adding some kind of integrity check (per row or table) will make it harder for someone to accidentally or maliciously change your data in a way that leaves it looking "valid".
If you read the section "Platform dependencies" in the java.nio.channels.FileLock docsyou see that:
FileLocks are not (only) for locking inside one JVM but for all processes on the computer.
File locks (note the different spelling) are greatly platform and configuration specific.
So you basicyll have to ask yourself: What protection do I really need?
If you only want to guard against running your programm multiple times on the same data you can assume that your programm "behaves well" and
use FileLocks or
use a marker lock file or
use a "dirty/locked" marker inside the file
If you want to protect against every other program then you are lost as you have seen in the Notepad++ scenario: Considering all platforms and all possible ways to circumvent locks and using Java- you have no chance.

Categories