@@ -96,6 +96,7 @@ version(Windows)
9696 /+ Waiting for druntime pull 299
9797 +/
9898 extern (C ) nothrow @nogc FILE * _wfopen(in wchar * filename, in wchar * mode);
99+ extern (C ) nothrow @nogc FILE * _wfreopen(in wchar * filename, in wchar * mode, FILE * fp);
99100
100101 import core.sys.windows.windows : HANDLE ;
101102}
@@ -488,6 +489,86 @@ Throws: $(D ErrnoException) in case of error.
488489 this = File (name, stdioOpenmode);
489490 }
490491
492+ /**
493+ Reuses the `File` object to either open a different file, or change
494+ the file mode. If `name` is `null`, the mode of the currently open
495+ file is changed; otherwise, a new file is opened, reusing the C
496+ `FILE*`. The function has the same semantics as in the C standard
497+ library $(HTTP cplusplus.com/reference/cstdio/freopen/, freopen)
498+ function.
499+
500+ Note: Calling `reopen` with a `null` `name` is not implemented
501+ in all C runtimes.
502+
503+ Throws: $(D ErrnoException) in case of error.
504+ */
505+ void reopen (string name, in char [] stdioOpenmode = " rb" ) @trusted
506+ {
507+ import std.internal.cstring : tempCString;
508+ import std.exception : enforce, errnoEnforce;
509+ import std.conv : text;
510+
511+ enforce(isOpen, " Attempting to reopen() an unopened file" );
512+
513+ auto namez = name.tempCString! FSChar();
514+ auto modez = stdioOpenmode.tempCString! FSChar();
515+
516+ FILE * fd = _p.handle;
517+ version (Windows )
518+ fd = _wfreopen(namez, modez, fd);
519+ else
520+ fd = freopen(namez, modez, fd);
521+
522+ errnoEnforce(fd, name
523+ ? text(" Cannot reopen file `" , name, " ' in mode `" , stdioOpenmode, " '" )
524+ : text(" Cannot reopen file in mode `" , stdioOpenmode, " '" ));
525+
526+ if (name ! is null )
527+ _name = name;
528+ }
529+
530+ unittest // Test changing filename
531+ {
532+ static import std.file ;
533+ import std.exception : assertThrown, assertNotThrown;
534+
535+ auto deleteme = testFilename();
536+ std.file.write (deleteme, " foo" );
537+ scope (exit) std.file.remove (deleteme);
538+ auto f = File (deleteme);
539+ assert (f.readln() == " foo" );
540+
541+ auto deleteme2 = testFilename();
542+ std.file.write (deleteme2, " bar" );
543+ scope (exit) std.file.remove (deleteme2);
544+ f.reopen(deleteme2);
545+ assert (f.name == deleteme2);
546+ assert (f.readln() == " bar" );
547+ f.close();
548+ }
549+
550+ version (CRuntime_DigitalMars ) {} else // Not implemented
551+ version (CRuntime_Microsoft ) {} else // Not implemented
552+ unittest // Test changing mode
553+ {
554+ static import std.file ;
555+ import std.exception : assertThrown, assertNotThrown;
556+
557+ auto deleteme = testFilename();
558+ std.file.write (deleteme, " foo" );
559+ scope (exit) std.file.remove (deleteme);
560+ auto f = File (deleteme, " r+" );
561+ assert (f.readln() == " foo" );
562+ f.reopen(null , " w" );
563+ f.write(" bar" );
564+ f.seek(0 );
565+ f.reopen(null , " a" );
566+ f.write(" baz" );
567+ assert (f.name == deleteme);
568+ f.close();
569+ assert (std.file.readText (deleteme) == " barbaz" );
570+ }
571+
491572/**
492573First calls $(D detach) (throwing on failure), and then runs a command
493574by calling the C standard library function $(HTTP
0 commit comments