如何将文件内容保存在Java的列表中?

huangapple go评论75阅读模式
英文:

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

问题

我有两个方法:saveSubscribedFeeds()loadSubscribedFeeds()。在保存方法中,我将一些数据保存到参数中的文件 feedsFile 中,如下所示:

@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();
    }
}

在加载方法中,我试图加载完全相同的文件 feedsFile,并将其作为一个列表返回,我使用了一个 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;
}

然而,JUnit 测试告诉我我的列表与读取的对象不匹配:

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!");
}

我做错了什么?以下是 Feed 类的内容:

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 = "";
    }

    // 更多类内容...
}
英文:

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&lt;Feed&gt; 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&lt;Feed&gt; loadSubscribedFeeds(File feedsFile) throws FileNotFoundException {	
	
	Scanner s = new Scanner(feedsFile.getAbsoluteFile());
	List&lt;Feed&gt; listFeed = new ArrayList&lt;&gt;();
	
	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(&quot;The data read from save-file &#39;&quot; + FEEDS_FILE.getName() + &quot;&#39; doesn&#39;t match the test input data!&quot;);
		fail(&quot;feed sample data (&quot; + FEEDS_FILE.getAbsolutePath() + &quot;) doesn&#39;t match read object!&quot;);
	}

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&lt;Feed&gt; {

private static final long serialVersionUID = 1L;

private String url;
private String title;
private String description;
private String publishedDateString;
private List&lt;Entry&gt; entries;

public Feed() {
	
}

public Feed(String url) {
	super();
	this.url = url;
	this.entries = new ArrayList&lt;Entry&gt;();
	this.title = &quot;&quot;;
	this.description = &quot;&quot;;
	this.publishedDateString = &quot;&quot;;
}

/**
 * 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 : &quot;&quot;;
}

public String getTitle() {
	return title;
}

public void setDescription(String description) {
	this.description = description != null ? description : &quot;&quot;;
}

public String getDescription() {
	return description;
}

public void setPublishedDateString(String publishedDateString) {
	this.publishedDateString = publishedDateString != null ? publishedDateString : &quot;&quot;;
}

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() + &quot; [&quot; +
			getEntriesCount() + &quot; entries]: &quot; + 
			getDescription() +
			(getPublishedDateString() != null &amp;&amp; getPublishedDateString().length() &gt; 0
				? &quot; (updated &quot; + getPublishedDateString() + &quot;)&quot;
				: &quot;&quot;);
}

public void addEntry(Entry entry) {
	if (entry != null) entries.add(entry);
}

public List&lt;Entry&gt; getEntries() {
	return entries;
}

public int getEntriesCount() {
	return entries.size();
}

@Override
public boolean equals(Object obj) {
	return (obj instanceof Feed)
		&amp;&amp; ((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());
}

}

答案1

得分: 1

首先:尝试使用调试器查看在遇到此类问题时发生了什么。您可以逐行查看代码并查看变量及其内容。
其次:您所遇到的问题,正如Tushar所提到的,是因为您每次都在新行中编写标题、描述等。然后,当您尝试读取对象时,您只读取一行,然后尝试创建一个新的Feed对象,在构造函数中用空字符串填充标题、描述等字段,url则使用给定的参数。那么在保存描述的文件中的下一行会发生什么呢?它将生成一个将描述设置为url的Feed对象。当然,JUnit会指出,这不是同一个对象。
您现在可以做以下操作:

  • 通过一个恒定的字符分隔字段,并仅在需要新的Feed对象时进行换行。然后从单独的行中解析字段以填充您的对象。例如:url;title;description;publishedDate;\nurl2;title2;description2;publishedDate2;\n其中\n明显标记了换行符。
  • 也可以创建一个XML,并使用适当的解析库进行解析。Java已经内置了一些可用的库。这里是一个链接,链接到其中一个教程:https://www.tutorialspoint.com/java_xml/java_dom_parse_document.htm
英文:

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

huangapple
  • 本文由 发表于 2020年9月7日 16:21:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63773855.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定