আমি জাভা ব্যবহার করে কোনও ফাইল লক করতে পারি (যদি সম্ভব হয়)


121

আমার একটি জাভা প্রক্রিয়া রয়েছে যা একটি ফাইলরেডার ব্যবহার করে কোনও ফাইল খোলায়। আমি কীভাবে এই ফাইলটি খুলতে থেকে অন্য কোনও (জাভা) প্রক্রিয়াটিকে বাধা দিতে পারি, বা কমপক্ষে সেই দ্বিতীয় প্রক্রিয়াটি জানাতে পারি যে ফাইলটি ইতিমধ্যে খোলা আছে? ফাইলটি খোলা থাকলে (যা আমার সমস্যা সমাধান করে) এটি দ্বিতীয় প্রক্রিয়াটি স্বয়ংক্রিয়ভাবে একটি ব্যতিক্রম ঘটায় বা আমাকে প্রথম প্রক্রিয়ায় কোনও ধরণের পতাকা বা তর্ক দিয়ে স্পষ্টভাবে এটি খুলতে হবে?

স্পষ্ট করা:

আমার কাছে একটি জাভা অ্যাপ্লিকেশন রয়েছে যা একটি ফোল্ডার তালিকাভুক্ত করে এবং প্রতিটি ফাইল এটির প্রক্রিয়াজাতকরণের জন্য তালিকায় খোলে। এটি প্রতিটি ফাইল একের পর এক প্রক্রিয়া করে। প্রতিটি ফাইলের প্রসেসিং এটিকে পড়তে এবং বিষয়বস্তুর উপর ভিত্তি করে কিছু গণনা করে থাকে এবং এটি প্রায় 2 মিনিট সময় নেয়। আমার কাছে আরও একটি জাভা অ্যাপ্লিকেশন রয়েছে যা একই কাজ করে তবে পরিবর্তে ফাইলটিতে লেখেন। আমি যা চাই তা হ'ল এই অ্যাপ্লিকেশনগুলি একই সাথে চালাতে সক্ষম হবে যাতে পরিস্থিতিটি এরকম হয়। রিড অ্যাপ ফোল্ডারটি তালিকাভুক্ত করে এবং এ, বি, সি ফাইলগুলি সন্ধান করে finds এটি ফাইল এ খুলবে এবং পঠন শুরু করে। WritApp ফোল্ডারটি তালিকাভুক্ত করে এবং এ, বি, সি ফাইলগুলি সন্ধান করে এটি ফাইল এ খুলবে, এটি খোলা রয়েছে তা দেখে (ব্যতিক্রম বা যে কোনও উপায়ে) এবং বি ফাইল করতে যায় রিড অ্যাপ্লিকেশন ফাইল এ শেষ করে এবং বিতে অবিরত থাকে এটি এটি দেখেছে যে এটি উন্মুক্ত এবং সিটিতে অবিরত রয়েছে এটি লিখিত অ্যাপ্লিকেশনটি গুরুত্বপূর্ণ নয় ' রিড অ্যাপ একই ফাইল বা বিপরীতে পড়ার সময় লিখবেন না। তারা বিভিন্ন প্রক্রিয়া।


12
আপনার অর্থ প্রক্রিয়া হিসাবে দুটি প্রক্রিয়া (দুটি জেভিএম) বা থ্রেড (একই জেভিএম)। উত্তরের উপর প্রভাবটি সর্বজনীন।
স্টু থম্পসন

স্যাম্পল কোডটি এখানে সমাধান দেখায় চেক করুন: stackoverflow.com/a/58871479/5154619
ডেভি Cavalcanti

উত্তর:


117

ফাইলচ্যানেল.লক সম্ভবত আপনি যা চান তা হ'ল।

try (
    FileInputStream in = new FileInputStream(file);
    java.nio.channels.FileLock lock = in.getChannel().lock();
    Reader reader = new InputStreamReader(in, charset)
) {
    ...
}

(অস্বীকৃতি: কোড সংকলিত হয়নি এবং অবশ্যই পরীক্ষিত নয়))

ফাইললকের জন্য এপিআই ডকটিতে "প্ল্যাটফর্ম নির্ভরতা" শিরোনামে বিভাগটি নোট করুন ।


22
আরও গুরুত্বপূর্ণ, জেভিএমের জন্য লক করা এবং একক জেভিএমের মধ্যে পৃথক থ্রেড দ্বারা অ্যাক্সেসের জন্য ফাইলটি লক করার পক্ষে উপযুক্ত নয় তা বুঝতে understand
স্টু থম্পসন

11
আপনার একটি লিখনযোগ্য স্ট্রিম প্রয়োজন (যেমন FileOutputStream)।
জাভিয়ের

@ জাভিয়ার আপনি কি করেন? আমি চেষ্টা করিনি। এপিআই ডক্সের বাইরে কোনও কিছুই লাফিয়ে উঠেনি যে এটি প্রয়োজনীয়তা। FileOutputStreamএকটি খুব বেশি ব্যবহার হতে যাচ্ছে না Reader
টম হাটিন -

18
হ্যাঁ, আমি এটি চেষ্টা করেছি এবং এটি ছুড়ে ফেলেছে NonWritableChannelException, কারণ lock()একচেটিয়া লক অর্জনের চেষ্টা করা হয়েছে তবে এর জন্য লেখার অ্যাক্সেস দরকার। আপনার যদি একটি ইনপুট স্ট্রিম থাকে তবে আপনি ব্যবহার করতে পারেন lock(0L, Long.MAX_VALUE, false)যা কোনও ভাগ করা লকটি অর্জন করে এবং কেবল একটি পড়ার অ্যাক্সেস প্রয়োজন। আপনি RandomAccessFileযখন পড়ার সময় একচেটিয়া লক চান তবে আপনি রিড-রাইটিং মোডে একটি খোলা ব্যবহার করতে পারেন ... তবে এটি সহবর্তী পাঠকদের বারণ করবে।
জাভিয়ের

6
@ জাভিয়ার আমার ধারণা আপনি বলতে চাইছেন lock(0L, Long.MAX_VALUE, true), না lock(0L, Long.MAX_VALUE, false)। শেষ যুক্তিটি হ'ল boolean shared ডকস.অরাকল.com
জন

60

java.ioপ্যাকেজে ক্লাস ব্যবহার করবেন না , পরিবর্তে java.nioপ্যাকেজটি ব্যবহার করুন । আধুনিক একটি FileLockক্লাস আছে। আপনি একটিতে একটি লক প্রয়োগ করতে পারেন FileChannel

 try {
        // Get a file channel for the file
        File file = new File("filename");
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();

        // Use the file channel to create a lock on the file.
        // This method blocks until it can retrieve the lock.
        FileLock lock = channel.lock();

        /*
           use channel.lock OR channel.tryLock();
        */

        // Try acquiring the lock without blocking. This method returns
        // null or throws an exception if the file is already locked.
        try {
            lock = channel.tryLock();
        } catch (OverlappingFileLockException e) {
            // File is already locked in this thread or virtual machine
        }

        // Release the lock - if it is not null!
        if( lock != null ) {
            lock.release();
        }

        // Close the file
        channel.close();
    } catch (Exception e) {
    }

বিটিডব্লিউ, আমি লক ফাইলটিতে এই টিপ স্ট্যাকওভারফ্লো.com / a / 35885 / 1422630 থেকে বর্তমান পিড লিখছি , যাতে আমি এটি নতুন উদাহরণে পড়তে পারি!
অ্যাকোরিয়াস পাওয়ার

1
এই এক ভাল লাগছিল, কিন্তু এটি কাজ করে না। আমি প্রতিবার ওভারল্যাপিং ফাইললক এক্সপ্লেশনটি পাই, এমনকি ফাইলটিও উপস্থিত ছিল না
গ্যাভরিয়েল

1
সমস্যাটি ঘটবে যদি আপনি তালাবদ্ধ হওয়ার পরে ট্র্যাকলককে কল করেন যেমন এটি যেমন লেখা আছে
Igor Vuković

17

আপনি যদি জাভা NIO ( JDK 1.4 বা তার বেশি ) ব্যবহার করতে পারেন তবে আমি মনে করি আপনি সন্ধান করছেনjava.nio.channels.FileChannel.lock()

FileChannel.lock ()


5
হতে পারে. ওপেন 'প্রক্রিয়া' বলতে কী বোঝায় তার উপর নির্ভর করে। "পুরো জাভা ভার্চুয়াল মেশিনের পক্ষে ফাইল লকগুলি রাখা হয় They একই ভার্চুয়াল মেশিনের মধ্যে একাধিক থ্রেড দ্বারা কোনও ফাইল অ্যাক্সেস নিয়ন্ত্রণের জন্য এগুলি উপযুক্ত নয়" "
স্টু থম্পসন

@ স্টু: আমি জানি আপনি এই প্রশ্নের উত্তর অনেক আগেই দিয়েছিলেন, তবে আমি আশা করি আপনি যখন বলেছিলেন তখন আপনি কী বোঝাতে চেয়েছিলেন তা ব্যাখ্যা করতে পারবেনFile locks are held on behalf of the entire Java virtual machine. They are not suitable for controlling access to a file by multiple threads within the same virtual machine
থাং ফাম

3
@ হ্যারি তিনি ডক্স থেকে উদ্ধৃতি দিচ্ছেন: download.oracle.com/javase/6/docs/api/java/nio/channels/… এর অর্থ এটি থ্রেডের কাছে অদৃশ্য তবে অন্যান্য প্রক্রিয়াগুলিকে প্রভাবিত করে।
আর্টুর সিজ্জাকা

@ হ্যারি: এই এনক্রো-মন্তব্যে আরও বেশি যুক্ত করতে, কল্পনা করুন যে আপনি টমক্যাটের সাথে ওয়েবসাইটগুলি পরিবেশন করার জন্য জাভা ব্যবহার করছেন। আপনার কাছে প্রচুর থ্রেড থাকতে পারে, প্রতিটি ওয়েব ব্রাউজার থেকে একটি অনুরোধ সরবরাহ করে। তবে, তারা সকলেই রান্নাঘরের অনেকগুলি রান্নার মতো একই ফাইল লকিং মেকানিজমকে নিয়ন্ত্রণ করে। একটি অনুরোধ দ্বিতীয়টির মাঝামাঝি সময়ে শেষ হয়ে যেতে পারে এবং হঠাৎ আপনার ফাইলটি "আনলক" হয়ে যায় যখন আপনি কোনও কিছুর মাঝখানে থাকাকালীন হন, এবং তারপরে ক্রোনজবের মতো অন্য কোনও প্রক্রিয়া এটি লক করে দিতে পারে এবং তারপরে আপনি অপ্রত্যাশিতভাবে আপনার হারিয়ে ফেলেন লক করুন এবং আপনার অনুরোধ শেষ হতে পারে না ...
ডারিয়ান


5

আপনি যা সন্ধান করছেন এটি এটি নাও হতে পারে, তবে অন্য একটি কোণ থেকে কোনও সমস্যা আসার স্বার্থে ....

এই দুটি জাভা প্রক্রিয়া যা একই অ্যাপ্লিকেশনে একই ফাইলটি অ্যাক্সেস করতে পারে? সম্ভবত আপনি কেবল একটি একক, সিঙ্ক্রোনাইজড পদ্ধতিতে (বা আরও ভাল, জেএসআর -166 ব্যবহার করে ) ফাইলের সমস্ত অ্যাক্সেস ফিল্টার করতে পারবেন ? এইভাবে, আপনি ফাইলটিতে অ্যাক্সেস এবং সম্ভবত সারি অ্যাক্সেস অনুরোধগুলি নিয়ন্ত্রণ করতে পারেন can


3
দুটি প্রক্রিয়া সিঙ্ক্রোনাইজেশন ব্যবহার করতে পারে না, একই প্রক্রিয়াতে কেবল দুটি থ্রেড।
লার্নের মারকুইস

3

একটি র্যান্ডমএকসেসফাইল ব্যবহার করুন, এটি চ্যানেল পান, তারপরে লক () এ কল করুন। ইনপুট বা আউটপুট স্ট্রিম সরবরাহ করা চ্যানেলটিতে সঠিকভাবে লক করার পর্যাপ্ত অধিকার নেই। শেষ অবধি আনলক () কল করতে ভুলবেন না (ফাইলটি বন্ধ করা লকটি অগত্যা মুক্তি দেয় না)।


তুমি কি বিস্তারিত বলতে পারো? আমি বলতে চাইছি, এলোমেলো র্যান্ডমএ্যাক্সেস ফাইলটির লকটি প্রবাহিতের চেয়ে ভাল বা নিরাপদ
প্যারালাইফ

নীচে পোস্ট করা সাধারণ উদাহরণের লিঙ্ক
Touko

প্যারালাইফ - বিলম্বের জন্য দুঃখিত - আপনার প্রশ্নটি কেবলমাত্র খেয়াল করেছেন। স্ট্রিমগুলি থেকে থাকা লকগুলি পঠিত লক (ইনপুট স্ট্রিমের জন্য) এবং একচেটিয়া, পূর্ণ চ্যানেল রাইটিং লকগুলি (আউটপুট স্ট্রিমের জন্য) হতে চলেছে। আমার অভিজ্ঞতা হয়েছে যে আরএএফের লকগুলি আরও সূক্ষ্ম দানাদার নিয়ন্ত্রণের অনুমতি দেয় (যেমন আপনি কোনও ফাইলের অংশ লক করতে পারেন)।
কেভিন ডে

1

নীচে JVM দ্বারা প্রক্রিয়াটি সম্পন্ন না হওয়া পর্যন্ত কোনও ফাইল লক করার জন্য একটি নমুনা স্নিপেট কোড রয়েছে।

 public static void main(String[] args) throws InterruptedException {
    File file = new File(FILE_FULL_PATH_NAME);
    RandomAccessFile in = null;
    try {
        in = new RandomAccessFile(file, "rw");
        FileLock lock = in.getChannel().lock();
        try {

            while (in.read() != -1) {
                System.out.println(in.readLine());
            }
        } finally {
            lock.release();
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.