রুবিতে ফাইল পড়ার সমস্ত সাধারণ উপায় কী কী?


280

রুবিতে ফাইল পড়ার সমস্ত সাধারণ উপায় কী কী?

উদাহরণস্বরূপ, এখানে একটি পদ্ধতি:

fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
  puts(line)
end
fileObj.close

আমি জানি রুবি অত্যন্ত নমনীয়। প্রতিটি পদ্ধতির সুবিধা / ত্রুটিগুলি কী কী?


6
আমি মনে করি বর্তমান বিজয়ী উত্তরটি সঠিক নয়।
ইনজার

উত্তর:


259
File.open("my/file/path", "r") do |f|
  f.each_line do |line|
    puts line
  end
end
# File is closed automatically at end of block

উপরের মত স্পষ্টতই ফাইলটি বন্ধ করাও সম্ভব ( openএটি আপনার জন্য বন্ধ করে দেওয়ার জন্য একটি ব্লক পাস করুন ):

f = File.open("my/file/path", "r")
f.each_line do |line|
  puts line
end
f.close

14
এটি মুর্শিবাদী রুবি। এর foreachপরিবর্তে ব্যবহার করুন openএবং each_lineব্লকটি সরবরাহ করুন।
টিন ম্যান

7
f.each { |line| ... }এবং f.each_line { |line| ... }একই আচরণ বলে মনে হচ্ছে (কমপক্ষে রুবি ২.০.০ এ)।
chbrown

327

ফাইলটি খুব বেশি দীর্ঘ না হলে সবচেয়ে সহজ উপায় হ'ল:

puts File.read(file_name)

প্রকৃতপক্ষে, IO.readবা File.readস্বয়ংক্রিয়ভাবে ফাইলটি বন্ধ করুন, সুতরাং কোনও File.openব্লক ব্যবহার করার দরকার নেই ।


16
IO.readবা File.readস্বয়ংক্রিয়ভাবে ফাইলটি বন্ধ করে দিন, যদিও আপনার শব্দটি এটিকে শোনায় এমন করে তোলে যা না।
ফ্রোগজ

15
তিনি ইতিমধ্যে বলেছিলেন "যদি ফাইলটি খুব দীর্ঘ না হয়"। আমার মামলা পুরোপুরি মামলা।
জয়প

227

"স্লারপিং" ফাইলগুলি থেকে সাবধান থাকুন। আপনি যখন একবারে পুরো ফাইলটি মেমরিতে পড়েন তখনই।

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

লাইন বাই লাইন আই / ও খুব দ্রুত এবং প্রায় সবসময় স্লুর্পিংয়ের মতো কার্যকর। এটি আশ্চর্যজনকভাবে আসলে দ্রুত।

আমি ব্যবহার করতে চাই:

IO.foreach("testfile") {|x| print "GOT ", x }

অথবা

File.foreach('testfile') {|x| print "GOT", x }

ফাইলটি আইও থেকে উত্তরাধিকার সূত্রে প্রাপ্ত foreachএবং আইওতে রয়েছে, সুতরাং আপনি যে কোনওটি ব্যবহার করতে পারেন।

readবনাম লাইন বাই লাইন I / O এর মাধ্যমে বড় ফাইলগুলি পড়ার চেষ্টা করার প্রভাবের কিছুটা বেনমার্ক রয়েছে যা "ফাইলকে" স্লুরপিং "একটি ভাল অনুশীলন নয় কেন? "।


6
আমি ঠিক এটিই খুঁজছিলাম। আমি পাঁচ মিলিয়ন লাইনযুক্ত একটি ফাইল পেয়েছি, এবং সত্যই এটি চায়নি যে এটি মেমরিতে লোড।
স্কটি সি।

68

আপনি একবারে ফাইলটি পড়তে পারেন:

content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}

যখন ফাইলটি বড় হয় বা বড় হতে পারে তবে সাধারণত এটি লাইন-লাইন প্রক্রিয়াকরণ করা ভাল:

File.foreach( 'file.txt' ) do |line|
  puts line
end

কখনও কখনও আপনি ফাইল হ্যান্ডেল অ্যাক্সেস করতে চান বা নিজেই পড়েন:

File.open( 'file.txt' ) do |f|
  loop do
    break if not line = f.gets
    puts "#{f.lineno}: #{line}"
  end
end

বাইনারি ফাইলগুলির ক্ষেত্রে, আপনি নীল-বিভাজক এবং একটি ব্লক আকার নির্দিষ্ট করতে পারেন:

File.open('file.bin', 'rb') do |f|
  loop do
    break if not buf = f.gets(nil, 80)
    puts buf.unpack('H*')
  end
end

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

begin
  f = File.open 'file.txt'
  while line = f.gets
    puts line
  end
ensure
  f.close
end

তথ্যসূত্র: ফাইল এপিআই এবং আইও এপিআই


2
for_eachফাইল বা আইও-তে কোনও নেই । foreachপরিবর্তে ব্যবহার করুন।
টিন ম্যান

1
এখানে উত্তরগুলিতে ডকুমেন্টিং কোড ব্যবহার করার সময় আমি সাধারণত রুবিমার্কার্স প্লাগইন সহ সাবলাইম পাঠ্য সম্পাদকটি ব্যবহার করি। এটি আইআরবি ব্যবহারের অনুরূপ মধ্যবর্তী ফলাফলগুলি দেখানো সত্যিই সহজ করে তোলে। সাবলাইম টেক্সট 2 এর জন্য সিভিং ইজ বিশ্বাসী প্লাগইনটি সত্যিই শক্তিশালী।
টিন ম্যান

1
দুর্দান্ত উত্তর। শেষ উদাহরণের জন্য আমি এর whileপরিবর্তে loopব্যবহার ensureএবং ফাইলটি বন্ধ হয়ে যায় কিনা তা নিশ্চিত করার জন্য যদি কোনও ব্যতিক্রম উত্থাপিত হয় তবে তা ব্যবহার করার পরামর্শ দিতে পারি । এই মত (প্রতিস্থাপন নতুন লাইন দিয়ে আধা কোলন): begin; f = File.open('testfile'); while line = f.gets; puts line; end; ensure; f.close; end
এন্টিনোম

1
হ্যাঁ, এটি অনেক বেশি ভাল @ উত্তরোত্তর, উত্তরটির উন্নতি করেছে। ধন্যবাদ!
ভিক্টর ক্লোস

26

একটি সহজ পদ্ধতি ব্যবহার করা হয় readlines:

my_array = IO.readlines('filename.txt')

ইনপুট ফাইলের প্রতিটি লাইন অ্যারেতে প্রবেশ করবে। পদ্ধতিটি আপনার জন্য ফাইলটি খোলার এবং বন্ধ করতে পরিচালনা করে।


5
যেমন readবা কোনও ভেরিয়েন্ট হিসাবে এটি পুরো ফাইলটিকে মেমরিতে টানবে, যা ফাইল উপলব্ধ মেমরির চেয়ে বড় হলে বড় সমস্যা তৈরি করতে পারে। এছাড়াও এটি একটি অ্যারে হওয়ায় রুবিকে অ্যারে তৈরি করতে হবে, প্রক্রিয়াটি অতিরিক্তভাবে ধীর করে ফেলবে।
টিন ম্যান 21


9

আমি সাধারণত এটি করি:

open(path_in_string, &:read)

এটি আপনাকে স্ট্রিং অবজেক্ট হিসাবে পুরো পাঠ্যটি দেবে। এটি কেবল রুবি ১.৯ এর অধীনে কাজ করে।


এটি সুন্দর এবং সংক্ষিপ্ত! এটি কি ফাইলটি বন্ধ করে দেয়?
mrgreenfur

5
এটি এটিকে বন্ধ করে দেয় তবে এটি পরিমাপযোগ্য নয় তাই সাবধান হন।
টিন ম্যান


1

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

ফাইলের সামগ্রীতে বাফারিংয়ের মাধ্যমে, লজিকাল খণ্ডগুলিতে ফাইলটি বিভক্ত করার সময় I / O কলগুলির সংখ্যা হ্রাস পাবে।

উদাহরণ:

পরিষেবা ক্লাব হিসাবে এই অ্যাপ্লিকেশনটিতে এই শ্রেণিটি যুক্ত করুন:

class MyIO
  def initialize(filename)
    fd = IO.sysopen(filename)
    @io = IO.new(fd)
    @buffer = ""
  end

  def each(&block)
    @buffer << @io.sysread(512) until @buffer.include?($/)

    line, @buffer = @buffer.split($/, 2)

    block.call(line)
    each(&block)
  rescue EOFError
    @io.close
 end
end

এটিকে কল করুন এবং :eachপদ্ধতিটিকে একটি ব্লক পাস করুন :

filename = './somewhere/large-file-4gb.txt'
MyIO.new(filename).each{|x| puts x }

এই বিস্তারিত পোস্টে এটি সম্পর্কে এখানে পড়ুন:

রুবি ম্যাজিক স্লুরপিং এবং স্ট্রিমিং ফাইলগুলি অ্যাপসিসিনাল দ্বারা


সতর্কতা অবলম্বন করুন: যদি কোনও লাইনফিড (অন্তত লিনাক্সে) দিয়ে শেষ না হয় তবে কোডটি শেষ পংক্তিকে অগ্রাহ্য করবে।
জর্জেন

আমি মনে করি "@ io.close" এর আগে "block.call (@ বাফার)" সন্নিবেশ করানো অনুপস্থিত লাইনটি বেছে নেবে। তবে আমি কেবল একদিন রুবীর সাথে খেলেছি যাতে আমি ভুল হতে পারি। এটি আমার অ্যাপ্লিকেশনটিতে কাজ করেছে :)
জর্জেন

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

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

0
content = `cat file`

আমি মনে করি এই পদ্ধতিটি সবচেয়ে "অস্বাভাবিক" এক। হতে পারে এটি এক ধরণের কৌতুকজনক, তবে catইনস্টল করা থাকলে এটি কাজ করে ।


1
একটি সহজ কৌশল, তবে শেলের সাথে ডেকে আনা অনেক বিপত্তি রয়েছে যার মধ্যে রয়েছে ১) কমান্ডগুলি বিভিন্ন ওএসের সাথে পৃথক হতে পারে, ২) আপনার ফাইলের নাম থেকে ফাঁকা স্থানগুলি রক্ষা করতে হবে। রুবি অন্তর্নির্মিত ফাংশনগুলি ব্যবহার করে আপনি অনেক বেশি ভাল, যেমনcontent = File.read(filename)
জেফ ওয়ার্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.