ইনমেমোরী ফাইল সিস্টেম (In memory file system in java)

Posted on by

Categories:           

ফাইল সিস্টেম হলো এক ধরণের ডেটা স্ট্রাকচার ও পদ্ধতি যার মাধ্যে অপারেটিং সিস্টেম ডিস্কে যে বিভিন্নরকম ফাইল রাখা হয় তার ট্র্যাক রাখে।

অনেক সময়ই বিভিন্ন ইন্টারভিউতে ইন মেমোরী ফাইল সিস্টেম তৈরি করতে বলে। প্রশ্নটি এমন থাকে যে, একই ইন মেমোরী ফাইল সিস্টেম তৈরি রকতে হলে আপনি কীভাবে ডিজাইন করবেন এবং কী কী ডেটা স্ট্রাকচার ব্যবহার করবেন। সম্ভব হলে কিছু কোড লিখে দেখান। (Explain the data structures and algorithm that  you would use to design an in-memory file system. Illustrate with an example in code if possible. )

অনেকই ফাইল সিস্টেমের নাম শুনেই ভয় পেয়ে যায়, মনে করে এটি অনেক লো লেভেল (low level) অর্থাৎ অপারেটিং সিস্টেমের সঙ্গে সম্পর্কিত। কিন্তু সহজ-সরল ডিজাইন কিন্তু খুব কঠিন কিছু নয়। অবজেক্ট ওরিয়েন্টেড ডিজাইন ব্যবহার করেই এটি সমাধান করে ফেলা যায়।

একটি ফাইল সিস্টেমে থাকে কতগুলো ফাইল এবং ডিরেক্টরী। এরা বেশ কিছু বৈশিষ্ট্য শেয়ার করে। যেমন – এদের নাম থাকে, এদের পাথ থাকে, এগুলোর কখন তৈরি করা হয়েছে, কখন মোডিফাই করা হয়েছে, কবে শেষবার অ্যাকসেস করা হয়েছে ইত্যাদি। এই বৈশিষ্ট্যগুলো নিয়ে আমরা একটি অ্যাবস্ট্রাক্ট সুপার ক্লাস তৈরি করতে পারি।

public abstract class Node implements Comparable<Node> {
    private Directory root;
    private String name;
    private LocalDateTime created;
    private LocalDateTime lastUpdated;
    private LocalDateTime lastAccessed;

    public Node(String name) {
        this.name = name;
        this.created = LocalDateTime.now();
        this.lastUpdated = LocalDateTime.now();
        this.lastAccessed = LocalDateTime.now();
    }

    public boolean isDirectory() {
        return this instanceof Directory;
    }

    public String getPath() {
        return root != null ? root.getPath() + "/" + name : name;
    }

    public Node getParent() {
        return root;
    }

    public abstract long getLength();

    public String getName() {
        return name;
    }

    @Override
    public int compareTo(Node o) {
        return this.getName().compareTo(o.getName());
    }

    public void setRoot(Directory root) {
        this.root = root;
    }

    public LocalDateTime getCreated() {
        return created;
    }

    public LocalDateTime getLastUpdated() {
        return lastUpdated;
    }

    public LocalDateTime getLastAccessed() {
        return lastAccessed;
    }

    @Override
    public String toString() {
        return "root=" + root +
                ", nname='" + name + ''' +
                ", ncreated=" + created +
                ", nlastUpdated=" + lastUpdated +
                ", nlastAccessed=" + lastAccessed;
    }
}

এখানে কম্পেয়ারেবল ইন্টারফেইস ইমপ্লিমেন্ট করার কারণ হলো, যাতে আমরা সর্ট করতে পারি।

প্রত্যেকটি ফাইলের একটি করে রুট থাকে। রুট না থাকলে সে নিজেই রুট। এই নোডকে এক্সটেন্ড করে একটি ফাইল তৈরি করে ফেলা যাক –

public class File extends Node {
    private String content; // for simplicity

    public File(String name, String content) {
        super(name);
        this.content = content;
    }

    public File(String name) {
        super(name);
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public long getLength() {
        if (content != null) {
            return content.getBytes().length;
        }
        return 0;
    }
}

প্রত্যেকটি ফাইল কিছু কন্টেন্ট রাখে। সহজভাবে বুঝানোর জন্য এতে আপরা স্ট্রিং রেখেছি।
এবার ডিরেক্টরী স্ট্রাকচার তৈরি করা যাক –


public class Directory extends Node {
    private Set<Node> nodes;
    public Directory(String path) {
        super(path);
        nodes = new TreeSet<>();
    }

    public void add(Node node) {
        node.setRoot(this);
        nodes.add(node);
    }

    public Set<Node> getNodes() {
        return nodes;
    }

    @Override
    public long getLength() {
        long length = 0;
        for (Node node : nodes) {
            length += node.getLength();
        }
        return length;
    }

    public int numberOfFiles() {
        int count = 0;
        for (Node node : nodes) {
            if (node instanceof Directory) {
                count++;/// Directory counts as a file
                Directory directory = (Directory) node;
                count += directory.numberOfFiles();
            } else if (node instanceof File) {
                count++;
            }
        }

        return count;
    }
}

প্রত্যেকটি ডিরেক্টরীতে অারও অনেকগুলো করে ফাইল বা ডিরেক্টরী থাকতে পারে। এক্ষেত্রে ডিরেক্টরীতে একটি ট্রিসেটে (TreeSet) রাখা হয়েছে যা সেই ফাইল বা ডিরেক্টরীগুলো ধরে রাখে।

ডিরেক্টরী স্ট্রাকচারকরে সুন্দর করে প্রিন্ট করার জন্য কতগুলো মেথড যুক্ত করা যেতে পারে । যেমন-

public void printTree() {
    int indent = 0;
    StringBuilder sb = new StringBuilder();
    printDirectoryTree(this, indent, sb);
    System.out.println(sb.toString());
}

private void printDirectoryTree(Node node, int indent, StringBuilder sb) {
    sb.append(getIndentString(indent));
    sb.append("+--");
    sb.append(node.getName());
    sb.append("/");
    sb.append("n");
    if (node.isDirectory()) {
        Directory directory = (Directory) node;
        for (Node file : directory.getNodes()) {
            printDirectoryTree(file, indent + 1, sb);
        }
    }
}

private static String getIndentString(int indent) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < indent; i++) {
        sb.append("|  ");
    }
    return sb.toString();
}

এবার একটি মেইন মেথড থেকে এগুলোকে ব্যবহার করা যাক –

public class Main {
    public static void main(String\[\] args) {
        Directory root = new Directory("root");
        File file = new File("profile.jpg");
        root.add(file);

        Directory movie = new Directory("movie");
        root.add(movie);

        Directory englishMovie = new Directory("english");
        englishMovie.add(new File("IronFist.mp4"));
        englishMovie.add(new File("The Shawshank Redemption.mp4"));
        englishMovie.add(new File("ZotaPia.mp4"));
        File despicableMe = new File("DespicableMe.mp4");
        englishMovie.add(despicableMe);

        movie.add(englishMovie);

        Directory banglaMovie = new Directory("Bangla");
        banglaMovie.add(new File("The Clay Bird.mp4"));
        banglaMovie.add(new File("Jibon Thekey Neya.mp4"));
        movie.add(banglaMovie);

        root.printTree();

        System.out.println("name: " + movie.getName());
        System.out.println("Created: " + movie.getCreated());
    }
}

এটিকে রান করলে নিচের আউটপুটটি পাওয়া যাবে-


+--root/
|  +--movie/
|  |  +--Bangla/
|  |  |  +--Jibon Thekey Neya.mp4/
|  |  |  +--The Clay Bird.mp4/
|  |  +--english/
|  |  |  +--DespicableMe.mp4/
|  |  |  +--IronFist.mp4/
|  |  |  +--The Shawshank Redemption.mp4/
|  |  |  +--ZotaPia.mp4/
|  +--profile.jpg/

name: movie
Created: 2017-04-08T02:26:38.341

সম্পূর্ণ কোডটি পাওয়া যাবে এখানে: https://gist.github.com/rokon12/d3c83562c785de6d1a483a5585205b92

Share on:

Author: A N M Bazlur Rahman

Java Champion | Software Engineer | JUG Leader | Book Author | InfoQ & Foojay.IO Editor | Jakarta EE Ambassadors| Helping Java Developers to improve their coding & collaboration skills so that they can meet great people & collaborate

100daysofcode 100daysofjava access advance-java agile algorithm arraylist article bangla-book becoming-expert biginteger book calculator checked checked-exceptions cloning code-readability code-review coding coding-convention collection-framework compact-strings completablefuture concatenation concurrency concurrentmodificationexception concurrentskiplistmap counting countingcollections critical-section daemon-thread data-race data-structure datetime day002 deliberate-practice deserialization design-pattern developers duration execute-around executors export fibonacci file file-copy fork/join-common-pool functional future-java-developers groupby hash-function hashmap history history-of-java how-java-performs-better how-java-works http-client image import inspiration io itext-pdf java java-10 java-11 java-17 java-8 java-9 java-developers java-performance java-programming java-thread java-thread-programming java11 java16 java8 lambda-expression learning learning-and-development linkedlist list local-type-inference localdatetime map methodology microservices nio non-blockingio null-pointer-exception object-cloning optional packaging parallel pass-by-reference pass-by-value pdf performance prime-number programming project-loom race-condition readable-code record refactoring review scheduler scrum serialization serversocket simple-calculator socket software-development softwarearchitecture softwareengineering sorting source-code stack string string-pool stringbuilder swing thread threads tutorial unchecked vector virtual-thread volatile why-java zoneid