Frage

Ich Schreibe dieses kleine "HelloWorld" als follow-up zu diese und die zahlen addieren sich nicht

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}"

Das Ergebnis ist nicht das gleiche wie die Größe der Datei.Ich glaube, ich muss nur wissen, was format Ich Notwendigkeit, plug in...oder vielleicht habe ich den Punkt verpasst ganz. Wie kann ich Messen die Größe der Datei Zeile für Zeile?

Hinweis:Ich bin auf Windows und die Datei codiert ist als Typ ANSI.

Edit: Dies ergibt die gleichen Ergebnisse!

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}"

also wer kann jetzt helfen...

War es hilfreich?

Lösung

IO - #bekommt funktioniert genauso wie wenn Sie waren erfassen Eingang von der Befehlszeile aus:die "Enter" - ist nicht geschickt, als Teil des input;es ist auch bestanden, wenn #wird aufgefordert, eine Datei oder eine andere Unterklasse von IO -, also die zahlen sind definitiv nicht zu passen.

Siehe die entsprechenden Spitzhacke Abschnitt

Darf ich Fragen, warum Sie so besorgt sind die Leitungslängen addieren, die Größe der Datei?Sie können der Lösung schwieriger Probleme als nötig ist...

Aha.Ich denke, ich bekomme es jetzt.

Fehlt eine handliche iPod (oder jede andere Sorte, für diese Angelegenheit), ich weiß nicht, ob Sie genau möchten 4K-Blöcken, in welchem Fall IO#Lesen(4000) würde dein Freund sein (4000 4096?) oder wenn Sie glücklicher sind, brechen durch die Linie, in dem Fall so etwas sollte funktionieren:

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

Beachten Sie die Verwendung von IO#readlines um den gesamten text in einem slurp:#oder #each_line nicht genauso gut wäre.Ich verwendete String#chomp!um sicherzustellen, dass alles, was das Betriebssystem ist dabei, die byts am Ende wieder entfernt, so dass oder was auch immer, gezwungen werden in die Ausgabe.

Ich würde vorschlagen, mit Datei#schreiben, eher als #print oder #setzt für den Ausgang, als die letzteren haben eine Tendenz, zu liefern, OS-spezifische newline-Sequenzen.

Wenn Sie wirklich besorgt über die multi-byte-Zeichen, in Betracht ziehen, die each_byte oder entpacken(C*), Optionen und monkey-patching String, so etwas wie dieses:

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

Entpacken-version ist etwa 8-mal schneller als die each_byte auf meiner Maschine, btw.

Andere Tipps

Sie könnten versuchen, IO # each_byte, z.

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}"

Das ist natürlich, Sie zu einer Zeit, eine Linie nicht geben. Ihre beste Möglichkeit dafür ist wahrscheinlich durch die Datei über each_byte gehen, bis Sie \r\n begegnen. Die IO-Klasse bietet eine Reihe von ziemlich Low-Level-Lesemethoden, die hilfreich sein könnten.

Sie haben möglicherweise mehrere überlappende Probleme hier:

  1. Linefeeds \r\n vs. \n (wie pro Ihre früheren Post). Auch EOF-Datei Zeichen (^ Z)?

  2. Definition von „Größe“ in der Problemstellung: meinst du „wie viele Zeichen“ (unter Berücksichtigung der Multi-Byte-Zeichenkodierungen) oder meinst du „wie viele Bytes“

  3. Die Interaktion der $KCODE globalen Variable (veraltet in Ruby 1.9. Siehe String#encoding und Freunde, wenn Sie unter 1.9 laufen lassen). Gibt es zum Beispiel Zeichen mit Akzent in der Datei?

  4. Ihr Format-String für #unpack. Ich glaube, Sie wollen hier C* wenn Sie wirklich Bytes wollen zählen.

Beachten Sie auch die Existenz von IO#each_line (nur so können Sie die while wegwerfen kann und sein ein wenig mehr rubin idiomatische; -)).

Das Problem ist, dass, wenn Sie eine Textdatei auf Windows speichern, Ihre Zeilenumbrüche sind zwei Zeichen (Zeichen 13 und 10) und damit 2 Bytes, wenn Sie es auf Linux sparen gibt es nur 1 (Zeichen 10). Allerdings Rubin berichtet sowohl diese als ein einzelnes Zeichen ‚\ n‘ -. Es sagt Charakter 10. Was noch schlimmer ist, ist, dass, wenn Sie auf Linux mit einer Windows-Datei sind, rubin Ihnen beiden Zeichen geben

Also, wenn Sie auf wissen , dass Ihre Dateien immer aus den Fenstern Textdateien und ausgeführt werden, kommen auf Fenster, jedes Mal wenn ein Newline-Zeichen erhalten Sie 1 zu Ihrer Zählung hinzufügen können. Ansonsten ist es ein paar conditionals und eine wenig Zustandsmaschine.

BTW es gibt keinen 'Charakter' EOF.

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

Hier ist eine einfache Lösung, vorausgesetzt, dass die aktuellen Dateizeiger auf den Anfang einer Zeile in der Lesedatei festgelegt ist:

    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)

in diesem Beispiel „Datei“ die Datei, von der Sie gerade lesen. Um dies zu tun in einer Schleife:

    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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top