Saving a Hashset to a file in Java - java

I know this question has been asked a million times and I have seen a million solutions but none that work for me. I have a hashet that I want to write to a file but I want each element in the Hashset in a separate line.
Here is my code:
Collection<String> similar4 = new HashSet<String>(file268List);
Collection <String> different4 = new HashSet<String>();
different4.addAll(file268List);
different4.addAll(sqlFileList);
similar4.retainAll(sqlFileList);
different4.removeAll(similar4);
Iterator hashSetIterator = different.iterator();
while(hashSetIterator.hasNext()){
System.out.println(hashSetIterator.next());
}
ObjectOutputStream writer = new ObjectOutputStream(new FileOutputStream("HashSet.txt"));
while(hashSetIterator.hasNext()){
Object o = hashSetIterator.next();
writer.writeObject(o);
}

Where you got it wrong is that you are trying to serialize the strings instead of just printing them to the file, exactly the same way you print them to the screen:
PrintStream out = new PrintStream(new FileOutputStream("HashSet.txt")));
Iterator hashSetIterator = different.iterator();
while(hashSetIterator.hasNext()){
out.println(hashSetIterator.next());
}

ObjectOutputStream will try to serialize the String as an object (binary format). I think you you want to use a PrintWriter instead. Example:
PrintWriter writer= new PrintWriter( new OutputStreamWriter( new FileOutputStream( "HashSet.txt"), "UTF-8" ));
while(hashSetIterator.hasNext()) {
String o = hashSetIterator.next();
writer.println(o);
}
Note that per this answer and the answer from Marko, you can use PrintStream or PrintWriter to output strings (characters). There is little difference between the two, but be sure to specify a character encoding if you work with non standard characters or need to read/write files across different platforms.

Related

Why there is a 't' in front of column while using stream resolution return byte array outputstream? [duplicate]

This question already has an answer here:
Writing LinkedList into text file via ObjectOutputStream but output is garbage
(1 answer)
Closed 1 year ago.
I am using Spring framework, and use streamresolution to return a .txt file for user to download.
The result of data is fine, however, there is a 't' in front of every column of data,
and besides the last column, there is a 'w' in the end of every column.
I can't not understand why because the data seems fine, and I didn't told the program to create the letter.
Here is my code:
// A list of String, which are the data, it might looks like 20200810,a,b,c,100,55,.....
// the whole is a String contains comma
List<String> dataList = (List<String>) parameters.get("myData");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
StreamingResolution streamingResolution = null;
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject("\n");
for (String s : dataList) {
oos.writeObject(s.trim());
oos.writeUTF("\n");
}
streamingResolution = new StreamingResolution("text/plain", new ByteArrayInputStream(outputStream.toByteArray()));
streamingResolution.setCharacterEncoding(CharEncoding.UTF_8);
String year = Integer.toString((Integer.parseInt(end.substring(0, 4));
String day = year + end.substring(4, 6);
oos.close();
return streamingResolution.setFilename(day + ".txt");
while I download the data, 202108.txt
it might looks like
t ?0210810,a,b,c,100,55w
t ?0210810,d,e,f,99,60
could anyone please tell me why there would be a 't' in the front
and a 'w' in the end?
And how to fix this?
Thanks a lot.
This code uses an ObjectOutputStream, which is used to write serialized Java data in a binary format. It is not a plain text format, and should not be used in this way. The extra characters are bytes that are defined in the Java Object Serialization Specification.
To write plain text, you can use the java.io.PrintStream class instead. For example:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(outputStream, false, StandardCharsets.UTF_8);
printStream.println();
for (String s : dataList) {
printStream.println(s.trim());
}
printStream.flush();
StreamingResolution streamingResolution = new StreamingResolution("text/plain", new ByteArrayInputStream(outputStream.toByteArray()));
streamingResolution.setCharacterEncoding(CharEncoding.UTF_8);
Note that I also simplified the code by moving the streamingResolution local variable declaration to where it is assigned.
This is a straightforward translation of the code provided, to show you how to use the PrintStream class, however it may not be the best way to write it. The StreamingResolution class appears to be part of the Stripes Framework. It is intended for streaming large responses to the client. However, this implementation does not actually stream the response, it accumulates it into a byte array. A better way to implement this would be to subclass the StreamingResponse class, as described in the Stripe documentation, to write directly to the response:
return new StreamingResolution("text/plain") {
public void stream(HttpServletResponse response) throws Exception {
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.println();
for (String s : dataList) {
out.println(s.trim());
}
out.flush();
}
}.setFilename(day + ".txt");

Java I/O - Reuse InputStream Object

Is there anyway to reuse an inputStream by changing its content? (Without new statement).
For instance, I was able to something very close to my requirement, but not enough
In the following code I am using a SequenceInputStream, and everytime I am adding a new InputStream to that sequence.
But I would like to do the same thing by using the same inputStream (I don't care which implementation of InputStream).
I thought about mark()/reset() APIs, but i still need to change the content to be read.
The idea to avoid new InputStream creations is because of performance issues
//Input Streams
List<InputStream> inputStreams = new ArrayList<InputStream>();
try{
//First InputStream
byte[] input = new byte[]{24,8,102,97};
inputStreams.add(new ByteArrayInputStream(input));
Enumeration<InputStream> enu = Collections.enumeration(inputStreams);
SequenceInputStream is = new SequenceInputStream(enu);
byte [] out = new byte[input.length];
is.read(out);
for (byte b : out){
System.out.println(b);//Will print 24,8,102,97
}
//Second InputStream
input = new byte[]{ 4,66};
inputStreams.add(new ByteArrayInputStream(input));
out = new byte[input.length];
is.read(out);
for (byte b : out){
System.out.println(b);//will print 4,66
}
is.close();
}catch (Exception e){//
}
No, You can't restart reading the input stream after it reaches to the end of the stream as it is uni-directional i.e. moves only in single direction.
But Refer below links, they may help:
How to Cache InputStream for Multiple Use
Getting an InputStream to read more than once, regardless of markSupported()
You could create your own implementation (subclass) of InputStream that would allow what you require. I doubt there is an existing implementation of this.
I highly doubt you'll get any measurable performance boost from this though, there's not much of logic in e.g. FileInputStream that you wouldn't need to perform anyways, and Java is well optimized for garbage-collecting short-lived objects.

Print Objects to file txt

I'm trying to print objects into file.
Then I want to import them back to my program.
ObjectOutputStream not working, What am I missing? (try, catch not visible here but they're doing their job)
Map< Account, Customer> customerInfo = new HashMap< Account, Customer>();
File bankFile = new File("Bank.txt");
FileOutputStream fOut = new FileOutputStream( bankFile);
ObjectOutputStream objOut = new ObjectOutputStream(fOut);
for(Map.Entry<Account, Customer> e : bank.customerInfo.entrySet())
{
objOut.writeObject(e.getValue());
objOut.writeObject(e.getKey());
}
objOut.flush();
objOut.close();
fOut.close();
My problem here is that ObjectOutputStream is not working properly, it prints some weird code. I've used other methods to print out to file and they work just fine.
I've tried printing to different file extensions,
I tried changing the encoding for both the file and eclipse.
I tried different methods for getting the info from the Map using ObjectOutputStream. Is there a reason why ObjectOutputStream prints weird characters that I haven't think of? The entire file is almost impossible to read. Thanks!
Ps. some of the weird print, don't know if it helps.
¬ísrCustomerDìUðkJ
personalIdNumLnametLjava/lang/String;xpthellosr
SavingAccountUÞÀÀ;>ZfreeWithdrawDwithdrawalInterestRateLaccountTypeq~xrAccount é=UáÐI
accountNumberDbalanceDinterestRateLaccountTypeq~L transListtLjava/util/List;xpé?záG®{tsrjava.util.ArrayListxÒÇaIsizexpw
x?záG®{tSaving Accountq~sr
CreditAccountÝ
*5&­VcLaccountTypeq~xq~ê?záG®{q~sq~ w
xtCredit Account
It's really quite simple. First things first, create a class that implements Serializable. Serializable is a marker interface, so you don't need to implement any methods for it:
public class Shoe implements Serializable { ... }
NOTE: If Shoe has other classes in it, for example Heel, or Buckle, those classes also need to implement the Serializable interface.
Next step is to write that to a file, using an ObjectOutputStream.
FileOutputStream out = new FileOutputStream("myfile.txt");
// Create the stream to the file you want to write too.
ObjectOutputStream objOut = new ObjectOutputStream(out);
// Use the FileOutputStream as the constructor argument for your object.
objOut.writeObject(new Shoe("Prada"));
// Write your object to the output stream.
objOut.close();
// MAKE SURE YOU CLOSE to avoid memory leaks, and make sure it actually writes.
There you have it. The serialized object is written to the txt file. Now to read it, it's just a case of using the ObjectInputStream.
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream("myfile.txt");
Object obj = objIn.readObject();
if(obj instanceof Shoe)
{
Shoe shoe = (Shoe)obj;
}
And you've got an object you can use.

Update only the new content in a file all five minutes

I get a file personHashMap.ser with a HashMap in it. Here's the code how i create it:
String file_path = ("//releasearea/ToolReleaseArea/user/personHashMap.ser");
public void createFile(Map<String, String> newContent) {
try{
File file = new File(file_path);
FileOutputStream fos=new FileOutputStream(file);
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(newContent);
oos.flush();
oos.close();
fos.close();
}catch (Exception e){
System.err.println("Error in FileWrite: " + e.getMessage());
}
}
Now i want, when the program is running, that all five minutes update the file personHashMap.ser only with the content which changed. So the method i called:
public void updateFile(Map<String, String> newContent) {
Map<String, String> oldLdapContent = readFile();
if(!oldLdapContent.equals(ldapContent)){ // they arent the same,
// so i must update the file
}
}
But now i haven't any ideas how i can realise that.
And is it better for the performance to update only the new content or should i clean the full file and insert the new list again?
Hope you can Help me..
EDIT:
The HashMap includes i.e street=Example Street.
But now, the new street called New Example Street. Now i must update the HashMap in the File. So i can't just append the new content...
Firstly HashMap isn't really an appropriate choice. It's designed for in-memory usage, not serialization (though of course it can be serialized in the standard way). But if it's just 2kb, then go ahead and write the whole thing rather than the updated data.
Second, you seem to be overly worried about performance of this rather trivial method (for 2kb the write will take mere milliseconds). I would be worried more about consistency and concurrency issues. I suggest you look into using a lightweight database such as JavaDB or h2.
Use the constructor FileOutputStream(File file, boolean append), set the boolean append to true. It will append the text in the existing file.
You can call the updateFile method in a loop and then call sleep for 5 minutes (5*60*1000 ms).
Thread.Sleep(300000); // sleep for 5 minutes
To append to your already existing file you can use :
FileOutputStream fooStream = new FileOutputStream(file, true);

Writing multiple files with Spring Batch

I'm a newbie in Spring Batch, and I would appreciate some help to resolve this situation: I read some files with a MultiResourceItemReader, make some marshalling work, in the ItemProcessor I receive a String and return a Map<String, List<String>>, so my problem is that in the ItemWriter I should iterate the keys of the Map and for each one of them generate a new file containing the value associated with that key, can someone point me out in the right direction in order to create the files?
I'm also using a MultiResourceItemWriter because I need to generates files with a maximum of lines.
Thanks in advance
Well, finaly got a solution, I'm not really excited about it but it's working and I don't have much more time, so I've extended the MultiResourceItemWriter and redefined the "write" method, processing the map's elements and writing the files by myself.
In case anyone out there needs it, here it is.
#Override
public void write(List items) throws Exception {
for (Object o : items) {
//do some processing here
writeFile(anotherObject);
}
private void writeFile (AnotherObject anotherObject) throws IOException {
File file = new File("name.xml");
boolean restarted = file.exists();
FileUtils.setUpOutputFile(file, restarted, true, true);
StringBuffer sb = new StringBuffer();
sb.append(xStream.toXML(anotherObject));
FileOutputStream os = new FileOutputStream(file, true);
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(os, Charset.forName("UTF-8")));
bufferedWriter.write(sb.toString());
bufferedWriter.close();
}
And that's it, I want to believe that there is a better option that I don't know, but for the moment this is my solution. If anyone knows how can I enhance my implementation, I'd like to know it.

Categories

Resources