// Written in the D programming language. /**Utilities for manipulating files and scanning directories. Functionsin this module handle files as a unit, e.g., read or write one fileat a time. For opening files and manipulating them via handles referto module $(MREF std, stdio). $(SCRIPT inhibitQuickIndex = 1;)$(DIVC quickindex,$(BOOKTABLE,$(TR $(TH Category) $(TH Functions))$(TR $(TD General) $(TD $(LREF exists) $(LREF isDir) $(LREF isFile) $(LREF isSymlink) $(LREF rename) $(LREF thisExePath)))$(TR $(TD Directories) $(TD $(LREF chdir) $(LREF dirEntries) $(LREF getcwd) $(LREF mkdir) $(LREF mkdirRecurse) $(LREF rmdir) $(LREF rmdirRecurse) $(LREF tempDir)))$(TR $(TD Files) $(TD $(LREF append) $(LREF copy) $(LREF read) $(LREF readText) $(LREF remove) $(LREF slurp) $(LREF write)))$(TR $(TD Symlinks) $(TD $(LREF symlink) $(LREF readLink)))$(TR $(TD Attributes) $(TD $(LREF attrIsDir) $(LREF attrIsFile) $(LREF attrIsSymlink) $(LREF getAttributes) $(LREF getLinkAttributes) $(LREF getSize) $(LREF setAttributes)))$(TR $(TD Timestamp) $(TD $(LREF getTimes) $(LREF getTimesWin) $(LREF setTimes) $(LREF timeLastModified) $(LREF timeLastAccessed) $(LREF timeStatusChanged)))$(TR $(TD Other) $(TD $(LREF DirEntry) $(LREF FileException) $(LREF PreserveAttributes) $(LREF SpanMode) $(LREF getAvailableDiskSpace))))) Copyright: Copyright The D Language Foundation 2007 - 2011.See_Also: The $(HTTP ddili.org/ders/d.en/files.html, official tutorial) for anintroduction to working with files in D, module$(MREF std, stdio) for opening files and manipulating them via handles,and module $(MREF std, path) for manipulating path strings. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).Authors: $(HTTP digitalmars.com, Walter Bright), $(HTTP erdani.org, Andrei Alexandrescu), $(HTTP jmdavisprog.com, Jonathan M Davis)Source: $(PHOBOSSRC std/file.d) */module std.file; import core.stdc.errno, core.stdc.stdlib, core.stdc.string;import core.time : abs, dur, hnsecs, seconds; import std.datetime.date : DateTime;import std.datetime.systime : Clock, SysTime, unixTimeToStdTime;import std.internal.cstring;import std.meta;import std.range;import std.traits;import std.typecons; version (OSX) version = Darwin;else version (iOS) version = Darwin;else version (TVOS) version = Darwin;else version (WatchOS) version = Darwin; version (Windows){ import core.sys.windows.winbase, core.sys.windows.winnt, std.windows.syserror;}else version (Posix){ import core.sys.posix.dirent, core.sys.posix.fcntl, core.sys.posix.sys.stat, core.sys.posix.sys.time, core.sys.posix.unistd, core.sys.posix.utime;}else static assert(false, "Module " ~ .stringof ~ " not implemented for this OS."); // Character type used for operating system filesystem APIsversion (Windows){ private alias FSChar = WCHAR; // WCHAR can be aliased to wchar or wchar_t}else version (Posix){ private alias FSChar = char;}else static assert(0); // Purposefully not documented. Use at your own risk@property string deleteme() @safe{ import std.conv : text; import std.path : buildPath; import std.process : thisProcessID; enum base = "deleteme.dmd.unittest.pid"; static string fileName; if (!fileName) fileName = text(buildPath(tempDir(), base), thisProcessID); return fileName;} version (StdUnittest) private struct TestAliasedString{ string get() @safe @nogc pure nothrow return scope { return _s; } alias get this; @disable this(this); string _s;} version (Android){ package enum system_directory = "/system/etc"; package enum system_file = "/system/etc/hosts";}else version (Posix){ package enum system_directory = "/usr/include"; package enum system_file = "/usr/include/assert.h";} /++ Exception thrown for file I/O errors. +/class FileException : Exception{ import std.conv : text, to; /++ OS error code. +/ immutable uint errno; private this(scope const(char)[] name, scope const(char)[] msg, string file, size_t line, uint errno) @safe pure { if (msg.empty) super(name is null ? "(null)" : name.idup, file, line); else super(text(name is null ? "(null)" : name, ": ", msg), file, line); this.errno = errno; } /++ Constructor which takes an error message. Params: name = Name of file for which the error occurred. msg = Message describing the error. file = The file where the error occurred. line = The _line where the error occurred. +/ this(scope const(char)[] name, scope const(char)[] msg, string file = __FILE__, size_t line = __LINE__) @safe pure { this(name, msg, file, line, 0); } /++ Constructor which takes the error number ($(LUCKY GetLastError) in Windows, $(D_PARAM errno) in POSIX). Params: name = Name of file for which the error occurred. errno = The error number. file = The file where the error occurred. Defaults to `__FILE__`. line = The _line where the error occurred. Defaults to `__LINE__`. +/ version (Windows) this(scope const(char)[] name, uint errno = .GetLastError(), string file = __FILE__, size_t line = __LINE__) @safe { this(name, generateSysErrorMsg(errno), file, line, errno); } else version (Posix) this(scope const(char)[] name, uint errno = .errno, string file = __FILE__, size_t line = __LINE__) @trusted { import std.exception : errnoString; this(name, errnoString(errno), file, line, errno); }} ///@safe unittest{ import std.exception : assertThrown; assertThrown!FileException("non.existing.file.".readText);} private T cenforce(T)(T condition, lazy scope const(char)[] name, string file = __FILE__, size_t line = __LINE__){ if (condition) return condition; version (Windows) { throw new FileException(name, .GetLastError(), file, line); } else version (Posix) { throw new FileException(name, .errno, file, line); }} version (Windows)@trustedprivate T cenforce(T)(T condition, scope const(char)[] name, scope const(FSChar)* namez, string file = __FILE__, size_t line = __LINE__){ if (condition) return condition; if (!name) { import core.stdc.wchar_ : wcslen; import std.conv : to; auto len = namez ? wcslen(namez) : 0; name = to!string(namez[0 .. len]); } throw new FileException(name, .GetLastError(), file, line);} version (Posix)@trustedprivate T cenforce(T)(T condition, scope const(char)[] name, scope const(FSChar)* namez, string file = __FILE__, size_t line = __LINE__){ if (condition) return condition; if (!name) { import core.stdc.string : strlen; auto len = namez ? strlen(namez) : 0; name = namez[0 .. len].idup; } throw new FileException(name, .errno, file, line);} // https://issues.dlang.org/show_bug.cgi?id=17102@safe unittest{ try { cenforce(false, null, null, __FILE__, __LINE__); } catch (FileException) {}} /* ********************************** * Basic File operations. */ /********************************************Read entire contents of file `name` and returns it as an untypedarray. If the file size is larger than `upTo`, only `upTo`bytes are _read. Params: name = string or range of characters representing the file _name upTo = if present, the maximum number of bytes to _read Returns: Untyped array of bytes _read. Throws: $(LREF FileException) on error. See_Also: $(REF readText, std,file) for reading and validating a text file. */ void[] read(R)(R name, size_t upTo = size_t.max)if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R){ static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) return readImpl(name, name.tempCString!FSChar(), upTo); else return readImpl(null, name.tempCString!FSChar(), upTo);} ///@safe unittest{ import std.utf : byChar; scope(exit) { assert(exists(deleteme)); remove(deleteme); } std.file.write(deleteme, "1234"); // deleteme is the name of a temporary file assert(read(deleteme, 2) == "12"); assert(read(deleteme.byChar) == "1234"); assert((cast(const(ubyte)[])read(deleteme)).length == 4);} /// dittovoid[] read(R)(auto ref R name, size_t upTo = size_t.max)if (isConvertibleToString!R){ return read!(StringTypeOf!R)(name, upTo);} @safe unittest{ static assert(__traits(compiles, read(TestAliasedString(null))));} version (Posix) private void[] readImpl(scope const(char)[] name, scope const(FSChar)* namez, size_t upTo = size_t.max) @trusted{ import core.memory : GC; import std.algorithm.comparison : min; import std.conv : to; import std.checkedint : checked; // A few internal configuration parameters { enum size_t minInitialAlloc = 1024 * 4, maxInitialAlloc = size_t.max / 2, sizeIncrement = 1024 * 16, maxSlackMemoryAllowed = 1024; // } immutable fd = core.sys.posix.fcntl.open(namez, core.sys.posix.fcntl.O_RDONLY); cenforce(fd != -1, name); scope(exit) core.sys.posix.unistd.close(fd); stat_t statbuf = void; cenforce(fstat(fd, &statbuf) == 0, name, namez); immutable initialAlloc = min(upTo, to!size_t(statbuf.st_size ? min(statbuf.st_size + 1, maxInitialAlloc) : minInitialAlloc)); void[] result = GC.malloc(initialAlloc, GC.BlkAttr.NO_SCAN)[0 .. initialAlloc]; scope(failure) GC.free(result.ptr); auto size = checked(size_t(0)); for (;;) { immutable actual = core.sys.posix.unistd.read(fd, result.ptr + size.get, (min(result.length, upTo) - size).get); cenforce(actual != -1, name, namez); if (actual == 0) break; size += actual; if (size >= upTo) break; if (size < result.length) continue; immutable newAlloc = size + sizeIncrement; result = GC.realloc(result.ptr, newAlloc.get, GC.BlkAttr.NO_SCAN)[0 .. newAlloc.get]; } return result.length - size >= maxSlackMemoryAllowed ? GC.realloc(result.ptr, size.get, GC.BlkAttr.NO_SCAN)[0 .. size.get] : result[0 .. size.get];} version (Windows)private extern (Windows) @nogc nothrow{ pragma(mangle, CreateFileW.mangleof) HANDLE trustedCreateFileW(scope const(wchar)* namez, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES* lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) @trusted; pragma(mangle, CloseHandle.mangleof) BOOL trustedCloseHandle(HANDLE) @trusted;} version (Windows) private void[] readImpl(scope const(char)[] name, scope const(FSChar)* namez, size_t upTo = size_t.max) @trusted{ import core.memory : GC; import std.algorithm.comparison : min; static trustedGetFileSize(HANDLE hFile, out ulong fileSize) { DWORD sizeHigh; DWORD sizeLow = GetFileSize(hFile, &sizeHigh); const bool result = sizeLow != INVALID_FILE_SIZE; if (result) fileSize = makeUlong(sizeLow, sizeHigh); return result; } static trustedReadFile(HANDLE hFile, void *lpBuffer, size_t nNumberOfBytesToRead) { // Read by chunks of size < 4GB (Windows API limit) size_t totalNumRead = 0; while (totalNumRead != nNumberOfBytesToRead) { const uint chunkSize = min(nNumberOfBytesToRead - totalNumRead, 0xffff_0000); DWORD numRead = void; const result = ReadFile(hFile, lpBuffer + totalNumRead, chunkSize, &numRead, null); if (result == 0 || numRead != chunkSize) return false; totalNumRead += chunkSize; } return true; } alias defaults = AliasSeq!(GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, (SECURITY_ATTRIBUTES*).init, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init); auto h = trustedCreateFileW(namez, defaults); cenforce(h != INVALID_HANDLE_VALUE, name, namez); scope(exit) cenforce(trustedCloseHandle(h), name, namez); ulong fileSize = void; cenforce(trustedGetFileSize(h, fileSize), name, namez); size_t size = min(upTo, fileSize); auto buf = () { return GC.malloc(size, GC.BlkAttr.NO_SCAN)[0 .. size]; } (); scope(failure) { () { GC.free(buf.ptr); } (); } if (size) cenforce(trustedReadFile(h, &buf[0], size), name, namez); return buf[0 .. size];} version (linux) @safe unittest{ // A file with "zero" length that doesn't have 0 length at all auto s = std.file.readText("/proc/cpuinfo"); assert(s.length > 0); //writefln("'%s'", s);} @safe unittest{ scope(exit) if (exists(deleteme)) remove(deleteme); import std.stdio; auto f = File(deleteme, "w"); f.write("abcd"); f.flush(); assert(read(deleteme) == "abcd");} /++ Reads and validates (using $(REF validate, std, utf)) a text file. S can be an array of any character type. However, no width or endian conversions are performed. So, if the width or endianness of the characters in the given file differ from the width or endianness of the element type of S, then validation will fail. Params: S = the string type of the file name = string or range of characters representing the file _name Returns: Array of characters read. Throws: $(LREF FileException) if there is an error reading the file,Lines 1–500 of 5524. Load more
// Written in the D programming language. /** Utilities for manipulating files and scanning directories. Functions in this module handle files as a unit, e.g., read or write one file at a time. For opening files and manipulating them via handles refer to module $(MREF std, stdio). $(SCRIPT inhibitQuickIndex = 1;) $(DIVC quickindex, $(BOOKTABLE, $(TR $(TH Category) $(TH Functions)) $(TR $(TD General) $(TD $(LREF exists) $(LREF isDir) $(LREF isFile) $(LREF isSymlink) $(LREF rename) $(LREF thisExePath) )) $(TR $(TD Directories) $(TD $(LREF chdir) $(LREF dirEntries) $(LREF getcwd) $(LREF mkdir) $(LREF mkdirRecurse) $(LREF rmdir) $(LREF rmdirRecurse) $(LREF tempDir) )) $(TR $(TD Files) $(TD $(LREF append) $(LREF copy) $(LREF read) $(LREF readText) $(LREF remove) $(LREF slurp) $(LREF write) )) $(TR $(TD Symlinks) $(TD $(LREF symlink) $(LREF readLink) )) $(TR $(TD Attributes) $(TD $(LREF attrIsDir) $(LREF attrIsFile) $(LREF attrIsSymlink) $(LREF getAttributes) $(LREF getLinkAttributes) $(LREF getSize) $(LREF setAttributes) )) $(TR $(TD Timestamp) $(TD $(LREF getTimes) $(LREF getTimesWin) $(LREF setTimes) $(LREF timeLastModified) $(LREF timeLastAccessed) $(LREF timeStatusChanged) )) $(TR $(TD Other) $(TD $(LREF DirEntry) $(LREF FileException) $(LREF PreserveAttributes) $(LREF SpanMode) $(LREF getAvailableDiskSpace) )) )) Copyright: Copyright The D Language Foundation 2007 - 2011. See_Also: The $(HTTP ddili.org/ders/d.en/files.html, official tutorial) for an introduction to working with files in D, module $(MREF std, stdio) for opening files and manipulating them via handles, and module $(MREF std, path) for manipulating path strings. License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0). Authors: $(HTTP digitalmars.com, Walter Bright), $(HTTP erdani.org, Andrei Alexandrescu), $(HTTP jmdavisprog.com, Jonathan M Davis) Source: $(PHOBOSSRC std/file.d) */ module std.file; import core.stdc.errno, core.stdc.stdlib, core.stdc.string; import core.time : abs, dur, hnsecs, seconds; import std.datetime.date : DateTime; import std.datetime.systime : Clock, SysTime, unixTimeToStdTime; import std.internal.cstring; import std.meta; import std.range; import std.traits; import std.typecons; version (OSX) version = Darwin; else version (iOS) version = Darwin; else version (TVOS) version = Darwin; else version (WatchOS) version = Darwin; version (Windows) { import core.sys.windows.winbase, core.sys.windows.winnt, std.windows.syserror; } else version (Posix) { import core.sys.posix.dirent, core.sys.posix.fcntl, core.sys.posix.sys.stat, core.sys.posix.sys.time, core.sys.posix.unistd, core.sys.posix.utime; } else static assert(false, "Module " ~ .stringof ~ " not implemented for this OS."); // Character type used for operating system filesystem APIs version (Windows) { private alias FSChar = WCHAR; // WCHAR can be aliased to wchar or wchar_t } else version (Posix) { private alias FSChar = char; } else static assert(0); // Purposefully not documented. Use at your own risk @property string deleteme() @safe { import std.conv : text; import std.path : buildPath; import std.process : thisProcessID; enum base = "deleteme.dmd.unittest.pid"; static string fileName; if (!fileName) fileName = text(buildPath(tempDir(), base), thisProcessID); return fileName; } version (StdUnittest) private struct TestAliasedString { string get() @safe @nogc pure nothrow return scope { return _s; } alias get this; @disable this(this); string _s; } version (Android) { package enum system_directory = "/system/etc"; package enum system_file = "/system/etc/hosts"; } else version (Posix) { package enum system_directory = "/usr/include"; package enum system_file = "/usr/include/assert.h"; } /++ Exception thrown for file I/O errors. +/ class FileException : Exception { import std.conv : text, to; /++ OS error code. +/ immutable uint errno; private this(scope const(char)[] name, scope const(char)[] msg, string file, size_t line, uint errno) @safe pure { if (msg.empty) super(name is null ? "(null)" : name.idup, file, line); else super(text(name is null ? "(null)" : name, ": ", msg), file, line); this.errno = errno; } /++ Constructor which takes an error message. Params: name = Name of file for which the error occurred. msg = Message describing the error. file = The file where the error occurred. line = The _line where the error occurred. +/ this(scope const(char)[] name, scope const(char)[] msg, string file = __FILE__, size_t line = __LINE__) @safe pure { this(name, msg, file, line, 0); } /++ Constructor which takes the error number ($(LUCKY GetLastError) in Windows, $(D_PARAM errno) in POSIX). Params: name = Name of file for which the error occurred. errno = The error number. file = The file where the error occurred. Defaults to `__FILE__`. line = The _line where the error occurred. Defaults to `__LINE__`. +/ version (Windows) this(scope const(char)[] name, uint errno = .GetLastError(), string file = __FILE__, size_t line = __LINE__) @safe { this(name, generateSysErrorMsg(errno), file, line, errno); } else version (Posix) this(scope const(char)[] name, uint errno = .errno, string file = __FILE__, size_t line = __LINE__) @trusted { import std.exception : errnoString; this(name, errnoString(errno), file, line, errno); } } /// @safe unittest { import std.exception : assertThrown; assertThrown!FileException("non.existing.file.".readText); } private T cenforce(T)(T condition, lazy scope const(char)[] name, string file = __FILE__, size_t line = __LINE__) { if (condition) return condition; version (Windows) { throw new FileException(name, .GetLastError(), file, line); } else version (Posix) { throw new FileException(name, .errno, file, line); } } version (Windows) @trusted private T cenforce(T)(T condition, scope const(char)[] name, scope const(FSChar)* namez, string file = __FILE__, size_t line = __LINE__) { if (condition) return condition; if (!name) { import core.stdc.wchar_ : wcslen; import std.conv : to; auto len = namez ? wcslen(namez) : 0; name = to!string(namez[0 .. len]); } throw new FileException(name, .GetLastError(), file, line); } version (Posix) @trusted private T cenforce(T)(T condition, scope const(char)[] name, scope const(FSChar)* namez, string file = __FILE__, size_t line = __LINE__) { if (condition) return condition; if (!name) { import core.stdc.string : strlen; auto len = namez ? strlen(namez) : 0; name = namez[0 .. len].idup; } throw new FileException(name, .errno, file, line); } // https://issues.dlang.org/show_bug.cgi?id=17102 @safe unittest { try { cenforce(false, null, null, __FILE__, __LINE__); } catch (FileException) {} } /* ********************************** * Basic File operations. */ /******************************************** Read entire contents of file `name` and returns it as an untyped array. If the file size is larger than `upTo`, only `upTo` bytes are _read. Params: name = string or range of characters representing the file _name upTo = if present, the maximum number of bytes to _read Returns: Untyped array of bytes _read. Throws: $(LREF FileException) on error. See_Also: $(REF readText, std,file) for reading and validating a text file. */ void[] read(R)(R name, size_t upTo = size_t.max) if (isSomeFiniteCharInputRange!R && !isConvertibleToString!R) { static if (isNarrowString!R && is(immutable ElementEncodingType!R == immutable char)) return readImpl(name, name.tempCString!FSChar(), upTo); else return readImpl(null, name.tempCString!FSChar(), upTo); } /// @safe unittest { import std.utf : byChar; scope(exit) { assert(exists(deleteme)); remove(deleteme); } std.file.write(deleteme, "1234"); // deleteme is the name of a temporary file assert(read(deleteme, 2) == "12"); assert(read(deleteme.byChar) == "1234"); assert((cast(const(ubyte)[])read(deleteme)).length == 4); } /// ditto void[] read(R)(auto ref R name, size_t upTo = size_t.max) if (isConvertibleToString!R) { return read!(StringTypeOf!R)(name, upTo); } @safe unittest { static assert(__traits(compiles, read(TestAliasedString(null)))); } version (Posix) private void[] readImpl(scope const(char)[] name, scope const(FSChar)* namez, size_t upTo = size_t.max) @trusted { import core.memory : GC; import std.algorithm.comparison : min; import std.conv : to; import std.checkedint : checked; // A few internal configuration parameters { enum size_t minInitialAlloc = 1024 * 4, maxInitialAlloc = size_t.max / 2, sizeIncrement = 1024 * 16, maxSlackMemoryAllowed = 1024; // } immutable fd = core.sys.posix.fcntl.open(namez, core.sys.posix.fcntl.O_RDONLY); cenforce(fd != -1, name); scope(exit) core.sys.posix.unistd.close(fd); stat_t statbuf = void; cenforce(fstat(fd, &statbuf) == 0, name, namez); immutable initialAlloc = min(upTo, to!size_t(statbuf.st_size ? min(statbuf.st_size + 1, maxInitialAlloc) : minInitialAlloc)); void[] result = GC.malloc(initialAlloc, GC.BlkAttr.NO_SCAN)[0 .. initialAlloc]; scope(failure) GC.free(result.ptr); auto size = checked(size_t(0)); for (;;) { immutable actual = core.sys.posix.unistd.read(fd, result.ptr + size.get, (min(result.length, upTo) - size).get); cenforce(actual != -1, name, namez); if (actual == 0) break; size += actual; if (size >= upTo) break; if (size < result.length) continue; immutable newAlloc = size + sizeIncrement; result = GC.realloc(result.ptr, newAlloc.get, GC.BlkAttr.NO_SCAN)[0 .. newAlloc.get]; } return result.length - size >= maxSlackMemoryAllowed ? GC.realloc(result.ptr, size.get, GC.BlkAttr.NO_SCAN)[0 .. size.get] : result[0 .. size.get]; } version (Windows) private extern (Windows) @nogc nothrow { pragma(mangle, CreateFileW.mangleof) HANDLE trustedCreateFileW(scope const(wchar)* namez, DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES* lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) @trusted; pragma(mangle, CloseHandle.mangleof) BOOL trustedCloseHandle(HANDLE) @trusted; } version (Windows) private void[] readImpl(scope const(char)[] name, scope const(FSChar)* namez, size_t upTo = size_t.max) @trusted { import core.memory : GC; import std.algorithm.comparison : min; static trustedGetFileSize(HANDLE hFile, out ulong fileSize) { DWORD sizeHigh; DWORD sizeLow = GetFileSize(hFile, &sizeHigh); const bool result = sizeLow != INVALID_FILE_SIZE; if (result) fileSize = makeUlong(sizeLow, sizeHigh); return result; } static trustedReadFile(HANDLE hFile, void *lpBuffer, size_t nNumberOfBytesToRead) { // Read by chunks of size < 4GB (Windows API limit) size_t totalNumRead = 0; while (totalNumRead != nNumberOfBytesToRead) { const uint chunkSize = min(nNumberOfBytesToRead - totalNumRead, 0xffff_0000); DWORD numRead = void; const result = ReadFile(hFile, lpBuffer + totalNumRead, chunkSize, &numRead, null); if (result == 0 || numRead != chunkSize) return false; totalNumRead += chunkSize; } return true; } alias defaults = AliasSeq!(GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, (SECURITY_ATTRIBUTES*).init, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init); auto h = trustedCreateFileW(namez, defaults); cenforce(h != INVALID_HANDLE_VALUE, name, namez); scope(exit) cenforce(trustedCloseHandle(h), name, namez); ulong fileSize = void; cenforce(trustedGetFileSize(h, fileSize), name, namez); size_t size = min(upTo, fileSize); auto buf = () { return GC.malloc(size, GC.BlkAttr.NO_SCAN)[0 .. size]; } (); scope(failure) { () { GC.free(buf.ptr); } (); } if (size) cenforce(trustedReadFile(h, &buf[0], size), name, namez); return buf[0 .. size]; } version (linux) @safe unittest { // A file with "zero" length that doesn't have 0 length at all auto s = std.file.readText("/proc/cpuinfo"); assert(s.length > 0); //writefln("'%s'", s); } @safe unittest { scope(exit) if (exists(deleteme)) remove(deleteme); import std.stdio; auto f = File(deleteme, "w"); f.write("abcd"); f.flush(); assert(read(deleteme) == "abcd"); } /++ Reads and validates (using $(REF validate, std, utf)) a text file. S can be an array of any character type. However, no width or endian conversions are performed. So, if the width or endianness of the characters in the given file differ from the width or endianness of the element type of S, then validation will fail. Params: S = the string type of the file name = string or range of characters representing the file _name Returns: Array of characters read. Throws: $(LREF FileException) if there is an error reading the file,