My goal is to write an object to zip file in json format. The simplest way of doing it is:
ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
String json = gson.toJson(object);
zip.write(json.getBytes());
But I want to avoid to load the whole object to a single string. So I wrapped a zip stream into a writer object:
Writer writer = new OutputStreamWriter(zip);
And after that I write the entry in the following way:
zip.putNextEntry(entry);
gson.toJson(content, writer);
writer.flush();
zip.closeEntry();
zip.flush();
It works fine, but it seems very messy using writer and zip objects at the same time. Is there any better solution for this problem?
You can make it a bit simplier with Jackson which has methods to write directly to an OutputStream
ObjectMapper mapper = new ObjectMapper();
try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile))){
out.putNextEntry(new ZipEntry("object.json"));
mapper.writeValue(out, object);
}
You may declare one or more resources in a try-with-resources statement. For example
try (
ZipOutputStream zip = new ZipOutputStream(new BufferedOutputStream(new
FileOutputStream(zipFile)));
Writer writer = new OutputStreamWriter(zip);
) {
zip.putNextEntry(entry);
gson.toJson(content, writer);
}
The close methods are automatically called in this order. Note that the close methods of resources are called in the opposite order of their creation. With regards to flush, close flush it first.
public abstract void close() throws IOException
Closes the stream, flushing it first. Once the stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously closed stream has no effect.
Related
I am trying to create a fixed length file output using beanio. I don't want to write the physical file, instead I want to write content to an OutputStream.
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
StreamFactory factory = StreamFactory.newInstance();
StreamBuilder builder = new StreamBuilder("sb")
.format("fixedlength")
.parser(new FixedLengthParserBuilder())
.addRecord(Team.class);
factory.define(builder);
OutputStreamWriter writer = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
BeanWriter bw = sf.createWriter("sb", writer);
bw.write(teamVO) // teamVO has some value.
try(OutputStream os = new FileOutputStream("file.txt")){
outputStream.writeTo(os); //Doing this only to check outputStream has some value
}
Here the file created, file.txt has no content in it, It is of size 0 kb.
I am able to write the file in the following method, but as I don't want to write the file in physical location, I thought of writing the contents in to a outputStream and then later in a different method, it can be converted in to a file
//This is working and creates file successfully
StreamFactory factory = StreamFactory.newInstance();
StreamBuilder builder = new StreamBuilder("sb")
.format("fixedlength")
.parser(new FixedLengthParserBuilder())
.addRecord(Team.class)
factory.define(builder);
BeanWriter bw = factory.createWriter("sb", new File("file.txt"));
bw.write(teamVO);
Why in the first approach the file is created with size 0 kb?
It looks like you haven't written enough data to the OutputstreamWriter for it to push some data to the underlying ByteArrayOutputStream. You have 2 options here.
Flush the writer object manually and then close it. This will then write the data to the outputStream. I would not recommend this approach because the writer may not be flushed or closed should there be any Exception before you could manually flush and close the writer.
Use a try-with-resource block for the writer which should take care of closing the writer and ultimately flushing the data to the outputStream
This should do the trick:
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (final OutputStreamWriter writer = new OutputStreamWriter(outputStream) ) {
final BeanWriter bw = factory.createWriter("sb", writer);
final Team teamVO = new Team();
teamVO.setName("TESTING");
bw.write(teamVO); // teamVO has some value.
}
try (OutputStream os = new FileOutputStream("file.txt") ) {
outputStream.writeTo(os); // Doing this only to check outputStream has some value
}
I have a CSV file in Resources of my automation script and I need to amend one cell value to a parameter value I get by creating a folder in a site, I ran this code but then an error comes:
"(The process cannot access the file because it is being used by another process)".
Can anyone let me know how to write my parameter value to CSV file cell, please.
TIA
Method:
public static void writeCSV(String filePath, String separator) throws IOException {
try (OutputStream fileStream = new BufferedOutputStream(new FileOutputStream(filePath));
Writer outStreamWriter = new OutputStreamWriter(fileStream, StandardCharsets.UTF_8);
BufferedWriter buffWriter = new BufferedWriter(outStreamWriter)) {
buffWriter.append("https://mobile/sample_v4.zip");
buffWriter.append(separator);
buffWriter.append(createdTitle);
buffWriter.append(separator);
buffWriter.append("http://2-title-conversion/documentlibrary");
buffWriter.append(separator);
buffWriter.append("TRUE");
buffWriter.append(separator);
buffWriter.append("TRUE");
buffWriter.flush();
}
#Test segment,
loginPg.writeCSV("C:\\Users\\urathya\\Documents\\Automation\\03-11\\resources\\CS.csv",",");
You are not closing the output stream, please close it, it will close file and you can use the same file to append the data.
I'm little confused about FileWriter and FileOutputStream. As I see source code of FileWriter there are just 4 constructors and each constructor is calling FileOutputStream's constructor.
public FileWriter(String fileName) throws IOException {
super(new FileOutputStream(fileName));
}
public FileWriter(String fileName, boolean append) throws IOException {
super(new FileOutputStream(fileName, append));
}
public FileWriter(File file) throws IOException {
super(new FileOutputStream(file));
}
public FileWriter(File file, boolean append) throws IOException {
super(new FileOutputStream(file, append));
}
public FileWriter(FileDescriptor fd) {
super(new FileOutputStream(fd));
}
After searching difference between them I found mentioned here.
FileOutputStream is meant for writing streams of raw bytes such as
image data. For writing streams of characters, consider using
FileWriter.
How FileWriter can make difference? Even it still calling FileOutputStream's constructor without any changing.
FileWriter is a Writer. It's about writing text - and it happens to be writing it to a file. It does that by holding a reference to a FileOutputStream, which is created in the FileWriter constructor and passed to the superclass constructor.
FileOutputStream is an OutputStream. It's about writing binary data. If you want to write text to it, you need something to convert that text to binary data - and that's exactly what FileWriter does. Personally I prefer to use FileOutputStream wrapped in an OutputStreamWriter by me to allow me to specify the character encoding (as FileWriter always uses the platform default encoding, annoyingly).
Basically, think of FileWriter is a simple way of letting you write:
Writer writer = new FileWriter("test.txt");
instead of
Writer writer = new OutputStreamWriter(new FileOutputStream("test.txt"));
Except I'd normally recommend using the overload of the OutputStreamWriter constructor that accepts a Charset.
FileOutputStream is to write primitive types of data, like int, while FileWriter is to write character-oriented data.
FileOutputStream does not come with methods to deal with strings. If you want to use FileOutputStream to write a string to a file, you have to go like:
FileOutputStream fos=new FileOutputStream();
String str="Hello";
byte b[]=str.getBytes();
fos.write(b);
fos.close();
In Filewriter there is no conversion between string and byte array. You could simply use:
FileWriter fr=new FileWriter("C:\\");
fr.write("Hello");
fr.close();
Do not forget to throw any exceptions if needed.
A FileOutputStream writes bytes directly. A FileWriter encapsulates a FileOutputStream (by creating it in the FileWriter constructor as in your question) and provides convenience methods to write characters and Strings.
Actually, the question is when do use Reader/Writer and when Stream?
How to Decide Which to use:
1.If you are dealing with binary data (e.g. an image) use Streams.
2.If you are using non-ASCII Unicode characters, use Readers/Writers.
3.If you are using ordinary ASCII text you can (usually) use either.
try
{
File dataFile = new File("C:/Users/keatit/Desktop/players.txt");
if(!dataFile.exists())
{
dataFile.createNewFile();
}
FileOutputStream fos = new FileOutputStream("C:/Users/keatit/Desktop/players.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(players);
oos.close();
}
catch(FileNotFoundException fnfex)
{
System.out.println(fnfex.getMessage());
}
catch(IOException ioex)
{
System.out.println(ioex.getMessage());
}
I have a class player which implement Serializable but when I write objects to files the text is messed up and looks like the following. Any help would be much appreciated. Thank you.
"¬í sr java.util.ArrayListxÒ™Ça I sizexp w sr players.playerÌ`~%×êòœ I ageL firstNamet Ljava/lang/String;xp t Trevorsq ~ t Michaelax"
This is binary serialization. It's not meant to be writing to a human-readable text file. For that, you should look into something like JSON or YAML. I'd strongly recommend against writing to a .txt file using ObjectOutputStream - it gives the wrong impression.
The point of binary serialization is to be able to deserialize it later with the same serialization protocol - so in this case you'd use ObjectInputStream. You should find that that is able to correctly deserialize the object stored in your file.
(Side-note: FileOutputStream will create a new file automatically if it doesn't exist - you don't need to do so yourself. Additionally, you should use a try-with-resources statement to clean up automatically, rather than just calling close() outside a finally block.)
I'm writing a simple program that retrieves XML data from an object, and parses it dynamically, based on user criteria. I am having trouble getting the XML data from the object, due to the format it is available in.
The object containing the XML returns the data as a byteArray of a zipFile, like so.
MyObject data = getData();
byte[] byteArray = data.getPayload();
//The above returns the byteArray of a zipFile
The way I checked this, is by writing the byteArray to a String
String str = new String(byteArray);
//The above returns a string with strange characters in it.
Then I wrote the data to a file.
FileOutputStream fos = new FileOutputStream("new.txt");
fos.write(byteArray);
I renamed new.txt as new.zip. When I opened it using WinRAR, out popped the XML.
My problem is that, I don't know how to do this conversion in Java using streams, without writing the data to a zip file first, and then reading it. Writing data to disk will make the software way too slow.
Any ideas/code snippets/info you could give me would be really appreciated!! Thanks
Also, if you need a better explanation from me, I'd be happy to elaborate.
As another option, I am wondering whether an XMLReader would work with a ZipInputStream as InputSource.
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
ZipInputStream zis = new ZipInputStream(bis);
InputSource inputSource = new InputSource(zis);
A zip archive can contain several files. You have to position the zip stream on the first entry before parsing the content:
ByteArrayInputStream bis = new ByteArrayInputStream(byteArray);
ZipInputStream zis = new ZipInputStream(bis);
ZipEntry entry = zis.getNextEntry();
InputSource inputSource = new InputSource(new BoundedInputStream(zis, entry.getCompressedSize()));
The BoundedInputStream class is taken from Apache Commons IO (http://commons.apache.org/io)