কোনও নিউলাইন ফর্ম্যাটের স্ট্রিংয়ে না থাকলে কেন কলটির পরে প্রিন্টফ ফ্লাশ করবে না?


538

printfকোনও নিউলাইন ফর্ম্যাটের স্ট্রিং না থাকলে কল করার পরে কেন ফ্লাশ হবে না? এই POSIX আচরণ? আমি কীভাবে printfপ্রতিবার সঙ্গে সঙ্গে ফ্লাশ করতে পারি ?


2
আপনি কি অনুসন্ধান করেছেন যে এটি কোনও ফাইলের সাথে ঘটে বা কেবল টার্মিনালের সাথে? যে যদিও আমি আশা এটি প্রযোজ্য হবে না একটি চালাক টার্মিনাল একটি ব্যাকগ্রাউন্ড প্রোগ্রাম থেকে আউটপুট অসমাপ্ত লাইন না বৈশিষ্ট্য হতে শব্দ, হবে ফোরগ্রাউন্ড প্রোগ্রাম।
পাইপব্রোস

7
Cygwin ব্যাশ অধীনে আমি এই একই অশোভন আচরণ এমনকি যদি একটি newline দেখছি হয় বিন্যাস স্ট্রিং। এই সমস্যাটি উইন্ডোজ 7 এ নতুন; একই উত্স কোডটি উইন্ডোজ এক্সপিতে দুর্দান্ত কাজ করেছে। এমএস সেমিডি.এক্স.ই প্রত্যাশার মতো ফ্লাশ করে। এই setvbuf(stdout, (char*)NULL, _IONBF, 0)সমস্যাটি চারপাশে কাজ করে তবে অবশ্যই প্রয়োজনীয় হওয়া উচিত ছিল না। আমি এমএসভিসি ++ ২০০ এক্সপ্রেস ব্যবহার করছি। ~~~
স্টিভ পিচারস

9
প্রশ্নের শিরোনাম স্পষ্ট করার জন্য: নিজে printf(..) কোনও ফ্লাশিং করবেন না , stdoutএকটি নতুন লাইন দেখলে (এটি যদি লাইন-বাফারযুক্ত থাকে) ফ্লাশ হতে পারে the এটি একইভাবে প্রতিক্রিয়া জানায় putchar('\n');, তাই printf(..)এই ক্ষেত্রে বিশেষ নয়। এটি তার বিপরীতে cout << endl;, ডকুমেন্টেশনগুলির মধ্যে উল্লেখযোগ্যভাবে ফ্লাশিংয়ের উল্লেখ রয়েছে। Printf, ডকুমেন্টেশন এ সব অনিদ্রা উল্লেখ নেই।
এভেজেনি সার্জিভ

1
লিখন (/ ফ্লাশিং) সম্ভবত ব্যয়বহুল অপারেশন, সম্ভবত এটি কার্য সম্পাদনের কারণে বাফার হয়েছে।
হানশেনেরিক

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

উত্তর:


701

stdoutপ্রবাহ লাইন ডিফল্টরূপে বাফার হয়, তাই শুধুমাত্র প্রদর্শন করা হবে কি বাফারে এর পরে এটি একটি newline ছুঁয়েছে (অথবা যখন এটি করতে বলা হয়েছে)। অবিলম্বে মুদ্রণের জন্য আপনার কাছে কয়েকটি বিকল্প রয়েছে:

এ মুদ্রণ করুন stderrপরিবর্তে ব্যবহার fprintf( stderrহয় ডিফল্টরূপে unbuffered ):

fprintf(stderr, "I will be printed immediately");

আপনার যখনই এটি ব্যবহারের প্রয়োজন হবে তখন ফ্লাশ স্টডআউট fflush:

printf("Buffered, will be flushed");
fflush(stdout); // Will now print everything in the stdout buffer

সম্পাদনা করুন : নীচে অ্যান্ডি রস এর মন্তব্য থেকে আপনি স্টাডআউট ব্যবহার করে বাফারিং অক্ষম করতে পারেন setbuf:

setbuf(stdout, NULL);

266
বা, পুরোপুরি বাফারিং অক্ষম করতে:setbuf(stdout, NULL);
অ্যান্ডি রস

80
এছাড়াও, কেবল উল্লেখ করতে চেয়েছিলেন যে স্পষ্টতই ইউনিক্সে একটি নতুন লাইন সাধারণত বাফারটি ফ্লাশ করবে যদি স্ট্ডআউট একটি টার্মিনাল হয়। যদি আউটপুট কোনও ফাইলে পুনঃনির্দেশ করা হয় তবে একটি নতুন লাইন ফ্লাশ হবে না।
হোরা

5
আমি যে আমি যোগ করা উচিত মনে: আমি শুধুমাত্র এই তত্ত্ব পরীক্ষা করে থাকেন, আর আমি খোঁজার করছি যে ব্যবহার setlinebuf()একটি স্ট্রিম টার্মিনাল নির্দেশ হয়নি এমন হয় প্রতিটি লাইনে শেষে অনিদ্রা।
ডডি

8
"শুরুতে খোলার সাথে সাথে স্ট্যান্ডার্ড ত্রুটি স্ট্রিমটি পুরোপুরি বাফার হয় না; স্ট্যান্ডটি কোনও ইন্টারেক্টিভ ডিভাইসকে উল্লেখ না করার জন্য যদি স্ট্রিমটি নির্ধারণ করা যায় তবে কেবল স্ট্যান্ডার্ড ইনপুট এবং স্ট্যান্ডার্ড আউটপুট স্ট্রিমগুলি পুরোপুরি বাফার হবে" - এই প্রশ্নটি দেখুন: stackoverflow.com / প্রশ্নগুলি / 5229096 /…
সেপ্পো এনার্ভি

3
@ রদ্দজউলিনস্কি যদি এটি "কেন এটি মুদ্রণ করছে না" এর একটি ভাল ক্যানন উত্তর হতে চলেছে তবে "টেক্সটটি কি সর্বদা একটি নতুন লাইনের মুখোমুখি হওয়ার সময় বাফারটি ফ্লাশ করে?" সরাসরি এই অতি উত্তেজিত উত্তরে, বনাম লোকেরা মন্তব্যগুলি পড়ার প্রয়োজন ...
হোস্টাইলফোর্ক বলেছেন যে এস

128

না, এটা POSIX আচরণ নয়, এটা আইএসও আচরণ (ভাল, এটি হল POSIX আচরণ কিন্তু শুধুমাত্র যতটুকু তারা আইএসও সাথে সামঞ্জস্য)।

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

myprog >myfile.txt

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

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

কীভাবে এটি মোকাবেলা করতে হয়, আপনি যদি fflush (stdout)প্রতিটি আউটপুট কল করার পরে কল করে থাকেন যে আপনি অবিলম্বে দেখতে চান, এটি সমস্যার সমাধান করবে।

বিকল্পভাবে, setvbufঅপারেট করার আগে stdoutআপনি এটি অপ্রয়োজনীয়তে সেট করতে ব্যবহার করতে পারেন এবং আপনার কোডটিতে এই সমস্ত fflushলাইন যুক্ত করার বিষয়ে আপনাকে চিন্তা করতে হবে না :

setvbuf (stdout, NULL, _IONBF, BUFSIZ);

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

আইএসও সি 99 বিভাগটি 7.19.3/3প্রাসঙ্গিক বিট:

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

যখন একটি স্ট্রিম পুরোপুরি বাফার হয় , বাফারগুলি পূর্ণ হয়ে গেলে অক্ষরগুলি হোস্ট পরিবেশে বা একটি ব্লক হিসাবে স্থানান্তরিত করার উদ্দেশ্যে হয়।

যখন একটি স্ট্রিম লাইন বাফার হয় , অক্ষরগুলি যখন একটি নতুন-লাইন চরিত্রের মুখোমুখি হয় তখন একটি হোস্ট হিসাবে হোস্ট পরিবেশে বা থেকে একটি ব্লক হিসাবে প্রেরণ করা হয়।

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

এই বৈশিষ্ট্যগুলির জন্য সমর্থন বাস্তবায়ন-সংজ্ঞায়িত এবং এটি setbufএবং setvbufক্রিয়াকলাপগুলির মাধ্যমে প্রভাবিত হতে পারে ।


8
আমি সবেমাত্র এমন একটি দৃশ্যের মুখোমুখি হয়েছি যেখানে একটি '\ n' রয়েছে, প্রিন্টফ () ফ্লাশ হয় না। আপনি এখানে উল্লিখিত হিসাবে এটি একটি fflush (stdout) যোগ করে কাটিয়ে উঠেছে। তবে আমি কেন আশ্চর্য হয়েছি যে '\ n' প্রিন্টফে () বাফারে ফ্লাশ করতে ব্যর্থ হয়েছিল।
কিয়াং শু

11
@ কিয়াংএক্সু, স্ট্যান্ডার্ড আউটপুটটি কেবলমাত্র সেই ক্ষেত্রেই লাইফ বাফার হয় যেখানে কোনও ইন্টারেক্টিভ ডিভাইসকে উল্লেখ করার জন্য এটি দৃitive়ভাবে নির্ধারণ করা যেতে পারে। সুতরাং, উদাহরণস্বরূপ, আপনি যদি আউটপুট এর সাথে পুনর্নির্দেশ করেন তবে myprog >/tmp/tmpfileলাইন বাফার করার পরিবর্তে এটি পুরোপুরি বাফার হয়। স্মৃতি থেকে, আপনার স্ট্যান্ডার্ড আউটপুট ইন্টারেক্টিভ কিনা তা নিয়ে দৃ determination় সংকল্পটি বাস্তবায়নের জন্য রেখে গেছে।
paxdiablo

3
: উপরন্তু উইন্ডোজ কলিং setvbuf উপর (...., _IOLBF) _IOLBF কাজ না সেখানে _IOFBF হিসাবে একই হবে msdn.microsoft.com/en-us/library/86cebhfs.aspx
পাযত্র Lopusiewicz

28

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

program A output
program B output
program B output
program A output
program B output

এই দুর্গন্ধযুক্ত, কিন্তু এটি চেয়ে ভাল

proprogrgraam m AB  ououtputputt
prproogrgram amB A  ououtputtput
program B output

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


26

তাত্ক্ষণিকভাবে ফোন ফ্লাশ করতে fflush(stdout)বা fflush(NULL)( NULLঅর্থাত্ ফ্লাশ করার অর্থ)।


31
মনে রাখবেন fflush(NULL);সাধারণত খুব খারাপ ধারণা is যদি আপনার অনেকগুলি ফাইল খোলা থাকে তবে এটি কার্যকারিতা হ্রাস করবে, বিশেষত একটি বহু-থ্রেড পরিবেশে যেখানে আপনি লকের জন্য সমস্ত কিছু দিয়ে লড়াই করবেন।
আর .. গীটহাব বন্ধ করুন ICE

14

দ্রষ্টব্য: মাইক্রোসফ্ট রানটাইম লাইব্রেরিগুলি লাইন বাফারিং সমর্থন করে না, তাই printf("will print immediately to terminal"):

https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/setvbuf


3
চেয়ে খারাপ printf"স্বাভাবিক" ক্ষেত্রে টার্মিনালে অবিলম্বে যাচ্ছে যে হয় printfএবং fprintfআরো স্থূলভাবে ক্ষেত্রে যেখানে তাদের আউটপুট অবিলম্বে ব্যবহারের রাখা হয় এমনকি বাফার দেখায়। এমএস যদি নির্দিষ্ট জিনিসগুলি নির্দিষ্ট না করে থাকে তবে এটি কোনও প্রোগ্রামের পক্ষে অন্যটির কাছ থেকে স্ট্ডার এবং স্টাডআউট ক্যাপচার করা এবং প্রতিটিটিতে কী ক্রমগুলি প্রেরণ করা হয়েছিল তা সনাক্ত করা অসম্ভব করে তোলে।
সুপারক্যাট

না, কোনও বাফারিং সেট না করা থাকলে এটি অবিলম্বে টার্মিনালে মুদ্রণ করে না। ডিফল্টরূপে সম্পূর্ণ বাফারিং ব্যবহৃত হয়
ফুলচলভি

12

stdout বাফার করা হয়, সুতরাং একটি নতুন লাইন মুদ্রণের পরে কেবল আউটপুট হবে।

অবিলম্বে আউটপুট পেতে, হয়:

  1. Stderr মুদ্রণ।
  2. স্ট্যাডআউট আনফফার্ড করুন।

10
বা fflush(stdout)
রাস্তাজেদি

2
"সুতরাং নতুন লাইনটি মুদ্রণের পরে কেবল আউটপুট পাওয়া যাবে।" শুধু এটিই নয় অন্য অন্তত 4 টি মামলা। পূর্ণ, লেখ বাফার stderr(এই উত্তর পরে উল্লেখ), fflush(stdout), fflush(NULL)
chux - মনিকা

11

ডিফল্টরূপে, স্ট্ডআউট লাইন বাফার হয়, স্ট্যাডার কোনওটিই বাফার হয় না এবং ফাইলটি সম্পূর্ণ বাফার হয়।


10

পরিবর্তে আপনি স্টার্ডার এফপ্রিন্ট করতে পারেন, যা পরিবর্তিত is অথবা আপনি চাইলে স্টডআউট ফ্লাশ করতে পারেন। অথবা আপনি স্টাফাউট আনফফার্ড সেট করতে পারেন।



2

সাধারণত 2 স্তরের বাফারিং রয়েছে-

1. কার্নেল বাফার ক্যাশে (দ্রুত পড়তে / লিখতে সক্ষম করে)

২ / আই লাইব্রেরিতে বাফারিং (সিস্টেম কলগুলির সংখ্যা কমায়)

এর উদাহরণ নেওয়া যাক fprintf and write()

আপনি যখন কল করবেন তখন fprintf()এটি সরাসরি ফাইলে যায় না। এটি প্রোগ্রামের স্মৃতিতে প্রথমে স্টডিও বাফারে যায়। সেখান থেকে এটি লিখুন সিস্টেম কল ব্যবহার করে কার্নেল বাফার ক্যাশে লেখা হয়। সুতরাং I / O বাফার এড়িয়ে যাওয়ার একটি উপায় সরাসরি রাইট () ব্যবহার করে। অন্যান্য উপায় ব্যবহার করে হয় setbuff(stream,NULL)। এটি বাফারিং মোডকে কোনও বাফারিংয়ে সেট করে এবং ডেটা সরাসরি কার্নেল বাফারে লিখিত হয়। জোর করে ডেটা কার্নেল বাফারে স্থানান্তরিত করতে, আমরা "\ n" ব্যবহার করতে পারি, যা 'লাইন বাফারিং' এর ডিফল্ট বাফারিং মোডের ক্ষেত্রে I / O বাফারটি ফ্লাশ করবে। বা আমরা ব্যবহার করতে পারেন fflush(FILE *stream)

এখন আমরা কার্নেল বাফারে রয়েছি। কার্নেল (/ ওএস) ডিস্ক অ্যাক্সেসের সময়কে হ্রাস করতে চায় এবং তাই এটি কেবল ডিস্কের ব্লকগুলি পড়তে / লেখায় writes সুতরাং যখন একটিread() জারি করা হয়, যা একটি সিস্টেম কল এবং সরাসরি বা মাধ্যমে আহ্বান করা যেতে পারে fscanf(), কার্নেল ডিস্ক থেকে ডিস্ক ব্লকটি পড়ে এবং এটি একটি বাফারে সঞ্চয় করে। এর পরে ব্যবহারকারী স্থান থেকে ডেটা অনুলিপি করা হয়।

একইভাবে fprintf() আই / ও বাফার থেকে প্রাপ্ত তথ্যটি কার্নেলের দ্বারা ডিস্কে লেখা হয়। এটি পড়তে () লেখার () দ্রুত করে তোলে।

এখন কার্নেলটিকে একটি শুরু করতে বাধ্য করা write(), যার পরে ডেটা ট্রান্সফারটি হার্ডওয়্যার নিয়ন্ত্রণকারীরা দ্বারা নিয়ন্ত্রিত হয়, এর কয়েকটি উপায় রয়েছে। O_SYNCকল কল করার সময় আমরা একই জাতীয় পতাকা ব্যবহার করতে পারি । অথবা আমরা অন্যান্য ফাংশন ব্যবহার করতে পারি যেমন fsync(),fdatasync(),sync()কার্নেল বাফারে ডেটা উপলব্ধ হওয়ার সাথে সাথে কার্নেল সূচনা লিখতে শুরু করে।

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