How to write object to and read object from file using servlet - java

i am trying to write objects of a POJO class to a file and read them with the same Servlet with the Java serialization methods. I have the POJO in a public class and the writer and reader codes in two other public classes. I then accessed both the writer and reader methods in a servlet. The problem is that only the last object written to the file could be deserialized. It seems previously written objects were overwritten. See the codes below please.
The POJO class:
public class Comment implements Serializable{
private String name;//max 24 digits
private String date;//6 digits
private String email;//max 24 digits
private String comment; //to be stored into database as clob no max
private String id;//auto generated
public Comment(){}
public Comment(String id){
this.id = id;
}
public Comment(String name, String email, String comment){
this.name=name;
this.date=date;
this.email=email;
this.comment=comment;
}
public Comment(String name, String date, String email, String comment){
this.name=name;
this.date=date;
this.email=email;
this.comment=comment;
}
public Comment(String name, String date, String email, String comment, String id){
this.name=name;
this.date=date;
this.email=email;
this.comment=comment;
this.id=id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* #return the date
*/
public String getDate() {
return date;
}
/**
* #return the email
*/
public String getEmail() {
return email;
}
/**
* #param email the email to set
*/
public void setEmail(String email) {
this.email = email;
}
/**
* #return the id
*/
public String getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(String id) {
this.id = id;
}
/**
* #return the comment
*/
public String getComment() {
return comment;
}
/**
* #param comment the comment to set
*/
public void setComment(String comment) {
this.comment = comment;
}
Comment myComment;
#Override
public int hashCode()
{
return 31 + id.hashCode();
}
#Override
public boolean equals(Object obj) {
if(obj instanceof Comment){
Comment another = (Comment)obj;
if(this.getId()==another.getId()){
return true;
}
}
return false;
}
public String toString(){
StringBuilder sb = new StringBuilder();
return sb.append(name).append(",").append(" ").append(date).append(",").append(" ").append(comment).append(",").append(" ").append(id).append(",").append(" ").append(email).toString();
}
public void setDate(String date) {
this.date = date;
}
}
The writer class:
public class ObjectStreamWriterExample {
public void write(Object obj){
File outFile = new File("out.txt");
try(ObjectOutputStream objectOutput = new ObjectOutputStream(new FileOutputStream(outFile));){
List <Object> commentList = new ArrayList<>();
commentList.add(obj);
for(Object list : commentList){
objectOutput.writeObject(list);
//System.out.println("good ok now");
}
}catch(IOException io){
System.err.println("An Error occured :");
System.out.println(io.getCause());
}
}
}
Reader class:
public class ObjectStreamReaderExample {
public List <Comment> read( String inFile){
Comment comment = null;
List <Comment> list = new ArrayList<>();
try(ObjectInputStream oi = new ObjectInputStream(new FileInputStream(inFile));){
while(true){
try {
comment = (Comment)oi.readObject();
list.add(comment);
break;
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}catch(EOFException eof){
System.err.println("Reached End of File");
eof.printStackTrace();
}
}
}catch(IOException io){
System.err.println("Error :");
io.printStackTrace();
}
return list;
}
}
The servlet:
public class ObjectStreamExample extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
ObjectStreamWriterExample oswe =new ObjectStreamWriterExample();
oswe.write(new Comment("Omobolaji", "omo#javanice.net", "omo is commenting"));
oswe.write(new Comment("Omobolaji", "omo#javanice.net", "omo is commenting again"));
oswe.write(new Comment("Omobolaji", "omo#javanice.net", "omo is commenting again hhhhh"));
ObjectStreamReaderExample osre = new ObjectStreamReaderExample();
List <Comment> list = new ArrayList<>();
list = osre.read("out.txt");
for(Comment myList : list){
out.println(myList.getName() + "<br> ");
out.println(myList.getEmail() + "<br> ");
out.println(myList.getComment() + "<br> ");
}
}
#Override
public String getServletInfo() {
return "Short description";
}// </editor-fold>
}

No mystery. Every time you call write() you create a new file and write one object to it. You also create a completely pointless list, add the one object to it, iterate the list, once, of course, and write the one object you find in it to the file. Next time you call write(), you do all this nonsense again. Result: one file, with one object in it.
You need to completely reconsider all this. You can't append to object stream files without special measures. You should:
Create the file by opening it for output.
Write as many objects to it as you wish.
Close the file.
Open the file for input.
Read objects from it until you reach end of file, which is signalled by, err, an EOFException.
Close the input file.
OR
Create a list.
Append as many objects as you wish to the list.
Open the file for output, serialize the list, close the file.
Open the file for input, deserialize one object, the list, and iterate it to recover all the original objects, and close the input file.
NB
Object streams are not text, and should not be saved in files with the .txt extension.
The fact that you're in a servlet is irrelevant.

Related

How to save the content of a file in a list in Java?

I got two methods: saveSubscribedFeeds() and loadSubscribedFeeds(). In the save-method I'm saving some data to the file feedsFile in the parameter like this:
#Override
public void saveSubscribedFeeds(List<Feed> feeds, File feedsFile) {
try {
PrintWriter pw = new PrintWriter(new FileOutputStream(feedsFile));
for (Feed feed : feeds) {
pw.println(feed.getTitle());
pw.println(feed.getDescription());
pw.println(feed.getEntries());
pw.println(feed.getUrl());
pw.println(feed.getPublishedDateString());
}
pw.close();
}
catch(IOException i) {
i.printStackTrace();
}
}
In the load-method I'm trying to load the exact same file feedsFile and return it as a List and for that I used a Scanner .
#Override
public List<Feed> loadSubscribedFeeds(File feedsFile) throws FileNotFoundException {
Scanner s = new Scanner(feedsFile.getAbsoluteFile());
List<Feed> listFeed = new ArrayList<>();
while (s.hasNextLine()) {
listFeed.add(new Feed(s.nextLine()));
}
s.close();
return listFeed;
}
However the JUnit-test is telling me that my list does't match the read object:
if (!feedsTemp.get(0).getUrl().equals(TEST_FEED_URL)
|| !feedsTemp.get(0).getTitle().equals(TEST_FEED_TITLE)
|| !feedsTemp.get(0).getDescription().equals(TEST_FEED_DESC)) {
System.err.println("The data read from save-file '" + FEEDS_FILE.getName() + "' doesn't match the test input data!");
fail("feed sample data (" + FEEDS_FILE.getAbsolutePath() + ") doesn't match read object!");
}
What am I doing wrong? Here's the Feed Class:
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.rometools.rome.feed.synd.SyndEntry;
import com.rometools.rome.feed.synd.SyndFeed;
import de.uk.java.feader.utils.FeaderUtils;
public class Feed implements Serializable, Comparable<Feed> {
private static final long serialVersionUID = 1L;
private String url;
private String title;
private String description;
private String publishedDateString;
private List<Entry> entries;
public Feed() {
}
public Feed(String url) {
super();
this.url = url;
this.entries = new ArrayList<Entry>();
this.title = "";
this.description = "";
this.publishedDateString = "";
}
/**
* Creates an instance of a Feed and transfers the feed
* data form a SyndFeed object to the new instance.
* #param url The URL string of this feed
* #param sourceFeed The SyndFeed object holding the data for this feed instance
*/
public Feed(String url, SyndFeed sourceFeed) {
this(url);
setTitle(sourceFeed.getTitle());
setDescription(sourceFeed.getDescription());
if (sourceFeed.getPublishedDate() != null)
setPublishedDateString(FeaderUtils.DATE_FORMAT.format(sourceFeed.getPublishedDate()));
for (SyndEntry entryTemp : sourceFeed.getEntries()) {
Entry entry = new Entry(entryTemp.getTitle());
entry.setContent(entryTemp.getDescription().getValue());
entry.setLinkUrl(entryTemp.getLink());
entry.setParentFeedTitle(getTitle());
if (entryTemp.getPublishedDate() != null) {
entry.setPublishedDateString(FeaderUtils.DATE_FORMAT.format(entryTemp.getPublishedDate()));
}
addEntry(entry);
}
}
public String getUrl() {
return url;
}
public void setTitle(String title) {
this.title = title != null ? title : "";
}
public String getTitle() {
return title;
}
public void setDescription(String description) {
this.description = description != null ? description : "";
}
public String getDescription() {
return description;
}
public void setPublishedDateString(String publishedDateString) {
this.publishedDateString = publishedDateString != null ? publishedDateString : "";
}
public String getPublishedDateString() {
return publishedDateString;
}
/**
* Returns a short string containing a combination of meta data for this feed
* #return info string
*/
public String getShortFeedInfo() {
return getTitle() + " [" +
getEntriesCount() + " entries]: " +
getDescription() +
(getPublishedDateString() != null && getPublishedDateString().length() > 0
? " (updated " + getPublishedDateString() + ")"
: "");
}
public void addEntry(Entry entry) {
if (entry != null) entries.add(entry);
}
public List<Entry> getEntries() {
return entries;
}
public int getEntriesCount() {
return entries.size();
}
#Override
public boolean equals(Object obj) {
return (obj instanceof Feed)
&& ((Feed)obj).getUrl().equals(url);
}
#Override
public int hashCode() {
return url.hashCode();
}
#Override
public String toString() {
return getTitle();
}
#Override
public int compareTo(Feed o) {
return getPublishedDateString().compareTo(o.getPublishedDateString());
}
}
First of all: try using a debugger to see what's going on, when you run into such issues. You can progress in your code line by line and also see variables and their contents.
Second: The Problem you are facing there, as Tushar mentionend, you are writing title, description,... in a new line each time. Then when you try to read the object, you read just one line and then try to make a new Feed object, where you populate the fields title, description... with "" in the constructor and url with the given parameter. So what happens with the next line in the File which holds the description? It will generate a Feed object with the description set as url. Of course JUnit says, it is not the same object.
What you can do now:
separate the fields by a constant character and break line only for a new Feed object. Then parse the fields from the separate lines to populate your objects. For example: url;title;description;publishedDate;\nurl2;title2;description2;publishedDate2;\n whereas the \n obviously marks the linebreak
create an XML instead and use a proper parsing library. There are already java built-in libs you can use. Here's a link to a tutorial of one of them: https://www.tutorialspoint.com/java_xml/java_dom_parse_document.htm

Why I can't get objects from file properly?

I have list of custom objects that I writre and then read to file.
Here is my class:
public class Book implements Serializable{
private int isbn;
private String category;
private String authorName;
public int getIsbn() {
return isbn;
}
public String getCatId() {
return category;
}
public void setIsbn(int isbn) {
this.isbn = isbn;
}
public void setCategory(String category) {
this.category = category;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public String getAuthorName() {
return authorName;
}
public Book() {}
//copy book
public Book(Book book, int id) {
this.category = book.category;
this.title = book.title;
this.authorName = book.authorName;
this.isbn = id;
}
}
Here is function that I use to write the list of objects:
private static <T> void writeToFile(List<T> items, String fileName) {
try {
String path = "src\\hw1\\library\\repos\\" + fileName;
FileOutputStream f = new FileOutputStream(path, true);// true- means append to file
ObjectOutputStream o = new ObjectOutputStream(f);
// Write objects to file
o.writeObject(items);
o.close();
f.close();
} catch (Exception e) {}
}
And here is function that I reade from the list:
private static <T> List<T> readFromFile(Context context, String fileName) {
try {
String path = "src\\hw1\\library\\repos\\" +fileName ;
FileInputStream fi = new FileInputStream(path);
ObjectInputStream oi = new ObjectInputStream(fi);
// Read objects
List<T> items = (List<T>)oi.readObject();
oi.close();
fi.close();
return items;
} catch (Exception e) {}
return null;
}
The List of objects is written to the file,
but when I try to read it with function above the objects that I get from file only objects that was written to file first time.
Any idea why I get from file only objects that was written to file first time?
I only asume that
but when I try to read it with function above the objects that I get
from file only objects that was written to file first time.
Single write will put given list into a file, second write will put another list into that file - because you are appending to file
Now, you read method always reads from the begining so every invocation of readFromFile will result in reading the same (very first) object (list in your case) from given file. You would have to do do more f.readObject() on the same stream.
If you are not going to read all objects at once, I would suggest to use 1 file per list, so you will not have use file seeking to "shift" position of file pointer (nor doing empty f.readObject() invocations)

How to Insert ArrayList data to the DataBase

Im try to insert data into Database using ArrayList.there is a Erro msg.
That is my Custmer.class method. this is what i got from when i going to pass ArrayList into another class.
incompatible types: ArrayList<String> cannot be converted to ArrayList<Inquiries>
I want to know how to do this using correct Using OOP concept
public void passingMsg(ArrayList<Inquiries> arrlist){
try {
System.out.println("Method "+arrlist);
String sq = "INSERT INTO Inquiries (name,mail,tp,msg)VALUES(?,?,?)";
PreparedStatement pr = con.prepareStatement(sq);
for(int i=0;i<arrlist.size();i++){
pr.setString(1,arrlist.get(i).getName());
pr.setString(2,arrlist.get(i).getMail());
pr.setString(3,arrlist.get(i).getTp());
pr.setString(4,arrlist.get(i).getMsg());
}
pr.executeQuery();//executeBatch();
} catch (SQLException ex) {
}
}
and this is how i get values from user
String name = txtName.getText();
String mail = txtEmail.getText();
String tp = txtTp.getText();
String msg = txtMsg.getText();
ArrayList<String> arrInq = new ArrayList<String>();
arrInq.add(name);
arrInq.add(mail);
arrInq.add(tp);
arrInq.add(msg);
Custmer c =new Custmer();
if( c.passingMsg(arrInq)){
try {
JOptionPane.showMessageDialog(this, "Successs!!");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "Unsuccesss!!");
e.printStackTrace();
}
}
and this is my Inquiries.class :
public class Inquiries {
private String name;
private String mail;
private String tp;
private String msg;
public Inquiries(String name,String mail,String tp,String msg){
this.name = name;
this.mail = mail;
this.tp = tp;
this.msg = msg;
}
//
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getTp() {
return tp;
}
public void setTp(String tp) {
this.tp = tp;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
Can Some one please explain whats wrong with this. please ?
Reason For Error
This was simply telling you that your types were incompatible for the operation you were trying to perform. In your passingMsg() method, you have its header as: public void passingMsg(ArrayList<Inquiries> arrlist). However, inside your "how i get values from user" area, which I will now refer to as "2nd Snippet", you have your method call declared as: if( c.passingMsg(arrInq)). This means that you are implying that your parameter being passed, arrInq in this case, is of the type ArrayList<Inquiries>, but it's not. It's being initialized in your 2nd Snippet as: ArrayList<String> arrInq = new ArrayList<String>();
Simple Fix
I take no responsibility for this code; use at your own risk. To fix this, you would want to change that entire 2nd Snippet to something similar to the following:
String name = txtName.getText();
String mail = txtEmail.getText();
String tp = txtTp.getText();
String msg = txtMsg.getText();
ArrayList<Inquiries> arrInq = new ArrayList<Inquiries>();
arrInq.add(new Inquiries(name, mail, tp, msg));
Custmer c = new Custmer();
try {
c.passingMsg(arrInq);
JOptionPane.showMessageDialog(this, "Successs!!");
} catch (Exception e) {
JOptionPane.showMessageDialog(this, "Unsuccesss!!");
e.printStackTrace();
}
You would also want to change the method header to either return a boolean, or fix it up a little bit to actually throw the exception. Such as:
public void passingMsg(ArrayList<Inquiries> arrlist) {
System.out.println("Method " + arrlist);
String sq = "INSERT INTO Inquiries(name,mail,tp,msg) VALUES(?,?,?)";
PreparedStatement pr = con.prepareStatement(sq);
for (Inquiries inquiries : arrlist) {
pr.setString(1, inquiries.getName());
pr.setString(2, inquiries.getMail());
pr.setString(3, inquiries.getTp());
pr.setString(4, inquiries.getMsg());
}
pr.executeQuery();//executeBatch();
}
Let's talk in O-O-P way.
Here Inquiries is your model, model is nothing but simple class that has instance members and public methods to get and set value of model's instance variable.
Generally we put all database related operations code in their respective models.
e.g. I have model "Model" which typically maps to database table say it as "TableModel" ,I would do something like this:
public class Model{
private int id;
private String attr;
//other properties of the model
public int getId(){
return id;
}
public void setId(int id){
this.id=id;
}
//other getters and setters
//here we write methods to performs database operations
public void save(){
//use "this" to get properties of object
//logic to save to this object in database table TableModel as record
}
public void delete(int id){
//logic to delete this object i.e. from database table TableModel
}
public Model get(int id){
//retrieve record from table TableModel with this id
}
//other methods to get data from database.
}
Now question is how I can use this in some another class. Let's say I have list of Model objects and I wish to insert them in to database.I will do it something like this:
public class AnotherClass{
public void someMethod(){
//create list of models objects e.g. get them from user interface
ArrayList<Model> models=new ArrayList<>();
for(int i=0;i<3;i++){
Model model=new Model();
model.setId(i);
model.setAttr("attr"+i);
models.add(model);
}
SomeOtherClass obj=new SomeOtherClass();
obj.insert(models);
}
}
public class SomeOtherClass{
//other code above.....
//my method that inserts each Model object in database
//Note: this is sample method , you should do it in optimized way
// e.g. batch insert
public void insert(ArrayList<Model> models){
for(Model myModel:models){
myModel.save();
}
}
//other code below.....
}
You are using the wrong type parameter for the ArrayList. Instead of ArrayList<String> you need ArrayList<Inquiries>. To fix the problem, you should remove this code ...
ArrayList<String> arrInq = new ArrayList<String>();
arrInq.add(name);
arrInq.add(mail);
arrInq.add(tp);
arrInq.add(msg);
... and replace it with this code:
ArrayList<Inquiries> arrInq = new ArrayList<Inquiries>();
arrInq.add(new Inquiries(name, mail, tp, msg));

Java Swing Object[][] getData() confusion

Hi I'm having some trouble getting started with a problem in a Java course learning Swing and starting on JTables and getting data into them. It's going to be hard to explain so I'm just going to post the code I was given, along with the question.
The question is:
The getData() method needs to return an Object[][] containing the data represented by the class.
The first class is MusicAlbum
class MusicAlbum {
private String id;
private String name;
private String genre;
private boolean isCompilation;
private int track_count;
public MusicAlbum(String id, String name, String genre, boolean isCompilation, int track_count) {
this.id = id;
this.name = name;
this.genre = genre;
this.isCompilation = isCompilation;
this.track_count = track_count;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getGenre() {
return genre;
}
public boolean isCompilation() {
return isCompilation;
}
public int getTrackCount() {
return track_count;
}
public boolean equals(Object obj) {
if (obj instanceof MusicAlbum)
return this.id.equalsIgnoreCase(((MusicAlbum)obj).id);
return super.equals(obj);
}
}
The class I have to implement the methods in is MusicDataObject (at the bottom)
import java.util.Random;
import java.util.Scanner;
public class MusicDataObject {
private List<MusicAlbum> albums = new ArrayList<>();
private Random random = new Random(); // for generating IDs
public void addAlbum(MusicAlbum album) throws IllegalArgumentException {
if (searchAlbum(album.getId()) != null)
throw new IllegalArgumentException("Album ID is not new!");
albums.add(album);
}
public MusicAlbum searchAlbum(String id) {
for (MusicAlbum album : albums) {
if (album.getId().equalsIgnoreCase(id)) {
return album;
}
}
return null;
}
public MusicAlbum removeAlbum(String id) {
MusicAlbum album = searchAlbum(id);
albums.remove(album);
return album;
}
public void updateAlbum(MusicAlbum album)
throws IllegalArgumentException {
if (removeAlbum(album.getId()) == null)
throw new IllegalArgumentException("Album ID does not exist!");
addAlbum(album);
}
public String generateID() {
String formatter = "A%0" + (int)Math.ceil(Math.log10(albums.size() * 2) + 1) + "d";
String ID;
do {
ID = String.format(formatter, random.nextInt(albums.size() * 2 + 1));
} while (searchAlbum(ID) != null);
return ID;
}
public void saveData(String fileName) throws IOException {
// make sure that the file exists or try to create it
File fout = new File(fileName);
if (!fout.exists() && !fout.createNewFile())
return;
PrintWriter out = new PrintWriter(fout);
for (MusicAlbum album: albums) {
out.println(serializeAlbum(album));
}
out.close();
}
public String serializeAlbum(MusicAlbum album) {
return String.format(
"%s;%s;%s;%b;%d",
album.getId(),
album.getName(),
album.getGenre(),
album.isCompilation(),
album.getTrackCount());
}
public void loadFile(String fileName) throws FileNotFoundException {
albums = new ArrayList<>();
Scanner in = new Scanner(new File(fileName));
while (in.hasNext()) {
// --- split the next line with the character ";"
String line = in.nextLine();
String[] tokens = line.split(";");
// --- construct a new MusicAlbum using the resulting tokens. NOTE: This isn't very robust.
// If a line doesn't contain enough data or the data is invalid, this will crash
albums.add(new MusicAlbum(
tokens[0],
tokens[1],
tokens[2],
Boolean.parseBoolean(tokens[3]),
Integer.parseInt(tokens[4])
));
}
}
// ----- these methods need to be implemented
public Object[][] getData() {
// TODO
}
public String[] getColumnNames() {
// TODO
}
}
The sample data being used is in a txt file, formatted as so:
A01;Defiance;Soundtrack;true;24
A02;Insomniac;Punk Rock;false;14
A03;A Great Day For The Race;Gypsy Jazz;false;10
A04;Viva La Internet;Ska;false;31
A05;New Surrender;Rock;false;17
So basically it's this getData() method they want me to implement that is giving me grief. I don't fully understand what they want me to do, nor do I fully understand what the Object[][] does.
I hope I have been clear enough, and I will appreciate all help given. Also please try to explain things as best you can and dumb them down as much as possible, I'm new to a lot of this :)
Thanks for your time.
Object[][] is a 2-dimensional array. Each of its element is an Object[], a one-dimensional array.
Your task is to create a 2 dimensional array, having one element (Object[]) for each of your MusicAlbum. An Object[] should hold the properties of a MusicAlbum like id, name, genre, isCompilation and track_count.
You can create an object array like this:
Object[] arr = new Object[] { "some", "values", 23, true };
You can create a 2 dimensional array like this:
Object[][] arr2d = new Object[size][];
And you can iterate over all your MusicAlbums, create an Object[] for each of them containing the properties of that music album, and set it in the arr2d.
You can set/get elements of a 2-dimensional array just like any other arrays:
// Set first element:
arr2d[0] = arr;
// Get first element:
Object[] firstElement = arr2d[0];
The getColumnNames() method should just return a String[] (a String array) containing the column names, the names of the properties.
And it might be obvious but note that the order you return the column names and the order of the property values (in the elements of the Object[]) should be the same.

Java compareTo (Object obj)

I've given an assigment and its the last day of itself. I did most of it but on the last question I have a problem with creating a compareTo() function.
Here is what it does want from us ;
compareTo
public int compareTo(java.lang.Object other)
Specified by:
compareTo in interface java.lang.Comparable
Here is what I did
public int compareTo(Object obj)
{
Document tmp = (Document)obj;
if(this.text < tmp.text)
{
/* instance lt received */
return -1;
}
else if(this.text > tmp.text)
{
/* instance gt received */
return 1;
}
/* instance == received */
return 0;
}
Here is my whole Document.java file
class Document
{
private String text;
/**
* Default constructor; Initialize amount to zero.
*/
public Document()
{
text = "";
}
/**
* Default constructor; Initialize text to input value
* #param text New text value
*/
public Document(String text)
{
this.text = text;
}
/**
* Returns as a string the contents of the Document.
*/
public String toString()
{
return text;
}
and Here is the test file of itself.
import java.util.Arrays;
public class Homework2 extends Document {
/** ======================
* ContainsKeyword
* Returns true if the Document
* object passed in contains keyword as a substring
* of its text property.
* ======================
*/
public static boolean ContainsKeyword(Document docObject, String keyword)
{
if (docObject.toString().indexOf(keyword,0) >= 0)
return true;
return false;
}
public static void main(String[] args){
Email email1= new Email("Programming in Java",
"Larry", "Curly", "Programming");
Email email2 = new Email("Running marathons",
"Speedy", "Gonzales", "races");
System.out.println(email1);
File file1 = new File("Some Java file", "file.txt");
File file2 = new File(
"Boluspor wins against Besiktas. Muahahahaha",
"bolutas.txt");
Document doc = new Document (
"ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?,ok?");
System.out.println("\n"+file1);
System.out.println("\nWhich contains Java?");
if (ContainsKeyword(email1,"Java")) System.out.println(" Email1");
if (ContainsKeyword(email2,"Java")) System.out.println(" Email2");
if (ContainsKeyword(file1,"Java")) System.out.println(" File1");
if (ContainsKeyword(file2,"Java")) System.out.println(" File2");
Document [] da = new Document [5];
da[0] = email1;
da[1] = email2;
da[2] = file1;
da[3] = file2;
da[4] = doc;
Arrays.sort(da);
System.out.println("\nAfter sort:");
for(Document d : da){
System.out.println(d);
}
}
}
What I wanted to ask is, I cannot compare the objects from my Email.java and File.java , I can do anything else but the last part which starts with Document [] da... That part gives an error. What am I doing wrong here?
The error is ;
Exception in thread "main" java.lang.ClassCastException: Email cannot be cast to java.lang.Comparable
at java.util.Arrays.mergeSort(Arrays.java:1144)
at java.util.Arrays.sort(Arrays.java:1079)
at Homework2.main(Homework2.java:53)
UPLOAD ** Here is my Email and File Class..
/**
* First define class for Email, derive from Document
*/
class Email extends Document
{
private String sender;
private String recipient;
private String title;
private String body;
/**
* Constructors
*/
public Email()
{
super();
sender = "";
recipient = "";
title = "";
body = "";
}
public Email(String body, String sender, String recipient, String title)
{
this.sender = sender;
this.recipient = recipient;
this.title = title;
this.body = body;
}
// ======================
// Various accessor and mutator methods
// ======================
public String getSender()
{
return sender;
}
public void setSender(String sender)
{
this.sender = sender;
}
public String getRecipient()
{
return recipient;
}
public void setRecipient(String recipient)
{
this.recipient = recipient;
}
public String getTitle()
{
return title;
}
public void setTitle(String title)
{
this.title = title;
}
public String getBody(){
return body;
}
public void getBody(String body){
this.body = body;
}
/**
* Returns as a string the contents of the text fields concatenated
* together. Uses super.toString to get the parent's text.
*/
public String toString()
{
return "Sender:" + sender + ",Recipient:" + recipient + ",Title:" + title + ",Body:" + body + " " +
super.toString();
}
} // Email
and File ;
/**
* Next define class for File, derive from Document
* For brevity, short one-line methods are defined here in the
* header.
*/
class File extends Document
{
private String pathname;
/**
* Constructors.
*/
public File()
{
super();
pathname = "";
}
public File(String body, String pathname)
{
super(body);
this.pathname = pathname;
}
// ======================
// Various accessor and mutator methods
// ======================
public void setPathname(String s)
{
pathname = s;
}
public String getPathname()
{
return pathname;
}
/**
* Returns as a string the contents of the text fields concatenated
* together. Uses super.toString to get the parent's text.
*/
public String toString()
{
return "Pathname " + pathname + " Body " + super.toString();
}
} // File
Where did you put the compareTo method? If you're trying to sort an array of Documents, you need to have Document implement Comparable (or pass in a Comparator):
public class Document implements Comparable<Document> {
Or, if for some bizarre reason you're not allowed to use generics:
public class Document implements Comparable {
Then put compareTo within Document.
The exact reason it is failing is because you are trying to call Arrays.sort on a class that does not implement comparable
Implementing Comparable allows
calling Collections.sort and Collections.binarySearch
calling Arrays.sort and Arrays.binarySearch
using objects as keys in a TreeMap
using objects as elements in a TreeSet
Email did not implement the Comparable interface
use
public class Email implements Comparable<Email>
read this to do yourself a favor http://www.javapractices.com/topic/TopicAction.do?Id=10
The other note is you said you want to compare
Email.java and File.java
You will need a custom function for that based on the logic.
compareTo is used to compare two instances of the same type. It also means that the function lives in the Email class
Email myEmail = new Email();
Email hisEmail = new Email();
myEmail.compareTo(hisEmail);
What you are doing wrong is in the error message.
You can only sort objects for classes which implement Comparable. Your class does not.
As you are sorting a number of different types you may want to provide a custom Comparator instead, or make Document implement Comparable.
try this:
Here is my whole Document.java file
class Document implements Comparable { //this line is your solution.
private String text;
/**
* Default constructor; Initialize amount to zero.
*/
public Document()
{
text = "";
}
/**
* Default constructor; Initialize text to input value
* #param text New text value
*/
....}

Categories

Resources