Zeilenweise einlesen
Listing 1 erledigt eine typische Aufgabe im Zusamenhang mit Textdateien. Dabei geschieht die meiste Arbeit in der letzten Zeile: Sie liest eine Datei ein und zerteilt sie an den Newline-Zeichen – aber nur, falls die angegebene Datei überhaupt existiert. Der Code lässt sich zeilenweise an der interaktiven Ruby-Shell eingeben, die der Befehl »irb«
aufruft.
Listing 1
Zeilen einlesen
01 people_path = "/tmp/people.txt"
02
03 people = []
04 people = File.read(people_path).split("\n") if File.exists?(people_path)
Der Code wird plattformneutral, wenn man Rubys eingebaute Variable »$/«
für das Zeilenende verwendet. Diese dient auch als Trennzeichen der Methode »File.readlines()«
, die eine Datei gleichzeitig liest und in Zeilen aufteilt:
File.readlines(people_path)# => ["line1\n", "line2\n", ...]
Offenbar belässt »readlines()«
das Zeichen für das Zeilenende im Text, wie Abbildung 1 zeigt. So lässt sich das Zeichen entfernen:
File.readlines(people_path).map{ |line| line.chomp } Der obige Code verwendet eine Map, um jede Zeile durch einen Codeblock zu schicken. Da Ruby Koroutinen kennt und Funktionen als Bürger erster Klasse behandelt, erinnern die Programme oft an funktionale Programmierung.
Der Einzeiler lässt sich noch weiter kürzen, denn Ruby kennt eine Schreibweise, um eine benannte Funktion auf jedes Element einer Menge anzuwenden:
File.readlines(people_path).map(&:chomp)
Der bisherige Ansatz birgt allerdings ein Problem: Er setzt voraus, dass mehr Speicher zu Verfügung steht, als Daten eingelesen werden. Für Ad-hoc-Skripte mag es angehen, mit kompletten Dateien zu arbeiten, für ernsthafte Admin-Aufgaben ist es zu riskant. Besser ist es, die Daten Zeile für Zeile zu lesen und zu verarbeiten. Dazu eignet sich eine Koroutine:
File.foreach(people_path) do |line| # Zeile verarbeiten end
Die Methode »File.foreach()«
gibt einen so genannten Enumerator zurück, aus dem sich Element für Element verarbeiten lässt. Angenommen die verarbeitete Datei enthält einige sehr lange Zeilen, deren Zeichen der Ruby-Anwender zählen möchte. Dazu schreibt er:
character_counts = File.foreach(people_path).map(&:size)
Die Map-Methode entnimmt dem von »foreach()«
erzeugten Enumerator nur eine Zeile auf einmal, daher sollte sich auch nur jeweils eine Zeile im Speicher befinden. Liebhaber der funktionalen Programmierung kennen das als Lazy Evaluation. Das Programm wertet nur so viel aus, wie es gerade für den nächsten Schritt benötigt. In einer der nächsten Releases soll Ruby Unterstützung für lange Kommandoverkettungen mit mehreren Map- und Filter-Stufen bieten. Listing 2 zeigt die Verwendung von »File.open()«
. Es erzeugt ein Filehandle, ein Konzept, das Programmierer aus anderen Sprachen kennen. Der Modestring »"w"«
hat dabei dieselbe Bedeutung wie in C und öffnet die Datei zum Schreiben. Standardmäßig öffnet Ruby Dateien nur zum Lesen.
Listing 2
Filehandle
01 File.open(people_path, "w") do |f| 02 f.puts "john" # eine Zeile schreiben 03 f.puts "james", "george" # zwei Zeilen schreiben 04 f.print "anna" # 4 Zeichen ohne Newline 05 f.print "bel\n" # explizit Newline anfügen 06 end
Filehandles, Blocks und Verzeichnisse
Die Besonderheit von Listing 2 besteht darin, dass es das Filehandle an einen Codeblock übergibt. Das heißt, alles was im Block steht, passiert nur, wenn die Datei erfolgreich zum Schreiben geöffnet wurde. Am Ende das Blocks schließt Ruby die Datei automatisch.
Das »Dir«
-Modul dient dazu, Verzeichnisse zu lesen, anzulegen und so weiter. Listing 3 erstellt eine Liste aller C-Quelltextdateien im Arbeitsverzeichnis und sortiert sie nach dem »modified«
-Zeitstempel. Dabei kommt das von der Bash vertraute Globbing-Muster mit Asterisk zum Einsatz.
Listing 3
Dir
01 source_files = Dir["*.c"].select{|f| File.size(f) > 1024}.sort_by{|f| File.mtime(f)}
Der beschriebene Umgang mit Dateien lässt sich in der Ruby-Dokumentation unter den Klassennamen »File«
, »Dir«
, »IO«
und »Enumerator«
nachlesen. Daneben besitzt Ruby ein eingebautes Informationssystem, das sich auf der Kommandozeile mit »ri Schlagwort«
aufrufen lässt (Abbildung 2).
Für die aktuelle Version 1.9.x haben die Ruby-Entwickler dem Encoding eine Runderneuerung verpasst. Dieses Thema hat mehrere Aspekte: Die Kodierung der Skriptdateien selbst darf nun auch UTF-8 sein, was der Programmierer zu Beginn der Datei angeben muss:
#!/usr/bin/env ruby -w # encoding: UTF-8 utf8_string_literal = "André"
Außerdem geht es um den Zeichensatz der Ein- und Ausgaben. Hier ist es in der Regel empfehlenswert, die Standardkodierung des Betriebssystems zu verwenden:
ruby -e 'puts Encoding.default_external.name'
Daneben spielt noch das Encoding eine Rolle, das Ruby intern beim Verarbeiten der eingelesenen Zeichenketten einsetzt. Ein Blogeintrag des Ruby-Programmierers James Edward Gray behandelt alle Aspekte ausführlich [3].
Diesen Artikel als PDF kaufen
Express-Kauf als PDF
Umfang: 5 Heftseiten
Preis € 0,99
(inkl. 19% MwSt.)
Als digitales Abo
Weitere Produkte im Medialinx Shop »
Versandartikel
Onlineartikel
Alle Rezensionen aus dem Linux-Magazin
- Buecher/07 Bücher über 3-D-Programmierung sowie die Sprache Dart
- Buecher/06 Bücher über Map-Reduce und über die Sprache Erlang
- Buecher/05 Bücher über Scala und über Suchmaschinen-Optimierung
- Buecher/04 Bücher über Metasploit sowie über Erlang/OTP
- Buecher/03 Bücher über die LPI-Level-2-Zertifizierung
- Buecher/02 Bücher über Node.js und über nebenläufige Programmierung
- Buecher/01 Bücher über Linux-HA sowie über PHP-Webprogrammierung
- Buecher/12 Bücher über HTML-5-Apps sowie Computer Vision mit Python
- Buecher/11 Bücher über Statistik sowie über C++-Metaprogrammierung
- Buecher/10 Bücher zu PHP-Webbots sowie zur Emacs-Programmierung
Insecurity Bulletin
Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...





