রিসোর্স-ব্লক ব্যবহার করে একাধিক শৃঙ্খলাবদ্ধ সম্পদ পরিচালনার জন্য আইডিয়মটি সঠিক?


168

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

আমি নিম্নলিখিত তিনটি বিকল্প নিয়ে এসেছি:

1)

আমি যে নির্ভুল প্রতিমাটি দেখেছি তা হ'ল এআরএম-পরিচালিত ভেরিয়েবলের মধ্যে কেবলমাত্র শীর্ষ-স্তরের মোড়ক ঘোষনা করা:

static void printToFile1(String text, File file) {
    try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }
}

এটি সুন্দর এবং সংক্ষিপ্ত, তবে এটি ভেঙে গেছে। অন্তর্নিহিত FileWriterকোনও পরিবর্তনশীল হিসাবে ঘোষিত না হওয়ায় এটি কখনই উত্পন্ন finallyব্লকে সরাসরি বন্ধ হবে না । এটি কেবল closeমোড়ানোর পদ্ধতি দ্বারা বন্ধ করা হবে BufferedWriter। সমস্যাটি হ'ল, যদি bwএর নির্মাণকারীর থেকে কোনও ব্যতিক্রম ছুঁড়ে ফেলা হয় , তবে এটি কল করা closeহবে না এবং তাই অন্তর্নিহিত FileWriter বন্ধ করা হবে না

2)

static void printToFile2(String text, File file) {
    try (FileWriter fw = new FileWriter(file);
            BufferedWriter bw = new BufferedWriter(fw)) {
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }
}

এখানে, অন্তর্নিহিত এবং মোড়ানোর উভয় সংস্থানটি এআরএম-পরিচালিত ভেরিয়েবলগুলিতে ঘোষণা করা হয়েছে, সুতরাং উভয় অবশ্যই বন্ধ হয়ে যাবে, তবে অন্তর্নিহিত fw.close() দু'বার বলা হবে : কেবল সরাসরি নয়, তবে মোড়কের মাধ্যমেও bw.close()

এই দুটি নির্দিষ্ট শ্রেণীর ক্ষেত্রে সমস্যা হওয়া উচিত নয় যা উভয়ই প্রয়োগ করে Closeable(যা একটি উপপ্রকার AutoCloseable), যার চুক্তিতে বলা হয়েছে যে একাধিক কল করার closeঅনুমতি দেওয়া হয়েছে:

এই স্ট্রিমটি বন্ধ করে এবং এর সাথে যুক্ত যেকোনও সিস্টেম সংস্থান প্রকাশ করে। যদি স্ট্রিমটি ইতিমধ্যে বন্ধ হয়ে যায় তবে এই পদ্ধতিটি আহ্বানের কোনও প্রভাব নেই।

তবে, সাধারণ ক্ষেত্রে আমার কাছে এমন সংস্থান থাকতে পারে যা কেবলমাত্র প্রয়োগ করে AutoCloseable(এবং না Closeable), যা গ্যারান্টি দেয় না যে closeএকাধিকবার বলা যেতে পারে:

নোট করুন যে java.io.Cseseable এর ঘনিষ্ঠ পদ্ধতির বিপরীতে, এই ঘনিষ্ঠ পদ্ধতিটি আদর্শবান হওয়ার প্রয়োজন নেই। অন্য কথায়, এই ঘনিষ্ঠ পদ্ধতিকে একাধিকবার কল করা কিছুটা দৃশ্যমান পার্শ্ব প্রতিক্রিয়া হতে পারে, Cloableable.close এর বিপরীতে যা একাধিকবার ডাকা হলেও কোনও প্রভাব ফেলতে হবে না। যাইহোক, এই ইন্টারফেসের প্রয়োগকারীরা তাদের ঘনিষ্ঠ পদ্ধতিগুলিকে আদর্শবান করতে দৃ strongly়ভাবে উত্সাহিত করা হয়।

3)

static void printToFile3(String text, File file) {
    try (FileWriter fw = new FileWriter(file)) {
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }
}

এই সংস্করণটি তাত্ত্বিকভাবে সঠিক হওয়া উচিত, কারণ কেবল এমন fwএকটি বাস্তব সংস্থান উপস্থাপন করে যা পরিষ্কার করা দরকার needs bwকোনো সম্পদ এটি শুধুমাত্র প্রতিনিধিদের রাখা নিজেই নয়, fw, তাই এটি শুধুমাত্র ঘনিষ্ঠ অন্তর্নিহিত করার জন্য যথেষ্ট হওয়া উচিত fw

অন্যদিকে, সিনট্যাক্সটি কিছুটা অনিয়মিত এবং এছাড়াও, গ্রিপস একটি সতর্কতা জারি করে, যা আমি বিশ্বাস করি যে এটি একটি মিথ্যা বিপদাশঙ্কা, তবে এটি এখনও একটি সতর্কতা যা একটিকে মোকাবেলা করতে হবে:

রিসোর্স লিক: 'বিডব্লু' কখনই বন্ধ হয় না


সুতরাং, কোন পদ্ধতির জন্য যেতে? বা আমি অন্য কোনও প্রতিমাটি মিস করেছি যা সঠিক ?


4
অবশ্যই, যদি অন্তর্নিহিত ফাইল রাইটারের কনস্ট্রাক্টর একটি ব্যতিক্রম ছুঁড়ে, এটি এমনকি খোলা হয় না এবং সবকিছু ঠিক আছে। 1 ম উদাহরণটি কী, ফাইল রাইটার তৈরি হলে যা ঘটে তা হল, তবে বাফারড্রাইটারের কনস্ট্রাক্টর একটি ব্যতিক্রম ছুঁড়ে ফেলে।
নাটিক্স

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

10
@ পিটারল্যাওরে হ্যাঁ, আপনি ঠিক বলেছেন যে এই দৃশ্যে বাফারড্রাইটারের নির্মাতা সম্ভবত কোনও ব্যতিক্রম এড়াতে পারবেন না, তবে যেমনটি আমি উল্লেখ করেছি, এই প্রশ্নটি কোনও সাজসজ্জার-শৈলীর সংস্থান নিয়ে উদ্বেগ প্রকাশ করে। তবে উদাহরণস্বরূপ public BufferedWriter(Writer out, int sz)একটি নিক্ষেপ করতে পারেন IllegalArgumentException। এছাড়াও, আমি বাফারড্রাইটারকে এমন ক্লাসের সাথে প্রসারিত করতে পারি যা এর নির্মাতার কাছ থেকে কিছু নিক্ষেপ করতে পারে বা যা প্রয়োজন তা পছন্দ করে একটি কাস্টম মোড়ক তৈরি করতে পারে।
নাটিক্স

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

10
@ নাটিক্স আমি আশা করি এসও-তে সমস্ত প্রশ্ন যেমন রয়েছে তেমনি গবেষণা এবং পরিষ্কার হওয়া উচিত। আমি আশা করি আমি এই 100 বার ভোট দিতে পারতাম।
গিগ

উত্তর:


75

বিকল্পগুলি সম্পর্কে আমার গ্রহণ এখানে:

1)

try (BufferedWriter bw = new BufferedWriter(new FileWriter(file))) {
    bw.write(text);
}

আমার জন্য, 15 বছর আগে traditionalতিহ্যবাহী সি ++ থেকে জাভাতে আসা সেরা জিনিসটি ছিল আপনি নিজের প্রোগ্রামকে বিশ্বাস করতে পারেন। এমনকি জিনিসগুলি অশান্তি এবং ভুল হয়ে থাকলেও, যা তারা প্রায়শই করেন, আমি চাই বাকী কোডটি সর্বোত্তম আচরণ এবং গোলাপের ঘ্রাণে থাকতে পারে। আসলে, BufferedWriterসম্ভবত এখানে একটি ব্যতিক্রম নিক্ষেপ। উদাহরণস্বরূপ, মেমরির বাইরে চলে যাওয়া অস্বাভাবিক কিছু হবে না। অন্যান্য সাজসজ্জার জন্য, আপনি কি জানেন যে কোন java.ioমোড়ক ক্লাস তাদের নির্মাতাদের থেকে একটি পরীক্ষিত ব্যতিক্রম ছুঁড়ে ফেলে? আমি না। আপনি যদি সেই ধরণের অস্পষ্ট জ্ঞানের উপর নির্ভর করেন তবে কোড বোধগম্যতাটি খুব ভাল করে না।

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

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

2)

try (
    FileWriter fw = new FileWriter(file);
    BufferedWriter bw = new BufferedWriter(fw)
) {
    bw.write(text);
}

আমরা এখনও অবশেষে অবরুদ্ধ ব্লকে ফ্লাশ করছি (পুনরাবৃত্তি সহ close- এটি আরও সজ্জিত করার সাথে সাথে আরও খারাপ হয়) তবে নির্মাণটি নিরাপদ এবং আমাদের অবশেষে অবরুদ্ধ করতে হবে যাতে flushকোনও ব্যর্থও সম্পদ প্রকাশকে বাধা দেয় না prevent

3)

try (FileWriter fw = new FileWriter(file)) {
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write(text);
}

এখানে একটি বাগ আছে। হতে হবে:

try (FileWriter fw = new FileWriter(file)) {
    BufferedWriter bw = new BufferedWriter(fw);
    bw.write(text);
    bw.flush();
}

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

রায়

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


4
সংস্করণ 3-এ, আপনি কীভাবে জানবেন যে ডাব্লুডাব্লু এর কাছাকাছি কল করার প্রয়োজন নেই? এবং এমনকি যদি আপনি এটি নিশ্চিত হতে পারেন তবে এটি কি আপনার মতো সংস্করণ 1 এর জন্য উল্লিখিত "অস্পষ্ট জ্ঞান" নয়?
টিমকে

3
" সফ্টওয়্যার বিকাশের কারণগুলি 2 আরও ভাল পছন্দ করে তোলে " আপনি কি এই বিবৃতিটি আরও বিশদে ব্যাখ্যা করতে পারবেন?
ডানকান জোন্স

8
আপনি কি "ক্লোজারগুলির সাথে অভিজাতগুলির প্রায়শই সম্পাদন করুন"
মারকাস

2
আপনি "জাভা এসই 8 এ ক্লোজারগুলির সাথে পরিষ্কার সিনট্যাক্স" কী ব্যাখ্যা করতে পারেন?
পিটারটেক

1
: "বাগ্ধারা চারপাশ নির্বাহ করা" উদাহরণ এখানে stackoverflow.com/a/342016/258772
mrts

20

প্রথম শৈলীটি ওরাকল দ্বারা প্রস্তাবিত একটি । BufferedWriterচেক করা ব্যতিক্রমগুলি ছুঁড়ে না, সুতরাং যদি কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় তবে প্রোগ্রামটি এটি থেকে সেরে উঠবে বলে আশা করা যায় না, উত্সটি বেশিরভাগ ক্ষেত্রে পুনরুদ্ধার করে।

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


2
এটি কার্যকর জাভার তৃতীয় সংস্করণেও প্রস্তাবিত পদ্ধতির।
shmosel

5

বিকল্প 4

আপনার সংস্থানগুলি বন্ধযোগ্য হিসাবে পরিবর্তন করুন, আপনি যদি পারেন তবে অটোসক্লোয়েবল নয়। কনস্ট্রাক্টরদের বেঁধে রাখা যায় এই বিষয়টি থেকে বোঝা যায় যে দু'বার রিসোর্স বন্ধ করা অযৌক্তিক নয়। (এটিআরএমের আগেও এটি সত্য ছিল)) নীচে এটিতে আরও।

বিকল্প 5

কাছাকাছি () দুবার কল করা হবে না তা নিশ্চিত করতে খুব সাবধানতার সাথে এআরএম এবং কোড ব্যবহার করবেন না!

বিকল্প 6

এআরএম ব্যবহার করবেন না এবং চেষ্টা করার জন্য / শেষ পর্যন্ত আপনার শেষ দিকে () কলগুলি রাখুন।

কেন আমি মনে করি না যে এই সমস্যাটি আর্মের কাছে অনন্য

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

ভাল নয় কারণ fw দুইবার বন্ধ হতে পারে। (যা ফাইল রাইটারের পক্ষে ঠিক আছে তবে আপনার হাইপোথিয়াল উদাহরণে নয়):

FileWriter fw = null;
BufferedWriter bw = null;
try {
  fw = new FileWriter(file);
  bw = new BufferedWriter(fw);
  bw.write(text);
} finally {
  if ( fw != null ) fw.close();
  if ( bw != null ) bw.close();
}

কোনও ভাল নেই কারণ একটি বাফারড্রাইটার তৈরির ক্ষেত্রে ব্যতিক্রম হলে fw বন্ধ নয়। (আবার, ঘটতে পারে না তবে আপনার অনুমানের উদাহরণে):

FileWriter fw = null;
BufferedWriter bw = null;
try {
  fw = new FileWriter(file);
  bw = new BufferedWriter(fw);
  bw.write(text);
} finally {
  if ( bw != null ) bw.close();
}

3

আমি কেবল জিনে বোয়ারস্কির এআরএম ব্যবহার না করার বিষয়ে পরামর্শ চেয়েছিলাম তবে ফাইল রাইটারটি সর্বদা একবারে বন্ধ হয়ে গেছে তা নিশ্চিত করে তৈরি করতে চেয়েছিলাম। এখানে কোনও সমস্যা আছে বলে মনে করবেন না ...

FileWriter fw = null;
BufferedWriter bw = null;
try {
    fw = new FileWriter(file);
    bw = new BufferedWriter(fw);
    bw.write(text);
} finally {
    if (bw != null) bw.close();
    else if (fw != null) fw.close();
}

আমার ধারণা, যেহেতু এআরএম কেবল সিনট্যাকটিক চিনি, আমরা সবসময় এটি অবশেষে ব্লকগুলি প্রতিস্থাপন করতে ব্যবহার করতে পারি না। ঠিক তেমনি পুনরাবৃত্তিকারীদের দ্বারা সম্ভব এমন কিছু করার জন্য আমরা সর্বদা প্রতিটি লুপ ব্যবহার করতে পারি না।


5
যদি আপনার tryএবং finallyব্লক উভয়ই ব্যতিক্রম ছুঁড়ে ফেলে তবে এই নির্মাণটি প্রথম (এবং সম্ভাব্য আরও কার্যকর) একটিকে হারাবে।
আরএক্সজি

3

পূর্ববর্তী মন্তব্যে সম্মতি জানাতে : সবচেয়ে সহজ হ'ল (২)Closeable সংস্থানসমূহ ব্যবহারের চেষ্টা করুন এবং তাদের সাথে সম্পদ-বিধি অনুসারে ঘোষণা করুন। যদি আপনার কেবল থাকে তবে আপনি AutoCloseableএগুলি অন্য (নেস্টেড) শ্রেণিতে আবদ্ধ করতে পারেন যা কেবল closeএকবার (মুখের প্যাটার্ন) বলা হয়ে থাকে এমন চেক করে , যেমন থাকার মাধ্যমে private bool isClosed;। অনুশীলনে এমনকি ওরাকল ঠিক (1) নির্মাতাদের শৃঙ্খলাবদ্ধ করে এবং চেইনের মাধ্যমে কিছুটা ব্যতিক্রম সঠিকভাবে পরিচালনা করে না।

বিকল্পভাবে, আপনি স্ট্যাটিক কারখানার পদ্ধতি ব্যবহার করে ম্যানুয়ালি একটি শৃঙ্খলিত উত্স তৈরি করতে পারেন; এটি চেইনকে encapsulates, এবং এটি যদি পার্ট-ওয়ে ব্যর্থ হয় তবে ক্লিনআপ পরিচালনা করবে:

static BufferedWriter createBufferedWriterFromFile(File file)
  throws IOException {
  // If constructor throws an exception, no resource acquired, so no release required.
  FileWriter fileWriter = new FileWriter(file);
  try {
    return new BufferedWriter(fileWriter);  
  } catch (IOException newBufferedWriterException) {
    try {
      fileWriter.close();
    } catch (IOException closeException) {
      // Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
      // as in try-with-resources.
      newBufferedWriterException.addSuppressed(closeException);
    }
    throw newBufferedWriterException;
  }
}

এরপরে আপনি এটিকে রিসোর্স ক্লাউজে একটি একক সংস্থান হিসাবে ব্যবহার করতে পারেন:

try (BufferedWriter writer = createBufferedWriterFromFile(file)) {
  // Work with writer.
}

জটিলতা একাধিক ব্যতিক্রম পরিচালনা করে; অন্যথায় এটি কেবল "ঘনিষ্ঠ সংস্থান যা আপনি এখনও অর্জন করেছেন"। একটি প্রচলিত অনুশীলনটি প্রথমে মনে হয় যে চলকটি প্রথমে সূচনা করে যেটি অবজেক্টকে ধরে রাখে null(এখানে fileWriter), এবং তারপরে ক্লিনআপে একটি নাল চেক অন্তর্ভুক্ত করে তবে এটি অপ্রয়োজনীয় বলে মনে হয়: যদি কনস্ট্রাক্টর ব্যর্থ হয় তবে পরিষ্কার করার মতো কিছুই নেই, সুতরাং আমরা কেবলমাত্র সেই ব্যতিক্রমটিকে প্রচার করতে পারি, যা কোডটি কিছুটা সহজ করে।

আপনি সম্ভবত এটি উদারভাবে করতে পারেন:

static <T extends AutoCloseable, U extends AutoCloseable, V>
    T createChainedResource(V v) throws Exception {
  // If constructor throws an exception, no resource acquired, so no release required.
  U u = new U(v);
  try {
    return new T(u);  
  } catch (Exception newTException) {
    try {
      u.close();
    } catch (Exception closeException) {
      // Exceptions in cleanup code are secondary to exceptions in primary code (body of try),
      // as in try-with-resources.
      newTException.addSuppressed(closeException);
    }
    throw newTException;
  }
}

একইভাবে, আপনি তিনটি সংস্থান ইত্যাদি চেইন করতে পারেন etc.

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


আমি কি সঠিকভাবে জড়ো হয়েছি যে এখনও কারও মতো চেষ্টা-সহ-সংস্থান ব্যবহার করতে হবে try (BufferedWriter writer = <BufferedWriter, FileWriter>createChainedResource(file)) { /* work with writer */ }?
এরিক

@ এরিক হ্যাঁ, আপনার এখনও চেষ্টা করে উইথ-রিসোর্স ব্যবহার করা দরকার, তবে আপনাকে কেবল চেইন রিসোর্সের জন্য একটি ফাংশন ব্যবহার করতে হবে: কারখানার ফাংশনটি শৃঙ্খলকে আবদ্ধ করে। আমি ব্যবহারের উদাহরণ যুক্ত করেছি; ধন্যবাদ!
নীল ভন বার্থ

2

যেহেতু আপনার সংস্থানগুলি বাসা বেঁধেছে তাই আপনার চেষ্টা সহ দারাগুলিও হওয়া উচিত:

try (FileWriter fw=new FileWriter(file)) {
    try (BufferedWriter bw=new BufferedWriter(fw)) {
        bw.write(text);
    } catch (IOException ex) {
        // handle ex
    }
} catch (IOException ex) {
    // handle ex
}

5
এটি আমার ২ য় উদাহরণের সাথে বেশ মিল। যদি কোনও ব্যতিক্রম না ঘটে তবে ফাইল রাইটারগুলি closeদু'বার কল করা হবে।
নাটিক্স

0

আমি বলব এআরএম ব্যবহার করবেন না এবং ক্লোজবেবলের সাথে এগিয়ে যান। যেমন পদ্ধতি ব্যবহার করুন,

public void close(Closeable... closeables) {
    for (Closeable closeable: closeables) {
       try {
           closeable.close();
         } catch (IOException e) {
           // you can't much for this
          }
    }

}

এছাড়াও আপনি বন্ধ কলিং বিবেচনা করা উচিত BufferedWriterযেমন ঠিক পাসে প্রতিনিধিরূপে নয় FileWriter, কিন্তু এটা মত কিছু পরিষ্করণ করে flushBuffer


0

আমার সমাধানটি হল "এক্সট্রাক্ট মেথড" রিফ্যাক্টরিং করা, নিম্নলিখিত হিসাবে:

static AutoCloseable writeFileWriter(FileWriter fw, String txt) throws IOException{
    final BufferedWriter bw  = new BufferedWriter(fw);
    bw.write(txt);
    return new AutoCloseable(){

        @Override
        public void close() throws IOException {
            bw.flush();
        }

    };
}

printToFile হয় লেখা যেতে পারে

static void printToFile(String text, File file) {
    try (FileWriter fw = new FileWriter(file)) {
        AutoCloseable w = writeFileWriter(fw, text);
        w.close();
    } catch (Exception ex) {
        // handle ex
    }
}

অথবা

static void printToFile(String text, File file) {
    try (FileWriter fw = new FileWriter(file);
        AutoCloseable w = writeFileWriter(fw, text)){

    } catch (Exception ex) {
        // handle ex
    }
}

ক্লাস lib ডিজাইনারদের জন্য, আমি তাদের প্রসারিত করার পরামর্শ দেব AutoClosable বন্ধ করার জন্য অতিরিক্ত পদ্ধতিতে ইন্টারফেসটিএই ক্ষেত্রে আমরা ম্যানুয়ালি ঘনিষ্ঠ আচরণটি নিয়ন্ত্রণ করতে পারি।

ভাষা ডিজাইনারদের জন্য পাঠটি হ'ল একটি নতুন বৈশিষ্ট্য যুক্ত করার অর্থ অন্যকে যুক্ত করার অর্থ। এই জাভা ক্ষেত্রে, স্পষ্টতই এআরএম বৈশিষ্ট্যটি কোনও উত্সের মালিকানা স্থানান্তর প্রক্রিয়াটির সাথে আরও ভাল কাজ করবে।

হালনাগাদ

মূলত উপরের কোডটি ফাংশনটির অভ্যন্তরটির @SuppressWarningযেহেতু BufferedWriterপ্রয়োজনclose()

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

আবার আপডেট করুন

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

তাই সঠিকভাবে এই সমস্যা সমাধানের, আমরা একটি কাস্টমাইজড প্রয়োজন AutoClosableযে যখনই প্রচেষ্টা, নিম্নরেখা BufferedWriterহইবে flush()ইডি। প্রকৃতপক্ষে, এটি আমাদের সতর্কতাটিকে বাইপাস করার আরও একটি উপায় দেখায়, যেহেতু এটি BufferWriterকোনওভাবেই বন্ধ হয় না।


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

যদি ফোন flush()করার প্রয়োজন হয়, কলর যখন ফোনটি বন্ধ করার সিদ্ধান্ত নেবে তার আগেই এটি ঘটবে FileWriter। সুতরাং চেষ্টা ব্লকের printToFileকোনও ঠিক আগে হওয়া উচিত return। এটি কোনও অংশ হতে পারে না writeFileWriterএবং সুতরাং সতর্কতা সেই ফাংশনের অভ্যন্তরের কোনও বিষয় নয়, তবে সেই ফাংশনের কলার। আমাদের কাছে যদি কোনও টিকা থাকে তবে @LiftWarningToCaller("wanrningXXX")এটি এই কেস এবং অনুরূপটিকে সহায়তা করবে।
আর্থ ইঞ্জিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.