From dfae08051eabb3fec6999bed877b7df92d13bb44 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Fri, 2 May 2014 23:00:04 +0200 Subject: DataWriter should not open files in constructor Right now Store instances are created in the constructor of DataWriter. This causes issues, namely that Store instances are unable to use DataWriter in its constructor. The real-world implication is that convertUncompressed in CompressableDataWriter is unusable for the CompressedStore. --- src/io/CompressableDataWriter.java | 8 ++++-- src/io/DataWriter.java | 59 ++++++++++++++++++++++++++------------ src/main/TweetShell.java | 1 + 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/io/CompressableDataWriter.java b/src/io/CompressableDataWriter.java index 7523b78..26a6c26 100644 --- a/src/io/CompressableDataWriter.java +++ b/src/io/CompressableDataWriter.java @@ -35,7 +35,7 @@ public class CompressableDataWriter extends DataWriter { } @Override - protected Store getStore(String filename) throws IOException { + protected Store getStore(String filename) { return new CompressedStore(filename); } @@ -43,8 +43,12 @@ public class CompressableDataWriter extends DataWriter { private boolean compressable = false; - CompressedStore(String filename) throws IOException { + CompressedStore(String filename) { super(filename); + } + + @Override + public void open() throws IOException { BufferedInputStream bis = null; try { bis = new BufferedInputStream(new FileInputStream(getFileName())); diff --git a/src/io/DataWriter.java b/src/io/DataWriter.java index 252c50c..d06e283 100644 --- a/src/io/DataWriter.java +++ b/src/io/DataWriter.java @@ -48,24 +48,30 @@ public class DataWriter implements ResultListener { public final static String CFG_TWEETS_FILENAME = "tweets-filename"; /** - * Opens a stream to every single file that data will be streamed to. + * Creates an instance, specifying the profile and file names to which + * tweets and users are written. * * @param profilesName The file to write the profiles to. * @param tweetsName The file to write the tweets to. - * @throws java.io.IOException if the files cannot be read or written. */ - public DataWriter(final String profilesName, final String tweetsName) - throws IOException { + public DataWriter(final String profilesName, final String tweetsName) { m_profile = getStore(profilesName); - try { - m_profileIdSet = readIds(m_profile); - } catch (IOException ex) { - m_profile.close(); - throw ex; - } + m_profileIdSet = new HashSet<>(); m_tweet = getStore(tweetsName); + m_tweetIdSet = new HashSet<>(); + } + + /** + * Opens a stream to every single file that data will be streamed to. + * + * @throws java.io.IOException if the files cannot be read or written. + */ + public void open() throws IOException { try { - m_tweetIdSet = readIds(m_tweet); + m_profile.open(); + m_tweet.open(); + readIds(m_profileIdSet, m_profile); + readIds(m_tweetIdSet, m_tweet); } catch (IOException ex) { m_profile.close(); m_tweet.close(); @@ -78,9 +84,8 @@ public class DataWriter implements ResultListener { * * @param filename File to read/write. * @return A Store instance providing read and write access. - * @throws IOException if the target file cannot be read or written. */ - protected Store getStore(String filename) throws IOException { + protected Store getStore(String filename) { return new SimpleFileStore(filename); } @@ -106,8 +111,7 @@ public class DataWriter implements ResultListener { * @param is An input stream that provides JSON objects. * @return The set of ids, may be empty if the fill does not exist. */ - private Set readIds(Store store) throws IOException { - Set idSet = new HashSet<>(); + private void readIds(Set idSet, Store store) throws IOException { InputStream is = null; try { is = store.getInputStream(); @@ -128,7 +132,6 @@ public class DataWriter implements ResultListener { } finally { IOUtils.closeQuietly(is); } - return idSet; } /** @@ -177,12 +180,23 @@ public class DataWriter implements ResultListener { return filename; } + /** + * Opens the writable stream (if not open yet), must be called before + * writing a stream. + * + * @throws IOException + */ + abstract public void open() throws IOException; + /** * Properly closes a file, flushing any buffers. */ public void close() { try { - os.close(); + if (os != null) { + os.close(); + os = null; + } } catch (IOException ex) { Logger.getLogger(getClass().getName()).log(Level.WARNING, "Could not close " + getFileName(), ex); @@ -193,6 +207,7 @@ public class DataWriter implements ResultListener { * Returns a previously opened writable file stream. * * @return A stream to which JSON objects can be written (one per line). + * If no writable stream is open, {@code null} is returned. */ public OutputStream getOutputStream() { return os; @@ -209,9 +224,15 @@ public class DataWriter implements ResultListener { class SimpleFileStore extends Store { - SimpleFileStore(String filename) throws FileNotFoundException { + SimpleFileStore(String filename) { super(filename); - os = new FileOutputStream(getFileName(), true); + } + + @Override + public void open() throws IOException { + if (os == null) { + os = new FileOutputStream(getFileName(), true); + } } @Override diff --git a/src/main/TweetShell.java b/src/main/TweetShell.java index 1d03efb..8e50f3b 100644 --- a/src/main/TweetShell.java +++ b/src/main/TweetShell.java @@ -403,6 +403,7 @@ public class TweetShell implements TwitterApi.PinSupplier { } else { dw = new DataWriter(profilesFilename, tweetsFilename); } + dw.open(); resultListeners.register(dw); // save the changes to the config. config.save(); -- cgit v1.2.1