2015-01-21 11 views
5

Die Datei-I/O-API in Phobos ist relativ einfach zu bedienen, aber im Moment habe ich das Gefühl, dass sie nicht gut in die D-Bereichsschnittstelle integriert ist.Wie erstelle ich einen lazy-evaluated Bereich aus einer Datei?

Ich könnte einen Bereich begrenzen, den gesamten Inhalt erstellen, indem Sie die gesamte Datei in ein Array zu lesen:

import std.file; 
auto mydata = cast(ubyte[]) read("filename"); 
processData(mydata); // takes a range of ubytes 

Aber diese eifrige Auswertung der Daten kann unerwünscht sein, wenn ich nur ein Datei-Header abrufen möge, für Beispiel. Der Parameter upTo löst dieses Problem nicht, wenn das Format der Datei einen Header variabler Länge oder ein anderes Element annimmt, das wir abrufen möchten. Es könnte sogar in der Mitte der Datei sein, und read zwingt mich, die gesamte Datei bis zu diesem Punkt zu lesen.

Aber tatsächlich gibt es Alternativen. , readln, und ganz besonders byChunk lassen Sie mich Datenstücke abrufen, bis ich das Ende der Datei erreiche, oder nur wenn ich aufhören will, die Datei zu lesen.

import std.stdio; 
File file("filename"); 
auto chunkRange = file.byChunk(1000); // a range of ubyte[]s 
processData(chunkRange); // oops! not expecting chunks! 

Aber jetzt habe ich die Komplexität des Umgangs mit fester Größe Datenblöcke, anstatt einen kontinuierlichen Bereich von Bytes eingeführt.

Also wie kann ich einen einfachen Eingabebereich von Bytes aus einer Datei erstellen, die faul ausgewertet wird, entweder durch Zeichen oder durch kleine Chunks (um die Anzahl der Lesevorgänge zu reduzieren)? Kann der Bereich im zweiten Beispiel nahtlos gekapselt werden, so dass die Daten wie im ersten Beispiel verarbeitet werden können?

Antwort

7

können Sie std.algorithm.joiner verwenden:

auto r = File("test.txt").byChunk(4096).joiner(); 

Beachten Sie, dass byChunk für jeden Chunk den gleichen Puffer wieder verwendet, so können Sie .map!(chunk => chunk.idup) hinzufügen müssen träge auf dem Heap die Stücke zu kopieren.

+0

Das scheint zu funktionieren, ohne jedes Stück auf seinen eigenen Speicherraum abzubilden. Schließlich erwartet ein 'InputRange' bereits sequenzielles einmaliges Lesen. Können Sie sich einen Fall vorstellen, in dem das wirklich nötig ist? –

+0

Vielleicht wird es nie gebraucht wie du sagst. –