diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java index 25e835c4..85ecac7c 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Application.java @@ -9,11 +9,12 @@ import ch.heigvd.res.labio.quotes.QuoteClient; import org.apache.commons.io.FileUtils; -import java.io.File; -import java.io.IOException; -import java.io.StringWriter; -import java.io.Writer; +import java.io.*; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -98,6 +99,7 @@ public void fetchAndStoreQuotes(int numberOfQuotes) throws IOException { * one method provided by this class, which is responsible for storing the content of the * quote in a text file (and for generating the directories based on the tags). */ + storeQuote(quote, "quote-" + i + ".utf8"); LOG.info("Received a new joke with " + quote.getTags().size() + " tags."); for (String tag : quote.getTags()) { LOG.info("> " + tag); @@ -133,7 +135,23 @@ void clearOutputDirectory() throws IOException { * @throws IOException */ void storeQuote(Quote quote, String filename) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + + /* Create the path for the output file */ + StringBuilder path = new StringBuilder(WORKSPACE_DIRECTORY).append("/"); + for (String tag : quote.getTags()) { + path.append(tag).append("/"); + } + + /* Create sub-directories */ + File subdirectories = new File(path.toString()); + subdirectories.mkdirs(); + + /* Create and write in output file */ + path.append(filename); + Writer writer = new OutputStreamWriter(new FileOutputStream(path.toString()), StandardCharsets.UTF_8); + writer.write(quote.getQuote()); + writer.flush(); + writer.close(); } /** @@ -150,6 +168,11 @@ public void visit(File file) { * of the the IFileVisitor interface inline. You just have to add the body of the visit method, which should * be pretty easy (we want to write the filename, including the path, to the writer passed in argument). */ + try { + writer.write(file.toString() + "\n"); + }catch (Exception e){ + System.err.println("An error occurred with I/O file"); + } } }); } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java index c8a3a5ad..841de396 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/Utils.java @@ -3,24 +3,42 @@ import java.util.logging.Logger; /** - * * @author Olivier Liechti */ public class Utils { - private static final Logger LOG = Logger.getLogger(Utils.class.getName()); - - /** - * This method looks for the next new line separators (\r, \n, \r\n) to extract - * the next line in the string passed in arguments. - * - * @param lines a string that may contain 0, 1 or more lines - * @return an array with 2 elements; the first element is the next line with - * the line separator, the second element is the remaining text. If the argument does not - * contain any line separator, then the first element is an empty string. - */ - public static String[] getNextLine(String lines) { - throw new UnsupportedOperationException("The student has not implemented this method yet."); - } + private static final Logger LOG = Logger.getLogger(Utils.class.getName()); + + /** + * This method looks for the next new line separators (\r, \n, \r\n) to extract + * the next line in the string passed in arguments. + * + * @param lines a string that may contain 0, 1 or more lines + * @return an array with 2 elements; the first element is the next line with + * the line separator, the second element is the remaining text. If the argument does not + * contain any line separator, then the first element is an empty string. + */ + public static String[] getNextLine(String lines) { + + String[] result = new String[]{"", lines}; + + for(int i = 0; i < lines.length(); ++i) { + char c = lines.charAt(i); /* current char */ + switch (c) { + case '\r': + if (i < lines.length() - 1 && lines.charAt(i + 1) == '\n') { + result[0] = lines.substring(0, i + 2); + result[1] = lines.substring(i + 2); + return result; + } + case '\n': /* case '\n' or '\r\n' */ + result[0] = lines.substring(0, i + 1); + result[1] = lines.substring(i + 1); + return result; + } + } + + return result; + } } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java index b97c4a72..2cd02008 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/explorers/DFSFileExplorer.java @@ -4,20 +4,45 @@ import ch.heigvd.res.labio.interfaces.IFileVisitor; import java.io.File; +import java.util.Arrays; /** * This implementation of the IFileExplorer interface performs a depth-first * exploration of the file system and invokes the visitor for every encountered * node (file and directory). When the explorer reaches a directory, it visits all * files in the directory and then moves into the subdirectories. - * + * * @author Olivier Liechti */ public class DFSFileExplorer implements IFileExplorer { - @Override - public void explore(File rootDirectory, IFileVisitor vistor) { - throw new UnsupportedOperationException("The student has not implemented this method yet."); - } + @Override + public void explore(File rootDirectory, IFileVisitor visitor) { + + /* Visit root directory */ + visitor.visit(rootDirectory); + + /* List files and sub-directories in root */ + File[] listOfFiles = rootDirectory.listFiles(); + + if (listOfFiles != null) { + /* + * Need to sort files by name because "There is no guarantee that the name strings in the + * resulting array will appear in any specific order; they are not, in particular, guaranteed + * to appear in alphabetical order." + */ + Arrays.sort(listOfFiles); + + /* Visit each file and explore recursively sub-directories */ + for (File file : listOfFiles) { + if (file.isDirectory()) { /* sub-directory */ + explore(file, visitor); + } else { /* file */ + visitor.visit(file); + } + } + } + + } } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java index 976c9462..4654e425 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/FileNumberingFilterWriter.java @@ -23,19 +23,44 @@ public FileNumberingFilterWriter(Writer out) { super(out); } + private int lineNumber = 1; + private boolean newLineMac = true; + @Override public void write(String str, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + for(int i = off; i < off + len; ++i){ + write(str.charAt(i)); + } + } @Override public void write(char[] cbuf, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + for(int i = off; i < off + len; ++i){ + write(cbuf[i]); + } } @Override public void write(int c) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + if (c == '\n') { + super.write(c); + out.write( lineNumber++ + "\t"); + newLineMac = false; + return; + + } else if (c == '\r') { + newLineMac = true; + + } else { + if (newLineMac) { //Allow to print the first tab and, when it's Mac, to print the next line with tab + out.write(lineNumber++ + "\t"); + } + newLineMac = false; + } + + super.write(c); + } } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java index 0f41a5dd..07b883f4 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/filters/UpperCaseFilterWriter.java @@ -16,17 +16,17 @@ public UpperCaseFilterWriter(Writer wrappedWriter) { @Override public void write(String str, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + super.write(str.toUpperCase(),off,len); } @Override public void write(char[] cbuf, int off, int len) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + super.write((new String(cbuf)).toUpperCase(), off, len); } @Override public void write(int c) throws IOException { - throw new UnsupportedOperationException("The student has not implemented this method yet."); + super.write(Character.toUpperCase(c)); } } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java index 4beca482..319f0ac8 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/CompleteFileTransformer.java @@ -1,5 +1,8 @@ package ch.heigvd.res.labio.impl.transformers; +import ch.heigvd.res.labio.impl.filters.FileNumberingFilterWriter; +import ch.heigvd.res.labio.impl.filters.UpperCaseFilterWriter; + import java.io.Writer; /** @@ -15,16 +18,13 @@ public class CompleteFileTransformer extends FileTransformer { @Override public Writer decorateWithFilters(Writer writer) { - if (true) { - throw new UnsupportedOperationException("The student has not implemented this method yet."); - } /* * If you uncomment the following line (and get rid of th 3 previous lines...), you will restore the decoration * of the writer (connected to the file. You can see that you first decorate the writer with an UpperCaseFilterWriter, which you then * decorate with a FileNumberingFilterWriter. The resulting writer is used by the abstract class to write the characters read from the * input files. So, the input is first prefixed with line numbers, then transformed to uppercase, then sent to the output file.f */ - //writer = new FileNumberingFilterWriter(new UpperCaseFilterWriter(writer)); + writer = new FileNumberingFilterWriter(new UpperCaseFilterWriter(writer)); return writer; } diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java index bde833e8..477f55ba 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/FileTransformer.java @@ -48,10 +48,20 @@ public void visit(File file) { writer = decorateWithFilters(writer); /* - * There is a missing piece here: you have an input reader and an ouput writer (notice how the + * There is a missing piece here: you have an input reader and an output writer (notice how the * writer has been decorated by the concrete subclass!). You need to write a loop to read the * characters and write them to the writer. */ + + /* Decorate I/O streams with buffer */ + reader = new BufferedReader(reader); + writer = new BufferedWriter(writer); + + int data = reader.read(); + while(data != -1){ + writer.write((char) data); + data = reader.read(); + } reader.close(); writer.flush(); diff --git a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java index 5971a302..e0651e6a 100644 --- a/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java +++ b/LabJavaIO/src/main/java/ch/heigvd/res/labio/impl/transformers/NoOpFileTransformer.java @@ -13,14 +13,13 @@ public class NoOpFileTransformer extends FileTransformer { @Override public Writer decorateWithFilters(Writer writer) { - throw new UnsupportedOperationException("The student has not implemented this method yet."); /* * The NoOpFileTransformer does not apply any transformation of the character stream * (no uppercase, no line number, etc.). So, we don't need to decorate the writer connected to * the output file at all. Just uncomment the following line and get rid of the UnsupportedOperationException and * you will be all set. */ - //return writer; + return writer; } }