سؤال

أنا أكتب هذا القليل HelloWorld مثل متابعة هذا والأرقام لا تضيف ما يصل

filename = "testThis.txt"
total_bytes = 0
file = File.new(filename, "r")
file.each do |line|
  total_bytes += line.unpack("U*").length
end
puts "original size #{File.size(filename)}"
puts "Total bytes #{total_bytes}"

والنتيجة ليست نفس حجم الملف.أعتقد أنا فقط بحاجة إلى معرفة ما format أنا بحاجة إلى المكونات في...أو ربما كنت قد غاب عن هذه النقطة تماما. كيف يمكن قياس حجم ملف الخط الخط ؟

ملاحظة:أنا على ويندوز و يتم ترميز الملف بنوع ANSI.

تحرير: وهذا ينتج نفس النتائج!

filename = "testThis.txt"
total_bytes = 0
file = File.new(filename, "r")
file.each_byte do |whatever|
  total_bytes += 1
end
puts "Original size #{File.size(filename)}"
puts "Total bytes #{total_bytes}"

لذلك أي شخص يمكن أن تساعد الآن...

هل كانت مفيدة؟

المحلول

IO#يحصل يعمل نفس الشيء كما لو كنت التقاط المدخلات من سطر الأوامر:"أدخل" لا يتم إرسالها كجزء من المدخلات ؛ ولا مرت عند #يحصل على ملف أو أخرى فرعية من IO ، وبالتالي فإن الأرقام هي بالتأكيد لن تصل المباراة.

رؤية ذات الصلة معول القسم

أود الاستفسار لماذا أنت قلقة بشأن أطوال خط تلخيص إلى حجم الملف ؟ قد يكون حل أصعب مشكلة مما هو ضروري...

اها.أعتقد أنني أفهم الآن.

تفتقر مفيد بود (أو أي نوع آخر لهذه المسألة), أنا لا أعرف إذا كنت تريد بالضبط 4K قطع, في هذه الحالة IO#قراءة(4000) سيكون صديقك (4000 أو 4096?) أو إذا كنت أكثر سعادة لكسر الخط ، وفي هذه الحالة شيئا من هذا القبيل يجب أن تعمل:

class Chunkifier
  def Chunkifier.to_chunks(path)
    chunks, current_chunk_size = [""], 0
    File.readlines(path).each do |line|
      line.chomp! # strips off \n, \r or \r\n depending on OS
      if chunks.last.size + line.size >= 4_000 # 4096?
        chunks.last.chomp! # remove last line terminator
        chunks << ""
      end
      chunks.last << line + "\n" # or whatever terminator you need
    end
    chunks
  end
end

if __FILE__ == $0
  require 'test/unit'
  class TestFile < Test::Unit::TestCase
    def test_chunking
      chs = Chunkifier.to_chunks(PATH)
      chs.each do |chunk|
        assert 4_000 >= chunk.size, "chunk is #{chunk.size} bytes long"
      end
    end
  end
end

لاحظ استخدام IO#readlines للحصول على كل النص في ملتهم:#أو #each_line أن تفعل كذلك.اعتدت سلسلة#chomp!للتأكد من أن أيا كان نظام التشغيل ، byts في النهاية يتم إزالتها ، بحيث أو أيا كان يمكن أن يضطر إلى الإخراج.

أود أن أقترح استخدام ملف#كتابة بدلا من #طباعة أو #يضع على الإخراج ، لأن هذه الأخيرة تميل إلى تقديم نظام التشغيل الخاصة السطر متواليات.

إذا كنت قلقا حقا حول أحرف متعددة البايت ، والنظر في اتخاذ each_byte أو فك(ج*) خيارات و القرد-الترقيع سلسلة شيئا من هذا القبيل:

class String
  def size_in_bytes
    self.unpack("C*").size
  end
end

Unpack نسخة عن 8 مرات أسرع من each_byte واحد على الجهاز الخاص بي ، راجع للشغل.

نصائح أخرى

قد تحاول IO#each_byte مثلا

total_bytes = 0
file_name = "test_this.txt"
File.open(file_name, "r") do |file|
  file.each_byte {|b| total_bytes += 1}
end
puts "Original size #{File.size(file_name)}"
puts "Total bytes #{total_bytes}"

هذا بالطبع لا تعطيك خط في وقت واحد.افضل خيار لك هو من المحتمل أن تذهب من خلال الملف عن طريق each_byte حتى واجهت \r\n.IO الدرجة يوفر مجموعة جميلة انخفاض مستوى قراءة الأساليب التي قد تكون مفيدة.

هل يحتمل أن يكون العديد من القضايا المتداخلة هنا:

  1. آلية الشخصيات \r\n مقابل \n (كما في رسالتك السابقة).أيضا EOF ملف شخصية (^Z)?

  2. تعريف "حجم" في بيان المشكلة:تعني "كيف العديد من الشخصيات" (مع الأخذ بعين الاعتبار متعدد البايت ترميزات) أو تعني "كم بايت"?

  3. تفاعل $KCODE عالمي متغير (إهمال في روبي 1.9.انظر String#encoding والأصدقاء إذا كنت تعمل تحت 1.9).هناك ، على سبيل المثال ، أحرف معلمة في ملفك ؟

  4. الخاص بك شكل سلسلة #unpack.أعتقد أنك تريد C* هنا إذا كنت تريد حقا أن عدد وحدات البايت.

نلاحظ أيضا وجود IO#each_line (فقط حتى يمكنك رمي بعيدا while و يكون قليلا أكثر روبي-الاصطلاحية ;-)).

المشكلة هي أنه عند حفظ ملف نصي على ويندوز الخاص بك فواصل الأسطر نوعان من الأحرف (أحرف 13 و 10) ولذلك 2 بايت عند حفظه على لينكس لا يوجد سوى 1 (حرف 10).ومع ذلك, روبي تقارير كل هذه كحرف واحد ' ' - يقول حرف 10.ما هو أسوأ من ذلك ، هو أنه إذا كنت على لينكس مع ويندوز ملف روبي سوف تعطيك كل الشخصيات.

لذا ، إذا كنت أعلم أن الملفات الخاصة بك تأتي دائما من ويندوز وملفات نصية أعدم على النوافذ في كل مرة تحصل على حرف السطر الجديد يمكنك إضافة 1 إلى العدد.وإلا فإنه بضعة من الشرطية قليلا آلة الدولة.

BTW لا يوجد EOF 'حرف'.

f = File.new("log.txt")
begin
    while (line = f.readline)
        line.chomp
        puts line.length
    end
rescue EOFError
    f.close
end

هنا حل بسيط ، على افتراض ان الملف الحالي المؤشر هو بداية خط في قراءة الملف:

    last_pos = file.pos
    next_line = file.gets
    current_pos = file.pos
    backup_dist = last_pos - current_pos
    file.seek(backup_dist, IO::SEEK_CUR)

في هذا المثال "ملف" هو الملف الذي كنت تقرأ.للقيام بذلك في حلقة:

    last_pos = file.pos
    begin loop
        next_line = file.gets
        current_pos = file.pos
        backup_dist = last_pos - current_pos
        last_pos = current_pos
        file.seek(backup_dist, IO::SEEK_CUR)
    end loop
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top