উইন্ডোজে নির্ভরযোগ্য ফাইল.রনেমটো () বিকল্প?


92

জাভা File.renameTo()সমস্যাযুক্ত, বিশেষত উইন্ডোজে, এটি মনে হয়। যেমন এপিআই ডকুমেন্টেশন বলে,

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

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

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

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

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


সম্পাদনা : এই বিশেষ ক্ষেত্রে, মনে হয় আমরা renameTo()আরও কয়েকটি জিনিস বিবেচনায় নিয়ে ব্যবহার করে পালিয়ে গিয়েছি ; দেখতে এই উত্তর


4
আপনি জেডিকে wait ব্যবহার করতে বা ব্যবহার করতে পারেন, এতে আরও ভাল ফাইল সিস্টেম সমর্থন রয়েছে।
আকনারোকদ

@ কেডি 304, আসলে আমি প্রাথমিক অ্যাক্সেস সংস্করণটি অপেক্ষা করতে বা ব্যবহার করতে পারি না, তবে এরকম কিছু জানতে আগ্রহী পথে চলছে!
জোনিক

উত্তর:


52

Files.move()জেডিকে in- তেও পদ্ধতিটি দেখুন ।

একটি উদাহরণ:

String fileName = "MyFile.txt";

try {
    Files.move(new File(fileName).toPath(), new File(fileName).toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ex) {
    Logger.getLogger(SomeClass.class.getName()).log(Level.SEVERE, null, ex);
}

7
দুর্ভাগ্যক্রমে জাভা 7 সর্বদা উত্তর হয় না (যেমন 42 হয়)
ওপ্পি

4
এমনকি ইবিএস স্টোরেজ সহ ইসি 2 তে কোড চালানোর সময় আমরা উবুন্টু, জেডিকে 7 তেও এই সমস্যার মুখোমুখি হয়েছি। File.renameTo ব্যর্থ হয়েছিল এবং তাই File.canWrite হয়েছিল।
saurabheights

মনে রাখবেন যে এটি ফাইল # পুনর্নবীকরণের () হিসাবে অবিশ্বাস্য। এটি ব্যর্থ হলে এটি আরও কার্যকর ত্রুটি দেয়। আমি খুঁজে পাওয়ার একমাত্র যুক্তিযুক্ত নির্ভরযোগ্য উপায় হ'ল ফাইল # কপি দিয়ে নতুন নামটিতে ফাইলটি অনুলিপি করা, এবং তারপরে ফাইলগুলি # মুছা ব্যবহার করে আসলটি মুছুন (যা নিজে মুছে ফেললে খুব ব্যর্থ হতে পারে, একই কারণে ফাইল # সরানো ব্যর্থ হতে পারে) ।
jwenting

26

এটি মূল্যবান জন্য, আরও কিছু ধারণা:

  1. উইন্ডোজে, renameTo()লক্ষ্য ডিরেক্টরিটি ফাঁকা থাকলেও, যদি এটি উপস্থিত থাকে তবে এটি ব্যর্থ হবে। এটি আমাকে বিস্মিত করেছিল, যেমন আমি লিনাক্সে চেষ্টা করেছিলাম, যেখানে renameTo()লক্ষ্যটি থাকলে তা সফল ছিল, যতক্ষণ না এটি খালি ছিল।

    (স্পষ্টতই আমার ধারণা করা উচিত ছিল না যে এই জাতীয় জিনিস প্ল্যাটফর্মগুলির জুড়ে একইরকম কাজ করে; জাভাডোক সতর্কতাই সতর্ক করে দেয়))

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

আমার ক্ষেত্রে, বেশিরভাগ সমস্যাগুলি উপরের উভয়টিকে বিবেচনায় নিয়ে সমাধান করা হয়েছে বলে মনে হয়, সুতরাং আমাদের কোনও নেটিভ কার্নেল কল বা অন্য কোনও কিছু করার দরকার নেই, সর্বোপরি।


4
আমি আপাতত আমার নিজের উত্তরটি গ্রহণ করছি, কারণ এটি আমাদের ক্ষেত্রে কী কী সহায়তা করেছিল তা বর্ণনা করে। তবুও, কেউ যদি পুনরায় নামকরণের সাথে আরও সাধারণ ইস্যুটির দুর্দান্ত উত্তর নিয়ে আসে, তবে নির্দ্বিধায় পোস্ট করুন এবং আমি গৃহীত উত্তরটি পুনর্বিবেচনা করে খুশি হব।
জোনিক

4
.5.৫ বছর পরে, আমি মনে করি পরিবর্তে জেডিকে answer উত্তর গ্রহণ করার সময় এসেছে , বিশেষত যেহেতু অনেকে এটিকে সহায়ক হিসাবে বিবেচনা করে। =)
জোনিক

19

মূল পোস্টটি "উইন্ডোতে জাভা দিয়ে দ্রুত সরানো / পুনর্নবীকরণের বিকল্প, নির্ভরযোগ্য পদ্ধতির অনুরোধ করে, সাধারণ জেডিকে বা কোনও বাহ্যিক লাইব্রেরি দিয়ে with"

এখানে অপরিচিত অন্য একটি বিকল্পটি v1.3.2 বা apache.commons.io লাইব্রেরির পরে রয়েছে, যার মধ্যে ফাইলUtils.moveFile () অন্তর্ভুক্ত রয়েছে ।

এটি ভুলের ভিত্তিতে বুলিয়ান মিথ্যা ফেরতের পরিবর্তে একটি আইওএক্সেপশন ছুড়ে দেয়।

এই অন্যান্য থ্রেডে আরও বড় লেপের প্রতিক্রিয়াও দেখুন ।


4
এছাড়াও, দেখে মনে হচ্ছে জেডিকে 1.7 এর মধ্যে আরও ভাল ফাইল সিস্টেম I / O সমর্থন অন্তর্ভুক্ত থাকবে। Java.nio.file.Path.moveTo
মাইকেনা

4
java.nio.file.Path.moveTo()
জেডিকে

5

আমার ক্ষেত্রে এটি আমার নিজের প্রয়োগের মধ্যে একটি মৃত বস্তু বলে মনে হয়েছিল, যা সেই ফাইলটির একটি হ্যান্ডেল রেখেছিল। সুতরাং সমাধানটি আমার পক্ষে কাজ করেছে:

for (int i = 0; i < 20; i++) {
    if (sourceFile.renameTo(backupFile))
        break;
    System.gc();
    Thread.yield();
}

সুবিধা: এটি খুব দ্রুত, কারণ নির্দিষ্ট হার্ডকোডযুক্ত কোনও থ্রেড.স্লিপ () নেই।

অসুবিধা: ২০ এর সীমাটি কিছু হার্ডকডযুক্ত নম্বর। আমার সমস্ত পরীক্ষায় i = 1 যথেষ্ট। তবে নিশ্চিত হয়ে আমি এটি 20 এ রেখেছি।


4
আমি একই জিনিসটি করেছি, তবে লুপটিতে 100 মিমি ঘুম নিয়ে।
লরেন্স ডল

4

আমি জানি এটি কিছুটা হ্যাকি বলে মনে হচ্ছে তবে আমি যা প্রয়োজন তার জন্য এটি মনে হচ্ছে বাফার পাঠক এবং লেখকদের ফাইল তৈরির কোনও সমস্যা নেই।

void renameFiles(String oldName, String newName)
{
    String sCurrentLine = "";

    try
    {
        BufferedReader br = new BufferedReader(new FileReader(oldName));
        BufferedWriter bw = new BufferedWriter(new FileWriter(newName));

        while ((sCurrentLine = br.readLine()) != null)
        {
            bw.write(sCurrentLine);
            bw.newLine();
        }

        br.close();
        bw.close();

        File org = new File(oldName);
        org.delete();

    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
    catch (IOException e)
    {
        e.printStackTrace();
    }

}

পার্সারের অংশ হিসাবে ছোট পাঠ্য ফাইলগুলির জন্য ভাল কাজ করে, নিশ্চিত করুন যে ওল্ডনেম এবং নিউনাম ফাইলের অবস্থানের পুরো পথ।

চিয়ার্স ক্যাকটাস


4

নিম্নলিখিত কোডের টুকরোটি কোনও 'বিকল্প' নয়, তবে উইন্ডোজ এবং লিনাক্স উভয় পরিবেশেই আমার জন্য নির্ভরযোগ্যভাবে কাজ করেছে:

public static void renameFile(String oldName, String newName) throws IOException {
    File srcFile = new File(oldName);
    boolean bSucceeded = false;
    try {
        File destFile = new File(newName);
        if (destFile.exists()) {
            if (!destFile.delete()) {
                throw new IOException(oldName + " was not successfully renamed to " + newName); 
            }
        }
        if (!srcFile.renameTo(destFile))        {
            throw new IOException(oldName + " was not successfully renamed to " + newName);
        } else {
                bSucceeded = true;
        }
    } finally {
          if (bSucceeded) {
                srcFile.delete();
          }
    }
}

4
হুম, এই কোডটি srcFile মুছে ফেলবে এমনকি পুনরায় নামকরণ (বা ডেসটফিল.ডিলিট) ব্যর্থ হলে এবং পদ্ধতিটি IOException নিক্ষেপ করে; আমি নিশ্চিত না যে এটি একটি ভাল ধারণা কিনা।
জোনিক 14

4
@ জোনিক, থ্যাঙ্কস, নাম পরিবর্তন করতে ব্যর্থ হলে এসসিআর ফাইলটি মোছার জন্য স্থির কোড।
পাগল ঘোড়া

উইন্ডোতে এই আমার নাম পরিবর্তন স্থির ভাগ করে নেওয়ার জন্য ধন্যবাদ।
বিলম্যান

3

উইন্ডোগুলিতে আমি Runtime.getRuntime().exec("cmd \\c ")ফাইলগুলি পুনরায় নামকরণ করতে কমান্ডলাইন পুনরায় নামকরণ ফাংশনটি ব্যবহার করি । এটি অনেক বেশি নমনীয়, উদাহরণস্বরূপ, আপনি বেক করার জন্য সমস্ত টেক্সট ফাইলের এক্সটেনশনটির নাম পরিবর্তন করতে চাইলে কেবল এটিকে আউটপুট স্ট্রিমে লিখুন:

পুনঃনামকরণ * .txt * .বাক

আমি জানি এটি কোনও ভাল সমাধান নয় তবে দৃশ্যত এটি আমার পক্ষে সর্বদা কাজ করেছে, জাভা ইনলাইন সমর্থনটি আরও ভাল better


সুপার, এটি আরও ভাল! ধন্যবাদ! :-)
গ্যাফক্জ

2

কেন না....

import com.sun.jna.Native;
import com.sun.jna.Library;

public class RenamerByJna {
    /* Requires jna.jar to be in your path */

    public interface Kernel32 extends Library {
        public boolean MoveFileA(String existingFileName, String newFileName);
    }

    public static void main(String[] args) {
        String path = "C:/yourchosenpath/";
        String existingFileName = path + "test.txt";
        String newFileName = path + "renamed.txt";

        Kernel32 kernel32 = (Kernel32) Native.loadLibrary("kernel32", Kernel32.class);
            kernel32.MoveFileA(existingFileName, newFileName);
        }
}

এনওয়াইন্ডো 7 এ কাজ করে, বিদ্যমান ফাইল উপস্থিত না থাকলে কিছুই করে না, তবে এটি ঠিক করার জন্য সম্ভবত আরও ভাল গতিযুক্ত হতে পারে।


2

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

fis = new FileInputStream(originalFile);
..
..
..
fis.close();// <<<---- Fixed by adding this
originalFile.renameTo(newDesitnationForOriginalFile);

1

আমার ক্ষেত্রে, ত্রুটিটি পিতামাতার ডিরেক্টরিতে ছিল। একটি বাগ হতে পারে, আমাকে সঠিক পথ পেতে সাবস্ট্রিং ব্যবহার করতে হবে।

        try {
            String n = f.getAbsolutePath();
            **n = n.substring(0, n.lastIndexOf("\\"));**
            File dest = new File(**n**, newName);
            f.renameTo(dest);
        } catch (Exception ex) {
           ...

0

আমি জানি এটি চুষে গেছে, তবে একটি বিকল্প হ'ল ব্যাট স্ক্রিপ্ট তৈরি করা যা "সাফল্য" বা "এরর" এর মতো সাধারণ কিছু তৈরি করে, অনুরোধ করে, এটি কার্যকর করার জন্য অপেক্ষা করে এবং তার ফলাফলগুলি পরীক্ষা করে।

রানটাইম.জেটআরটাইম ()। এক্সিকিউট ("সেন্টিমিডি / সি স্টার্ট টেস্ট.বাট");

এই থ্রেড আকর্ষণীয় হতে পারে। একটি পৃথক প্রক্রিয়ার কনসোল আউটপুট কীভাবে পড়তে হয় সে সম্পর্কে প্রক্রিয়া শ্রেণিটিও পরীক্ষা করে দেখুন।


-2

আপনি রোবোকপি চেষ্টা করতে পারেন । এটি ঠিক "নামকরণ" নয়, তবে এটি খুব নির্ভরযোগ্য।

রবোকপি ডিরেক্টরি বা ডিরেক্টরি গাছের নির্ভরযোগ্য মিরর করার জন্য ডিজাইন করা হয়েছে। এতে সমস্ত এনটিএফএসের বৈশিষ্ট্য এবং বৈশিষ্ট্য অনুলিপি করা হয়েছে তা নিশ্চিত করার বৈশিষ্ট্য রয়েছে এবং এতে নেটওয়ার্ক সংযোগগুলির জন্য বাধাগ্রস্থার জন্য অতিরিক্ত পুনরায় চালু কোড অন্তর্ভুক্ত রয়েছে।


ধন্যবাদ তবে যেহেতু রোবোকপি জাভা গ্রন্থাগার নয়, সম্ভবত এটি আমার জাভা কোড থেকে এটি ব্যবহার (এটি বান্ডিল করা এবং) করা খুব সহজ হবে না ...
জোনিক

-2

কোনও ফাইল সরানো / নামকরণ করতে আপনি এই ফাংশনটি ব্যবহার করতে পারেন:

BOOL WINAPI MoveFile(
  __in  LPCTSTR lpExistingFileName,
  __in  LPCTSTR lpNewFileName
);

এটি কার্নেল 32.dll এ সংজ্ঞায়িত করা হয়েছে।


4
আমি মনে করি জেএনআইতে এটি মোড়ানোর সমস্যাটি প্রসেস ডেকোরেটরে রবোকপি জড়ানোর জন্য প্রয়োজনীয় প্রচেষ্টার চেয়ে বেশি is
কেভিন মন্ট্রোজ

হ্যাঁ, আপনি বিমূর্ততার জন্য এই মূল্যটি প্রদান করেন - এবং যখন এটি ফাঁস হয়, তখন এটি ফাঁস হয় ভাল = ডি
চিআই

ধন্যবাদ, যদি এটি খুব জটিল না হয় তবে আমি এটি বিবেচনা করতে পারি। আমি কখনও জেএনআই ব্যবহার করি নি, এবং এসও তে উইন্ডোজ কার্নেল ফাংশন কল করার ভাল উদাহরণগুলি খুঁজে পাইনি, তাই আমি এই প্রশ্নটি পোস্ট করেছি: stackoverflow.com/questions/1000723/...
Jonik

আপনি johannburkard.de/software/nativecall এর মতো জেনেরিক জেএনআই মোড়কের চেষ্টা করতে পারেন কারণ এটি একটি দুর্দান্ত সাধারণ ফাংশন কল।
পিটার স্মিথ

-8
 File srcFile = new File(origFilename);
 File destFile = new File(newFilename);
 srcFile.renameTo(destFile);

উপরেরটি সহজ কোড। আমি উইন্ডোজ 7 এ পরীক্ষা করেছি এবং পুরোপুরি সূক্ষ্মভাবে কাজ করি।


11
এমন কেস রয়েছে যেখানে পুনরায় নামকরণ () নির্ভরযোগ্যভাবে কাজ করে না ; এই প্রশ্নের পুরো বিষয়টি।
জোনিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.