Saturday, May 25, 2013

Handling files in Java

The java.io.File class provides ways to access file and directory information. It also allows file-level operations like rename, delete and move.

Checkout the source here.

/**
 * A program to list all files and directories in a given directory.
 *
 * @author megha birmiwal
 */
public class DirectoryLister {

        public void listDirectories(String filepath) {

                File topDir = new File(filepath);
                if (!topDir.exists()) {
                        System.out.println("Directory does not exist: " + filepath);
                        return;
                }

                if (!topDir.isDirectory()) {
                        System.out.println("Not a directory: " + filepath);
                        return;
                }

                File[] files = topDir.listFiles();

                for (File file : files) {
                        if (file.isHidden()) {
                                // do not show hidden files
                                continue;
                        }
                        if (file.isDirectory()) {
                                System.out.println(file.getName() + " - D");
                        } else {
                                System.out.println(file.getName() + " - " + file.length());
                        }
// You can use the File APIs to play around with files, eg. rename or delete etc.
//                      String name = file.getName();
//                      name = name.replace(".png", ".jpg");
//                      name = name + ".txt";
//                  file.renameTo(new File(name));
//          file.delete();
                }
        }

        public static void main(String[] args) {
                DirectoryLister lister = new DirectoryLister();
                lister.listDirectories("/");
        }
}

Threads II

Here is another example of threads.
Get the code here.

/**
 * An enum with a single value is probably the ultimate singleton.
 * However, it can get real ugly real soon as far as testability is concerned.
 *
 * @author megha birmiwal
 */
public enum StatisticsCollector {
// can override methods in enums like this
//      INFLATED_STATS
//              public int getTimesCalled() {
//                      return count * 10;
//              }
//      },
        STATS;
        private static int count = 0;
        private static double timeSum = 0;
        synchronized public void reportStat(double time) {
                count++;
                timeSum += time;
        }
        public int getTimesCalled() {
                return count;
        }
        public double getAverage() {
                return timeSum / getTimesCalled();
        }
}

/**
 * Reports a given time to the {@link StatisticsCollector}.
 *
 * @author megha birmiwal
 */
public class TimeReporter implements Runnable {
        private final int timeToReport;
        private final int count;
        public TimeReporter(int timeToReport, int count) {
                this.timeToReport = timeToReport;
                this.count = count;
        }
        @Override
        public void run() {
                for (int i = 0; i < count; i++) {
                        StatisticsCollector.STATS.reportStat(timeToReport);
                }
        }
}
public class Main {
        public static void main(String args[]) throws InterruptedException {
                Thread threadX1 = new Thread(new TimeReporter(100, 10000));
                threadX1.start();
                Thread threadX2 = new Thread(new TimeReporter(100, 10000));
                threadX2.start();
                Thread threadY = new Thread(new TimeReporter(200, 10000));
                threadY.start();
                threadX1.join();
                threadX2.join();
                threadY.join();
                int timesCalled = StatisticsCollector.STATS.getTimesCalled();
                double average = StatisticsCollector.STATS.getAverage();
                System.out.println("Total Calls: " + (timesCalled));
                System.out.println("Average Time: " + (average));
        }
}

Threads

Here's an example of threads. Threads can be created by extending the Thread class and overriding the run() method, or implementing a runnable and passing it to the Thread's constructor.
In this example, we implement the Runnable class.
Explicit synchronization/care should be taken to perform thread-unsafe operations. In this case, the access to the ThreadUnsafeCounter is explicity synchronized in CounterIncrementor. Try commenting out the synchronize block and see the results.

Checkout the code here.

public class ThreadUnsafeCounter {

        private int count = 0;

        public int getCount() {
                return count;
        }

        // unsafe when multiple threads try to increment at the same time.
        // ALL callers need to use ensure that they do not call increment at the same
        // time. This may be done using explicit synchronize blocks.
    public void increment() {
                count++;
        }
}
public class ThreadSafeCounter extends ThreadUnsafeCounter {

        // synchronized makes it safe to call increment() in different threads without
        // explicit locking/synchronization. the jvm with assure that only one call of
        // increment() on an instance of ThreadSafeCounter is running at any given time.
        @Override
        synchronized public void increment() {
                super.increment();
        }
}
/**
 * Increments the given counters a given number of times.
 *
 * @author megha
 */
public class CounterIncrementor implements Runnable {

        private final int times;
        private final ThreadSafeCounter safeCounter;
        private final ThreadUnsafeCounter unsafeCounter;

        public CounterIncrementor(ThreadUnsafeCounter unsafeCounter,
                        ThreadSafeCounter safeCounter, int times) {
                this.unsafeCounter = unsafeCounter;
                this.safeCounter = safeCounter;
                this.times = times;
        }

        @Override
        public void run() {
                for(int i = 0; i < times; i++) {
                        safeCounter.increment();
                        // need to run in a synchronized block to ensure that two
                        // parallel calls to increment are never made
                        synchronized (unsafeCounter) {
                                unsafeCounter.increment();
                        }
                }
        }
}
import java.util.ArrayList;
import java.util.List;

public class Main {

        public static void main(String args[]) throws InterruptedException{

                ThreadUnsafeCounter unsafeCounter = new ThreadUnsafeCounter();
                ThreadSafeCounter safeCounter = new ThreadSafeCounter();
                CounterIncrementor incrementor =
                                new CounterIncrementor(unsafeCounter, safeCounter, 10000);

                List<Thread> threads = new ArrayList<Thread>();
                // start lots of parallel threads that increment the counter(s)
                for (int i = 0; i < 100; i++) {
                        Thread thread = new Thread(incrementor);
                        thread.start();
                        threads.add(thread);
                }

                // wait for all threads to finish
                for (Thread thread: threads) {
                        thread.join();
                }

                // count on unsafe counter matches that of safe counter because
                // CounterIncrement increments unsafeCounter in a safe manner
                System.out.println(unsafeCounter.getCount());
                System.out.println(safeCounter.getCount());
        }
}