How to make my FileSaver being able to output any type stuff?

S

Shawn

Hi,

I am writing a Class file (FileSaver.java), which has the outline:

public class FileSaver {
private JFileChooser _fileChooser = null;

public FileSaver()
{
_fileChooser = new JFileChooser(new File("."));
_fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
}

public void saveFile()
{
... //writes to the external file
}

} //end of class
This class will pup up a gui to let user choose the directory and file
name etc. It will be called anytime when the major program needs to save
something. Right now, when something needs to be saved, the code for
saving is repeated typed in that place. I hope to pull out those code
and create an object which can do saving for anybody, anytime.

Sometime it is several lines of text needs to be saved, sometimes it is
other things(e.g. image). I hope this class file FileSaver can be as
generic as possible. So I am thinking to let the major program pass
something(OutpurStream?) as arguments. I am not clear how to achieve
this purpose. Could you give me some help?

Thank you.
 
O

Oliver Wong

Shawn said:
Hi,

I am writing a Class file (FileSaver.java), which has the outline:

public class FileSaver {
private JFileChooser _fileChooser = null;

public FileSaver()
{
_fileChooser = new JFileChooser(new File("."));
_fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
}

public void saveFile()
{
... //writes to the external file
}

} //end of class
This class will pup up a gui to let user choose the directory and file
name etc. It will be called anytime when the major program needs to save
something. Right now, when something needs to be saved, the code for
saving is repeated typed in that place. I hope to pull out those code and
create an object which can do saving for anybody, anytime.

Sometime it is several lines of text needs to be saved, sometimes it is
other things(e.g. image). I hope this class file FileSaver can be as
generic as possible. So I am thinking to let the major program pass
something(OutpurStream?) as arguments. I am not clear how to achieve this
purpose. Could you give me some help?

How about having your data-classes implement some sort of interface
which dictates that they provide an InputStream which are the bytes
representing the content of your data?

Then your FileSaver class would take an instance of this interface, call
the method to get the InputStream, and read the bytes, and write those bytes
to the desired file.

- Oliver
 
S

Shawn

Oliver said:
How about having your data-classes implement some sort of interface
which dictates that they provide an InputStream which are the bytes
representing the content of your data?

Then your FileSaver class would take an instance of this interface, call
the method to get the InputStream, and read the bytes, and write those bytes
to the desired file.

- Oliver

It would be much better if you could elaborate a little more or even
throw in some code? I am not very experienced yet. I barely follow what
you mean.

Thank you.
 
C

Chris Uppal

Shawn said:
public void saveFile()
{
... //writes to the external file
}

Would it make more sense for your generic file saver to return an open
OutputStream to the caller ? The caller would then use that to write
application-specific data to the file. That seems simpler to me, than
expecting the caller to "package up" its output code in a form that can be
directly invoked by the FileSaver.

That does have the disadvantage that the caller will be expected to close() the
file, but personally I don't see that as a big enough problem to justify much
extra complexity.

Still, if you do want to ensure that the file is closed by the FileSaver you
could do something like

Define an Interface:

interface FileWriter
{
void write(OutputStream out)
throws IOException;
}

Make your FileSaver take a FileWriter as one parameter (to its constructor or
to some other method). E.g.

class FileSaver
{
....

void promptAndSave(
String suggestedFileName,
// ...etc...
FileWriter writer)
throws IOException
{
// ...prompt for filename...
// ...open file...
try
{
writer.write(output);
}
finally
{
output.close();
}
}

....
}

And then when you use a FileWriter you can pass a local instance of FileWriter
to promptAndSave(). That instance might be one of your existing objects
(probably the object representing the data which is to be written to the file,
but extended to implement FileWriter), or almost as likely it would be
appropriate to create a local class (possibly an anonymous one, though I don't
like 'em myself), to do the job.

As I say, that's all a bit complicated. It is undoubtedly cleaner, and in a
different language I would follow that pattern without hesitation, but Java
makes it pretty messy, and since the gain is only that I don't have to remember
to close() the stream, I'm not sure the mess is worth it.

-- chris
 
O

Oliver Wong

Shawn said:
It would be much better if you could elaborate a little more or even throw
in some code? I am not very experienced yet. I barely follow what you
mean.

Thank you.

See Chris Uppal's second solution (the one which he says he's not sure
is worth it due to messiness). That's essentially what I was proposing.

- Oliver
 
S

Shawn

Chris said:
Would it make more sense for your generic file saver to return an open
OutputStream to the caller ? The caller would then use that to write
application-specific data to the file. That seems simpler to me, than
expecting the caller to "package up" its output code in a form that can be
directly invoked by the FileSaver.

That does have the disadvantage that the caller will be expected to close() the
file, but personally I don't see that as a big enough problem to justify much
extra complexity.

Still, if you do want to ensure that the file is closed by the FileSaver you
could do something like

Define an Interface:

interface FileWriter
{
void write(OutputStream out)
throws IOException;
}

Make your FileSaver take a FileWriter as one parameter (to its constructor or
to some other method). E.g.

class FileSaver
{
....

void promptAndSave(
String suggestedFileName,
// ...etc...
FileWriter writer)
throws IOException
{
// ...prompt for filename...
// ...open file...
try
{
writer.write(output);
}
finally
{
output.close();
}
}

....
}

And then when you use a FileWriter you can pass a local instance of FileWriter
to promptAndSave(). That instance might be one of your existing objects
(probably the object representing the data which is to be written to the file,
but extended to implement FileWriter), or almost as likely it would be
appropriate to create a local class (possibly an anonymous one, though I don't
like 'em myself), to do the job.

As I say, that's all a bit complicated. It is undoubtedly cleaner, and in a
different language I would follow that pattern without hesitation, but Java
makes it pretty messy, and since the gain is only that I don't have to remember
to close() the stream, I'm not sure the mess is worth it.

-- chris
Thank you very much. I will take the first approach.
 
S

Shawn

One more question: In the following program, I feel I am stuck with the
line:
printwriter = new PrintWriter(new
FileOutputStream(_fileChooser.getSelectedFile()));

Because the stuff I am saving maynot be text files. If it is other
things, then FileOutputStream should be replaced.

I cannot figure out more generic ways.

Thank you for your help.

<code>
public class FileSavingHelper {
private JFileChooser _fileChooser = null;

public FileSavingHelper()
{
_fileChooser = new JFileChooser(new File("."));
_fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
}

public PrintWriter getPrintWriter()
{
PrintWriter printwriter = null;

if (_fileChooser.showSaveDialog(null) ==
JFileChooser.APPROVE_OPTION) //user clicks Save button
{
//open the printwriter
try
{
printwriter = new PrintWriter(new
FileOutputStream(_fileChooser.getSelectedFile()));
}
catch(FileNotFoundException e)
{
System.out.println("Error opening the file " +
_fileChooser.getSelectedFile().getAbsolutePath());
}
}
else //user clicked Cancel button
{
System.out.println("Save command cancelled by user.");
}

return printwriter;
} //end of getPrintWriter
}
</code>

To use it:
PrintWriter pw = new FileSavingHelper().getPrintWriter();
pw.println("Hello");
pw.println("");
pw.println("This is Thursday");

pw.close();
 
C

Chris Uppal

Shawn said:
One more question: In the following program, I feel I am stuck with the
line:
printwriter = new PrintWriter(new
FileOutputStream(_fileChooser.getSelectedFile()));

Don't pass any sort of java.io.Writer to what I called the FileWriter. Always
pass a java.io_OutputStream and let the FileWriter wrap that in an
OutputStreamWriter if it wants to.

BTW, it would /probably/ be a good idea for your FileWriter to wrap a
BufferedOutputStream around the FileOutputStream before passing it to the
FileWriter. If you do decide to do that, then you should make it clear in the
documentation[*] that the FileSaver is guaranteed to do so.

-- chris

[*] if there is any ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top