Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Can someone explain to me if what this method mean?
clientOutputStreams = new ArrayList();
public void tellEveryone(String message) {
Iterator it = clientOutputStreams.iterator();
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message);
writer.flush();
} catch(Exception ex){ex.printStackTrace();}
}//end while
}//end method
Any help would be appreciated.
It seems to be implementing an Observer pattern where subscribers are the output streams targets.
That is, you have a list of output streams where the message is going to be published whenever someone calls to tellEveryone method. Having the output streams references stored in a list allows to easily add "listeners", in this case, output channels without changing your code.
This is your code commented:
clientOutputStreams = new ArrayList(); //Subscribers list
...
...
public void tellEveryone(String message) { //Publish your message writing it in each single outPutStream
Iterator it = clientOutputStreams.iterator(); //Get an iterator to traverse the subscriber list
while(it.hasNext()) {
try {
PrintWriter writer = (PrintWriter) it.next();
writer.println(message); //Print the message.
writer.flush();
} catch(Exception ex){ex.printStackTrace();} //Catch any posssible exception, (what happens if one stream is closed?)
}//end while
}//end method
An example of use could be a log for which you want the messages to be sent through a socket connection as well as to be stored in a file. To perform that task you just have to add the socket's PrintWriter object and your file's PrintWriter to clientOutputStream once.
Then, whenever a message is to be logged you just have to call to tellEveryone and it will be stored in the file and sent to the connection receiver.
This method seems to output the "clientOutputStreams" to the "message", and turned the ASCII code into the default character set. The iterator, in my view, it looks like a poniter, points to the element of the array.
Related
I have an ArrayList of Employee objects where Employee class implements Serializable. I am using this code to write lists to a file:
ArrayList<Employee> empList = new ArrayList<>();
FileOutputStream fos = new FileOutputStream("EmpObject.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// write object to file
empList .add(emp1);
empList .add(emp2);
oos.writeObject(empList);
empList .add(emp3);
oos.writeObject(empList);
}
If I try to de-serialize it I am just getting first two objects not the 3rd one. Can anyone please try why is it?
edit1: If I add all elements at once everything is fine but not the way I did first. What is the difference?
ArrayList<Employee> empList = new ArrayList<>();
FileOutputStream fos = new FileOutputStream("EmpObject.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// write object to file
empList .add(emp1);
empList .add(emp2);
empList .add(emp3);
oos.writeObject(empList);
}
After this I have 3 elements
As GhostCat and uaraven already mentioned reset does not what you are expecting it to do and you should have a look at a tutorial on serialization and maybe consider using sth. else if this isn't fitting your use case.
Your code could look as follows if creating a new FileOutputStream:
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class SerializationTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
String path = "EmpObject.ser";
ArrayList<Employee> empList = new ArrayList<>();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path));
empList.add(emp1);
empList.add(emp2);
oos.writeObject(empList);
empList.add(emp3);
// Create a new FileOutputStream to override the files content instead of appending the new employee list
oos = new ObjectOutputStream( new FileOutputStream(path));
oos.writeObject(empList);
ObjectInputStream objectinputstream = new ObjectInputStream(new FileInputStream(path));
List<Employee> readCase = (List<Employee>) objectinputstream.readObject();
System.out.println(readCase);
}
}
What happens with your code:
you write the list into the file, with two entries
you reset the stream
you write the list again, with three entries
Thus your file contains two values, yes. Two lists, one with 2, one with 3 entries.
In other words: reset() doesn't reset what has been written to the file! You wrote one list with two entries. You are only resetting the information about stored objects, so that emp1 and emp2 get serialized completely again. Without the call to reset, the JVM would understand that it doesn't need to fully serialize emp1 and emp2 again.
Meaning: by default the JVM compresses the amount of data to transmit. It remembers which objects where already written, and instead of writing them repeatedly, it only writes something like "object X that was serialized earlier on comes again" into the stream.
So: I think you simply do not understand the point of the reset() method. Solution: read a small tutorial, like the one from tutorialspoint.
Edit given the latest comment by the OP:
What you ask for isn't possible in this way. You are writing list objects. That means that all entries of that list at that point get written to the file. The JVM remembers "that list has been written already", so it will not write it again, even when its internal state changed in the meantime.
Basically ObjectOutputStream remembers objects that are written to it. If the same object (by reference) is written again, it is not serialized, but rather a reference to previous serialized data is written to stream. reset() method cleans up internal data structures of ObjectOutputStream and allows you to write the same object again. reset() does not discard data already written to the stream.
If you try to deserialize your stream into two ArrayLists, you'll get one with two elements and one with three elements.
If you remove call to reset() method, then you will get two array lists with two elements (one actually serialized, and another as a reference to the previous serialized instance)
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
Right now to test my mock service method call parameters i use below techniques, is there any better or latest way to do that?
#Test
public void testSendOutBidNotificationWhenCurrentBidderIsNotNullAndDifferentThenUserWithBidDifferenceNonZero(){
Event event = new Event();
event.setCurrency(Currency.USD);
Item item = new Item();
item.setCode("TST");
User user = new User("current#current.com", 8888888888L);
User currentHighBidder = new User("high#high.com", 9999999999L);
item.setCurrentHighBidder(currentHighBidder);
doReturn(10).when(itemService).getBidIncrement(any(), any());
ArgumentCaptor<TextMessage> textMessageCaptor = ArgumentCaptor.forClass(TextMessage.class);
textMessagePrepareService.sendOutBidNotification(event, item, user, 20, currentHighBidder);
verify(textMessageService).sendText(textMessageCaptor.capture());
assertEquals("You have been outbid for item TST. The new bid is $20, so you need to bid $10 more than that to win the item. For example: TST$30",
textMessageCaptor.getValue().getMessage());
}
here i am capturing the TextMessage which will be used as parameter in sendText method and testing the values in that which will be constructed previously.
Method under test is as Below
public void sendOutBidNotification(Event event, Item item, User user, int bidAmount, User currentHighBidder){
if (currentHighBidder != null && !currentHighBidder.equals(user)) {
log.info("Outbid person different: " + currentHighBidder);
try {
int bidIncrement = itemService.getBidIncrement(item, eventService.getAuction(event));
Map<String, String> params = new HashMap<String, String>();
params.put("increment", String.valueOf(bidIncrement));
params.put("required", String.valueOf(bidAmount + bidIncrement));
params.put("amount", String.valueOf(bidAmount));
params.put("item_code", item.getCode());
params.put("currency_symbol", event.getCurrency().getSymbol());
String loserMessage = this.getLooserOutBidNotificationMessage(bidIncrement, params);
TextMessage textMessage = new TextMessage(loserMessage, event.getAePhoneNumber(), currentHighBidder, loserMessage);
textMessageService.sendText(textMessage);
} catch (Exception e) {
log.error("Exception Occurred : " + e);
e.printStackTrace();
}
}
}
There is a better way: don't use new to create that TextMessage. Instead, have a factory that creates the message for you; and use dependency injection go put that factory in your class under test.
Because then you gain control over that TextMessage object that gets used when that method is called! Meaning: you could mock that factory, and have it return a "known" TextMessage object. And now you only need to verify that your service is called with that object. That allows you to just do a simply argument match; and you can get rid of that ArgumentCaptor and the assert on it completely!
And that would be really good; as: doing an assertEquals() for the text of a message is bad practice. Those messages change all the time; and people will get annoyed quickly when they find that changing the content of some resource bundle that contains the message text breaks a unit test.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
If I wanted to build a constructor for a class to import a file, which I have passed in a String nameOfFile, how can I initialize the object's state, then open the document file, and process each line of the document? References and clear explanation would be appreciated. I'm just beginning to learn java.
To clear up my question, how can you build an object for a document file you have imported? What I'm doing right now is that I have wrote a class but i'm struggling with building an object for a SPECIFIC file. What I have thus far is
public class theImport
{
theImport(String nameOfFile)
{
(Here is where I want to achieve all the listing I have above.)
}
.
.
.
}
I believe you would do this in a two-step process.
Step one: The actual constructor.
private String nOF;
public ClassName(String nameOfFile) {
nOF = nameOfFile;
}
Step two: Evaluation of the file. Since this can fail for a variety of reasons (for example the file not existing, it shouldn't go to the constructor (you can't catch these errors from a return type you aren't having in the constructor)
public boolean Evaluate() {
//Evaluate your file and return false if it fails for whatever reason.
}
My Java isn't the best at the moment, but this should tip you in the right direction.
Propably you mean something like this:
public class theImport
{
theImport(String nameOfFile)
{
try {
FileReader input = new FileReader(nameOfFile);
BufferedReader bufRead = new BufferedReader(input);
String line;
line = bufRead.readLine();
//this will loop thought the lines of the file
while (line != null){
line = bufRead.readLine();
//do whatever you want with the line
}
bufRead.close();
}
catch (Exception e){
e.printStackTrace();
}
}
}
I have some input that I add to a serialized object.
Now when I read the serialized object, I want to check if it exists... If not loop till it has a value in it.
How do i modify the deserialization function to handle that.
There is basically a delay in populating my serializable object. So in the meantime if i were to read that object, it is going to be empty. I want to put a check to read only when it has data in it. if not it should wait till it has some data
public String _displayResults(){
String SomeData = "";
try {
FileInputStream fis = new FileInputStream("SomeDataobj");
ObjectInputStream ois = new ObjectInputStream(fis);
SomeData = (String)ois.readObject();
ois.close();
}
catch(Exception e) {
System.out.println("Exception during deserialization: ");
}
return SomeData;
}
What I tried:
added a wait condition for 2 secs for 10 times... Is there a cleaner way.
while ( ois.readObject().toString().equalsIgnoreCase("") && i <10){
Thread.sleep(2000);
i++;
}
Java provides an API called Externalizable, which allows you to customize the (de) serialization. Serialiazable is marker interface and that indicates the object can be wrote to output stream. Externalizable provides two methods readExternal() and writeExternal() where you can override the behavior.
Your question is not so clear about what you want to achieve, so I am not sure if the above information is helpful for you
This question already has an answer here:
StreamCorruptedException: invalid type code: AC
(1 answer)
Closed 5 years ago.
I was trying out a program that was given in the exercise at the end of the chapter 'Serialization'.
The program requires me to declare a class Person which encapsulates only two data members of type Name and Address , which are also classes.
Then I have to take a series of names and addresses from the keyboard , create objects and write them to the file.
However , if the FILE ALREADY EXISTS then the objects must be APPENDED to the existing file.
My program runs perfectly for the first time but for the second time , when I try to read back the appended records , I get an Exception
java.io.StreamCorruptedException: invalid type code: AC
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1374)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at Trial.main(Trial.java:66)
I did my bit of research on this and found that the StreamHeader can be written ONLY ONCE and appending corrupts it.
What is the way around it ???
The Object Writing Code is:
try(ObjectOutputStream stream = new ObjectOutputStream(new BufferedOutputStream(Files.newOutputStream(filePath,WRITE,CREATE,APPEND)))) {
for(int i = 0;i<name.length;i++) {
Person aPerson = new Person(name[i],address[i]);
System.out.println(aPerson);
stream.writeObject(aPerson);
stream.reset();
aPerson = null;
}
System.out.println("Writing Complete");
Yes, I've had this problem myself before... it is not possible, unfortunately.
What you could do is to place your objects into a List and persist the full list at a time. As the list is an object it can persisted just as easily. I know this is terrible as this require the entire contents to be read into memory, but it is the only way as far as I know.
The other option (which I recommend) is that you use something like JSon to commit your data. GSon works quite well for this purpose. You can then simply marshall and unmarshall your objects which can be committed to a text file. It's very easy to do as a single line of code is required to go either way (object to JSon-string and vice versa).
This works. So debug your program and see why it doesn't. Probably don't call reset()
public class ClassTest {
public static void main(String a[]) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c:/temp/foo.txt"));
oos.writeObject(new Test("foo", "bar"));
oos.writeObject(new Test("baz", "brr"));
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c:/temp/foo.txt"));
System.out.println(ois.readObject());
System.out.println(ois.readObject());
ois.close();
}
}
class Test implements Serializable {
private String fld1;
private String fld2;
public Test(String v1, String v2) {
this.fld1 = v1;
this.fld2 = v2;
}
#Override
public String toString() {
return "Test [fld1=" + fld1 + ", fld2=" + fld2 + "]";
}
}