www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - std.stream.File

reply Arcane Jill <Arcane_member pathlink.com> writes:
On the Windows platform:

#    import std.stream;
#
#    void main()
#    {
#        File f = new File("foo"); // where foo does not exist
#    }

creates the file "foo", does not throw any kind of exception, and then carries
on executing as though everything were hunky dory.

This is currently a very good reason not to use std.stream.File

Arcane Jill
Jul 21 2004
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Arcane Jill wrote:
 On the Windows platform:
 
 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }
 
 creates the file "foo", does not throw any kind of exception, and then carries
 on executing as though everything were hunky dory.

In accordance with the documentation. ---------- this() this(char[] filename) this(char[] filename, FileMode mode) Create the stream with no open file, an open file in read and write mode, or an open file with explicit file mode. mode, if given, is a combination of FileMode.In (indicating a file that can be read) and FileMode.Out (indicating a file that can be written). If the file does not exist, it is created. ---------- After all, your code does say "new File"! Even though that isn't what it really means!
 This is currently a very good reason not to use std.stream.File

Yes, the whole File class could be more clearly defined. At the moment, it seems you're meant to manually call std.file.exists first. Chances are this isn't part of the normal program logic.... My idea would probably be something like enum FILE_MODE { IN = 0b000001, OUT = 0b000010, CREATE_IF_NONEXISTENT = 0b000100, NEW_FILE = 0b001100, /*!< create new file, prevent overwrite */ OVERWRITE = 0b001000, /*!< create new file, overwrite if necessary */ APPEND = 0b010000, //!< start pointer at end EXCLUSIVE = 0b100000 /*!< lock for exclusive access, if that follows */ } Obviously some combinations don't make sense.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 21 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cdlpci$2ma4$1 digitaldaemon.com>, Stewart Gordon says...
Arcane Jill wrote:
 On the Windows platform:
 
 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }


Whoops. Should have said: import std.stream; # void main() # { # File f = new File("foo", FileMode.In); // where foo does not exist # } Please observe the FileMode.In parameter
 creates the file "foo", does not throw any kind of exception, and then carries
 on executing as though everything were hunky dory.


Is /this/ in accordance with the documentation? Arcane Jill
Jul 21 2004
parent Burton Radons <burton-radons shaw.ca> writes:
Arcane Jill wrote:
 In article <cdlpci$2ma4$1 digitaldaemon.com>, Stewart Gordon says...
 
Arcane Jill wrote:

On the Windows platform:

#    import std.stream;
#
#    void main()
#    {
#        File f = new File("foo"); // where foo does not exist
#    }


Whoops. Should have said: import std.stream; # void main() # { # File f = new File("foo", FileMode.In); // where foo does not exist # } Please observe the FileMode.In parameter
creates the file "foo", does not throw any kind of exception, and then carries
on executing as though everything were hunky dory.


Is /this/ in accordance with the documentation?

Yes. "If the file does not exist, it is created." There's nothing about examining the mode parameter for how to behave; it only modifies what operations can be performed on the stream. I do think the API's incorrectly designed, but it's not a bug.
Jul 21 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Wed, 21 Jul 2004 14:00:01 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:
 Arcane Jill wrote:
 On the Windows platform:

 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }

 creates the file "foo", does not throw any kind of exception, and then 
 carries
 on executing as though everything were hunky dory.

In accordance with the documentation. ---------- this() this(char[] filename) this(char[] filename, FileMode mode) Create the stream with no open file, an open file in read and write mode, or an open file with explicit file mode. mode, if given, is a combination of FileMode.In (indicating a file that can be read) and FileMode.Out (indicating a file that can be written). If the file does not exist, it is created. ---------- After all, your code does say "new File"! Even though that isn't what it really means!
 This is currently a very good reason not to use std.stream.File

Yes, the whole File class could be more clearly defined. At the moment, it seems you're meant to manually call std.file.exists first. Chances are this isn't part of the normal program logic.... My idea would probably be something like enum FILE_MODE { IN = 0b000001, OUT = 0b000010, CREATE_IF_NONEXISTENT = 0b000100, NEW_FILE = 0b001100, /*!< create new file, prevent overwrite */ OVERWRITE = 0b001000, /*!< create new file, overwrite if necessary */ APPEND = 0b010000, //!< start pointer at end EXCLUSIVE = 0b100000 /*!< lock for exclusive access, if that follows */ } Obviously some combinations don't make sense....

I suggested these a little while back: READ WRITE CREATE APPEND NEW allowing: "r" - READ - read, fails if file does not exist. "w" - CREATE - write, overwrite existing. "a" - APPEND - write, create if not exist. "r+" - READ|WRITE - read, write, fails if file does not exist. "w+" - READ|CREATE - read, write, overwrite existing. "a+" - READ|APPEND - read, append, create if not exist. "" - WRITE|NEW - write, fail if file exist. to mirror fopen capability _and_ add new WRITE|NEW capability. I would extend File creating LockedFile and/or add a LockFile class to handle file locking as it is done differently on the various *NIX operating systems. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 21 2004
parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 22 Jul 2004 12:00:32 +1200, Regan Heath wrote:

 On Wed, 21 Jul 2004 14:00:01 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
 wrote:
 Arcane Jill wrote:
 On the Windows platform:

 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }

 creates the file "foo", does not throw any kind of exception, and then 
 carries
 on executing as though everything were hunky dory.

In accordance with the documentation. ---------- this() this(char[] filename) this(char[] filename, FileMode mode) Create the stream with no open file, an open file in read and write mode, or an open file with explicit file mode. mode, if given, is a combination of FileMode.In (indicating a file that can be read) and FileMode.Out (indicating a file that can be written). If the file does not exist, it is created. ---------- After all, your code does say "new File"! Even though that isn't what it really means!
 This is currently a very good reason not to use std.stream.File

Yes, the whole File class could be more clearly defined. At the moment, it seems you're meant to manually call std.file.exists first. Chances are this isn't part of the normal program logic.... My idea would probably be something like enum FILE_MODE { IN = 0b000001, OUT = 0b000010, CREATE_IF_NONEXISTENT = 0b000100, NEW_FILE = 0b001100, /*!< create new file, prevent overwrite */ OVERWRITE = 0b001000, /*!< create new file, overwrite if necessary */ APPEND = 0b010000, //!< start pointer at end EXCLUSIVE = 0b100000 /*!< lock for exclusive access, if that follows */ } Obviously some combinations don't make sense....

I suggested these a little while back: READ WRITE CREATE APPEND NEW allowing: "r" - READ - read, fails if file does not exist. "w" - CREATE - write, overwrite existing. "a" - APPEND - write, create if not exist. "r+" - READ|WRITE - read, write, fails if file does not exist. "w+" - READ|CREATE - read, write, overwrite existing. "a+" - READ|APPEND - read, append, create if not exist. "" - WRITE|NEW - write, fail if file exist. to mirror fopen capability _and_ add new WRITE|NEW capability. I would extend File creating LockedFile and/or add a LockFile class to handle file locking as it is done differently on the various *NIX operating systems.

Hmmmm...this got me a-thinkin'... I came up with this... The open() routine seems to controls four aspects: Access: Read, Write, Both, Neither File-Exists action: Use, Overwrite, Fail File-Not-Exists action: Create, Fail Initial Seek: Start-of-File (normal), End-of-File (append) This leads to 48 different combinations, some of which are not useful (eg. neither read nor write, fails if exists and if not-exists, read starting from end of file, etc...). So after removing the useless combinations, we are left with 20 possible ones. I've devised six codes that encompass these combinations: R : read access from start of file W : write access from start of file A : write access from end of file U : use existing file O : overwrite existing file C : create non-existing file So the useful combinations that either open a file or fail are (I've also show Regan's equivalent codes) ... RWUC - read, write, use existing, create if not existing. RAUC "a+" - read, append (to existing), create if not exist. RWOC "w+" - read, write, overwrite existing(, create if not existing). RWU "r+" - read, write, fails if file does not exist. RAU - read, append to existing, fail if not exist. RWC - read, write, fail if exists, create if not existing. RWO - read, write, overwrite if exists, fail if not existing. RAO - read, append if exists, fail if not existing. WUC - write, use if exists, create if not existing. AUC "a" - write(, append if exists), create if not exist. WOC "w" - write, overwrite existing(, create if not existing). RUC - read, use if exists, create if not existing. ROC - read, overwrite if exists, create if not existing. (Used to always create an empty file). RU "r" - read, fails if file does not exist. RC - read, fail if exists, create if not existing. (Used to create an empty file if it doesn't already exist). RO - read, overwrite if exists, fail if not existing. (Used to wipe an existing file). WU - write, use if file exists, fail if not existing. AU - write, append if file exists, fail if not existing. WC "" - write, fail if file exists(, create if not existing). WO - write, overwrite if exists, fail if not existing.(Used to replace an existing file). Of course, these don't take file locking into account ;-) -- Derek Melbourne, Australia 22/Jul/04 12:06:49 PM
Jul 21 2004
next sibling parent Regan Heath <regan netwin.co.nz> writes:
On Thu, 22 Jul 2004 12:51:01 +1000, Derek Parnell <derek psych.ward> wrote:
 On Thu, 22 Jul 2004 12:00:32 +1200, Regan Heath wrote:

 On Wed, 21 Jul 2004 14:00:01 +0100, Stewart Gordon <smjg_1998 yahoo.com>
 wrote:
 Arcane Jill wrote:
 On the Windows platform:

 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }

 creates the file "foo", does not throw any kind of exception, and then
 carries
 on executing as though everything were hunky dory.

In accordance with the documentation. ---------- this() this(char[] filename) this(char[] filename, FileMode mode) Create the stream with no open file, an open file in read and write mode, or an open file with explicit file mode. mode, if given, is a combination of FileMode.In (indicating a file that can be read) and FileMode.Out (indicating a file that can be written). If the file does not exist, it is created. ---------- After all, your code does say "new File"! Even though that isn't what it really means!
 This is currently a very good reason not to use std.stream.File

Yes, the whole File class could be more clearly defined. At the moment, it seems you're meant to manually call std.file.exists first. Chances are this isn't part of the normal program logic.... My idea would probably be something like enum FILE_MODE { IN = 0b000001, OUT = 0b000010, CREATE_IF_NONEXISTENT = 0b000100, NEW_FILE = 0b001100, /*!< create new file, prevent overwrite */ OVERWRITE = 0b001000, /*!< create new file, overwrite if necessary */ APPEND = 0b010000, //!< start pointer at end EXCLUSIVE = 0b100000 /*!< lock for exclusive access, if that follows */ } Obviously some combinations don't make sense....

I suggested these a little while back: READ WRITE CREATE APPEND NEW allowing: "r" - READ - read, fails if file does not exist. "w" - CREATE - write, overwrite existing. "a" - APPEND - write, create if not exist. "r+" - READ|WRITE - read, write, fails if file does not exist. "w+" - READ|CREATE - read, write, overwrite existing. "a+" - READ|APPEND - read, append, create if not exist. "" - WRITE|NEW - write, fail if file exist. to mirror fopen capability _and_ add new WRITE|NEW capability. I would extend File creating LockedFile and/or add a LockFile class to handle file locking as it is done differently on the various *NIX operating systems.

Hmmmm...this got me a-thinkin'... I came up with this... The open() routine seems to controls four aspects: Access: Read, Write, Both, Neither File-Exists action: Use, Overwrite, Fail File-Not-Exists action: Create, Fail Initial Seek: Start-of-File (normal), End-of-File (append) This leads to 48 different combinations, some of which are not useful (eg. neither read nor write, fails if exists and if not-exists, read starting from end of file, etc...). So after removing the useless combinations, we are left with 20 possible ones. I've devised six codes that encompass these combinations: R : read access from start of file W : write access from start of file A : write access from end of file U : use existing file O : overwrite existing file C : create non-existing file So the useful combinations that either open a file or fail are (I've also show Regan's equivalent codes) ... RWUC - read, write, use existing, create if not existing. RAUC "a+" - read, append (to existing), create if not exist. RWOC "w+" - read, write, overwrite existing(, create if not existing). RWU "r+" - read, write, fails if file does not exist. RAU - read, append to existing, fail if not exist. RWC - read, write, fail if exists, create if not existing. RWO - read, write, overwrite if exists, fail if not existing. RAO - read, append if exists, fail if not existing. WUC - write, use if exists, create if not existing. AUC "a" - write(, append if exists), create if not exist. WOC "w" - write, overwrite existing(, create if not existing). RUC - read, use if exists, create if not existing. ROC - read, overwrite if exists, create if not existing. (Used to always create an empty file). RU "r" - read, fails if file does not exist. RC - read, fail if exists, create if not existing. (Used to create an empty file if it doesn't already exist). RO - read, overwrite if exists, fail if not existing. (Used to wipe an existing file). WU - write, use if file exists, fail if not existing. AU - write, append if file exists, fail if not existing. WC "" - write, fail if file exists(, create if not existing). WO - write, overwrite if exists, fail if not existing.(Used to replace an existing file). Of course, these don't take file locking into account ;-)

Excellent work. I believe I will pilfer this list for a File implementation I am writing. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 21 2004
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Derek Parnell wrote:
<snip excessive quote>
 I've devised six codes that encompass these combinations:
 R : read access from start of file
 W : write access from start of file
 A : write access from end of file
 U : use existing file
 O : overwrite existing file
 C : create non-existing file
 
 So the useful combinations that either open a file or fail are (I've also
 show Regan's equivalent codes) ...
 
 RWUC      - read, write, use existing, create if not existing.
 RAUC "a+" - read, append (to existing), create if not exist.

By your system, RA together means that reads start from the beginning, and writes from the end. Which would mean separate read and write pointers, and extra functions needed to manipulate them.
  RWOC "w+" - read, write, overwrite existing(, create if not existing).
 RWU  "r+" - read, write, fails if file does not exist.
 RAU       - read, append to existing, fail if not exist.
 RWC       - read, write, fail if exists, create if not existing.
 RWO       - read, write, overwrite if exists, fail if not existing.
 RAO       - read, append if exists, fail if not existing.

That's read, append, overwrite. Doesn't make sense to me. Or at least it would be redundant as the end of an initially empty file is the same as the beginning.
 WUC       - write, use if exists, create if not existing.
 AUC  "a"  - write(, append if exists), create if not exist.
 WOC  "w"  - write, overwrite existing(, create if not existing).
 RUC       - read, use if exists, create if not existing.

Not sure about this one. To create an empty file if the file isn't there, for the benefit of dodgy programs that insist a file exists even if it may be empty?
 ROC       - read, overwrite if exists, create if not existing. (Used to
                  always create an empty file).
 RU   "r"  - read, fails if file does not exist.
 RC        - read, fail if exists, create if not existing. (Used to create
                  an empty file if it doesn't already exist).

Correction, to require that a file doesn't already exist, but create it as an empty file. Not sure about this one.
 RO        - read, overwrite if exists, fail if not existing. (Used to wipe
                  an existing file).
 WU        - write, use if file exists, fail if not existing.
 AU        - write, append if file exists, fail if not existing.
 WC    ""  - write, fail if file exists(, create if not existing).
 WO        - write, overwrite if exists, fail if not existing.(Used to
                  replace an existing file).

Before I looked through your list, I did my own analysis of your enumeration of aspects, which seems the most logical system so far. I separated W and A, so that R simply means read, W simply means write and A simply means start at the end. I came up with 16 combinations as making sense: WUC RWUC WAUC RWAUC WOC RWOC RC RWC RU WU RWU RAU WAU RWAU WO RWO As you see, I hadn't thought of modes purely to create empty files. RA, WO and RWO make sense but are of questionable value. To read starting from the end does make a bit of sense, if you want to look at the end of a file. But you'd need to seek anyway before you can do anything, so there's little point using it. And you can recreate a file from scratch, making sure that you're indeed recreating a file that was already there, but I'm not sure of its practical uses. But there's little point in validating the combinations to somebody's conception of making sense, except for the obvious nonsensicality of UO together. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 22 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Thu, 22 Jul 2004 11:56:34 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:

 Derek Parnell wrote:
 <snip excessive quote>
 I've devised six codes that encompass these combinations:
 R : read access from start of file
 W : write access from start of file
 A : write access from end of file
 U : use existing file
 O : overwrite existing file
 C : create non-existing file

 So the useful combinations that either open a file or fail are (I've 
 also
 show Regan's equivalent codes) ...

 RWUC      - read, write, use existing, create if not existing.
 RAUC "a+" - read, append (to existing), create if not exist.

By your system, RA together means that reads start from the beginning, and writes from the end. Which would mean separate read and write pointers, and extra functions needed to manipulate them.

Or.. (MSDN fopen docs) "When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten."
  RWOC "w+" - read, write, overwrite existing(, create if not existing).
 RWU  "r+" - read, write, fails if file does not exist.
 RAU       - read, append to existing, fail if not exist.
 RWC       - read, write, fail if exists, create if not existing.
 RWO       - read, write, overwrite if exists, fail if not existing.
 RAO       - read, append if exists, fail if not existing.

That's read, append, overwrite. Doesn't make sense to me. Or at least it would be redundant as the end of an initially empty file is the same as the beginning.

Looks like Derek forgot to prune this one as nonsensical?
 WUC       - write, use if exists, create if not existing.
 AUC  "a"  - write(, append if exists), create if not exist.
 WOC  "w"  - write, overwrite existing(, create if not existing).
 RUC       - read, use if exists, create if not existing.

Not sure about this one. To create an empty file if the file isn't there, for the benefit of dodgy programs that insist a file exists even if it may be empty?

Basically it's saying a file should be there (create if not), and I want to read anything that's in it if its there. So you're not having to catch 'file does not exist' exceptions, as in some cases you don't care.
 ROC       - read, overwrite if exists, create if not existing. (Used to
                  always create an empty file).
 RU   "r"  - read, fails if file does not exist.
 RC        - read, fail if exists, create if not existing. (Used to 
 create
                  an empty file if it doesn't already exist).

Correction, to require that a file doesn't already exist, but create it as an empty file. Not sure about this one.

Simple file locking, i.e. to lock "foobar.dat" we create "foobat.dat.lock" but only if it doesn't already exist (meaning someone has it locked already)
 RO        - read, overwrite if exists, fail if not existing. (Used to 
 wipe
                  an existing file).
 WU        - write, use if file exists, fail if not existing.
 AU        - write, append if file exists, fail if not existing.
 WC    ""  - write, fail if file exists(, create if not existing).
 WO        - write, overwrite if exists, fail if not existing.(Used to
                  replace an existing file).

Before I looked through your list, I did my own analysis of your enumeration of aspects, which seems the most logical system so far. I separated W and A, so that R simply means read, W simply means write and A simply means start at the end. I came up with 16 combinations as making sense: WUC RWUC WAUC RWAUC WOC RWOC RC RWC RU WU RWU RAU WAU RWAU WO RWO As you see, I hadn't thought of modes purely to create empty files. RA, WO and RWO make sense but are of questionable value.

 To read starting from the end does make a bit of sense, if you want to 
 look at the end of a file.  But you'd need to seek anyway before you can 
 do anything, so there's little point using it.

I don't think it makes much sense to read starting from the end. Like you say, you have to seek anyway, why not simply seek from the start to point x, instead of from the start to the end and back to point x.
 And you can recreate a file from scratch, making sure that you're indeed 
 recreating a file that was already there,  but I'm not sure of its 
 practical uses.

 But there's little point in validating the combinations to somebody's 
 conception of making sense, except for the obvious nonsensicality of UO 
 together.

True, I think I have demonstrared that by coming up with a few (IMO) sensible uses for ones you did not think were sensible? Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 22 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Regan Heath wrote:

 On Thu, 22 Jul 2004 11:56:34 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
 wrote:
 
 Derek Parnell wrote:


 RAUC "a+" - read, append (to existing), create if not exist.

By your system, RA together means that reads start from the beginning, and writes from the end. Which would mean separate read and write pointers, and extra functions needed to manipulate them.

Or.. (MSDN fopen docs) "When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten."

Yes, we could have append as a distinct writing mode, rather than merely a seek. In that respect, it would be of use even for O and/or C and not U, to force output to be sequential. As long as it is clear to everyone who uses it.... <snip>
 RAO       - read, append if exists, fail if not existing.

That's read, append, overwrite. Doesn't make sense to me. Or at least it would be redundant as the end of an initially empty file is the same as the beginning.

Looks like Derek forgot to prune this one as nonsensical?

Again, I now suppose it makes sense if the aforementioned semantics of append are implemented.
 WUC       - write, use if exists, create if not existing.
 AUC  "a"  - write(, append if exists), create if not exist.
 WOC  "w"  - write, overwrite existing(, create if not existing).
 RUC       - read, use if exists, create if not existing.

Not sure about this one. To create an empty file if the file isn't there, for the benefit of dodgy programs that insist a file exists even if it may be empty?

Basically it's saying a file should be there (create if not), and I want to read anything that's in it if its there. So you're not having to catch 'file does not exist' exceptions, as in some cases you don't care.

You mean that if the file isn't there, treat it as empty? This should be a third option for File-Not-Exists action. This would stop empty files being created without good cause, and also enable the protocol to be used on write-protected media.
 RC        - read, fail if exists, create if not existing. (Used to 
             create an empty file if it doesn't already exist).

Correction, to require that a file doesn't already exist, but create it as an empty file. Not sure about this one.

Simple file locking, i.e. to lock "foobar.dat" we create "foobat.dat.lock" but only if it doesn't already exist (meaning someone has it locked already)

Which OSs these days don't have their own built-in concept of file locking, which might have the advantage (?) of being automatically released if the locking process dies? <snip>
 True, I think I have demonstrared that by coming up with a few (IMO) 
 sensible uses for ones you did not think were sensible?

I guess so.... Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 22 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Thu, 22 Jul 2004 13:59:59 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:
 Regan Heath wrote:

 On Thu, 22 Jul 2004 11:56:34 +0100, Stewart Gordon 
 <smjg_1998 yahoo.com> wrote:

 Derek Parnell wrote:


 RAUC "a+" - read, append (to existing), create if not exist.

By your system, RA together means that reads start from the beginning, and writes from the end. Which would mean separate read and write pointers, and extra functions needed to manipulate them.

Or.. (MSDN fopen docs) "When a file is opened with the "a" or "a+" access type, all write operations occur at the end of the file. The file pointer can be repositioned using fseek or rewind, but is always moved back to the end of the file before any write operation is carried out. Thus, existing data cannot be overwritten."

Yes, we could have append as a distinct writing mode, rather than merely a seek. In that respect, it would be of use even for O and/or C and not U, to force output to be sequential.

Why not U?
 As long as it is clear to everyone who uses it....

 <snip>
 RAO       - read, append if exists, fail if not existing.

That's read, append, overwrite. Doesn't make sense to me. Or at least it would be redundant as the end of an initially empty file is the same as the beginning.

Looks like Derek forgot to prune this one as nonsensical?

Again, I now suppose it makes sense if the aforementioned semantics of append are implemented.
 WUC       - write, use if exists, create if not existing.
 AUC  "a"  - write(, append if exists), create if not exist.
 WOC  "w"  - write, overwrite existing(, create if not existing).
 RUC       - read, use if exists, create if not existing.

Not sure about this one. To create an empty file if the file isn't there, for the benefit of dodgy programs that insist a file exists even if it may be empty?

Basically it's saying a file should be there (create if not), and I want to read anything that's in it if its there. So you're not having to catch 'file does not exist' exceptions, as in some cases you don't care.

You mean that if the file isn't there, treat it as empty? This should be a third option for File-Not-Exists action. This would stop empty files being created without good cause, and also enable the protocol to be used on write-protected media.

I guess so, I was actually thinking it would create an empty file, but I guess treating it as empty without creating it is slightly more useful with no drawbacks. So instead of RUC which would actually create the file you have RUP (p == pretend it exists)
 RC        - read, fail if exists, create if not existing. (Used to 
             create an empty file if it doesn't already exist).

Correction, to require that a file doesn't already exist, but create it as an empty file. Not sure about this one.

Simple file locking, i.e. to lock "foobar.dat" we create "foobat.dat.lock" but only if it doesn't already exist (meaning someone has it locked already)

Which OSs these days don't have their own built-in concept of file locking, which might have the advantage (?) of being automatically released if the locking process dies?

This method has the characteristic of not being automatically released when the locking process dies/exits/etc you _might_ be after that behaviour.
 <snip>
 True, I think I have demonstrared that by coming up with a few (IMO) 
 sensible uses for ones you did not think were sensible?

I guess so....

I think, instead of bothering to decide which modes 'make no sense' we allow them all and just do what we're told to do, which, may make no sense sometimes but that is up to the user of the api to decide. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 22 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Regan Heath wrote:

 On Thu, 22 Jul 2004 13:59:59 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
 wrote:

 Yes, we could have append as a distinct writing mode, rather than 
 merely a seek.  In that respect, it would be of use even for O and/or 
 C and not U, to force output to be sequential.

Why not U?

By that, I actually meant even if U is not also specified. <snip>
 You mean that if the file isn't there, treat it as empty?  This should 
 be a third option for File-Not-Exists action.  This would stop empty 
 files being created without good cause, and also enable the protocol 
 to be used on write-protected media.

I guess so, I was actually thinking it would create an empty file, but I guess treating it as empty without creating it is slightly more useful with no drawbacks. So instead of RUC which would actually create the file you have RUP (p == pretend it exists)

Exactly. <snip>
 Simple file locking, i.e. to lock "foobar.dat" we create 
 "foobat.dat.lock" but only if it doesn't already exist (meaning 
 someone has it locked already)

Which OSs these days don't have their own built-in concept of file locking, which might have the advantage (?) of being automatically released if the locking process dies?

This method has the characteristic of not being automatically released when the locking process dies/exits/etc you _might_ be after that behaviour.

Yes, you're probably right. E.g. you want to see the output that was generated by the process before it died, before getting back to letting other processes mess with it. Of course, for this whole file locking idea to work, the whole process of testing if the file exists and then creating it ought to be atomic, just in case. Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 23 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
On Fri, 23 Jul 2004 11:40:43 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:
 Regan Heath wrote:

 On Thu, 22 Jul 2004 13:59:59 +0100, Stewart Gordon 
 <smjg_1998 yahoo.com> wrote:

 Yes, we could have append as a distinct writing mode, rather than 
 merely a seek.  In that respect, it would be of use even for O and/or 
 C and not U, to force output to be sequential.

Why not U?

By that, I actually meant even if U is not also specified. <snip>
 You mean that if the file isn't there, treat it as empty?  This should 
 be a third option for File-Not-Exists action.  This would stop empty 
 files being created without good cause, and also enable the protocol 
 to be used on write-protected media.

I guess so, I was actually thinking it would create an empty file, but I guess treating it as empty without creating it is slightly more useful with no drawbacks. So instead of RUC which would actually create the file you have RUP (p == pretend it exists)

Exactly. <snip>
 Simple file locking, i.e. to lock "foobar.dat" we create 
 "foobat.dat.lock" but only if it doesn't already exist (meaning 
 someone has it locked already)

Which OSs these days don't have their own built-in concept of file locking, which might have the advantage (?) of being automatically released if the locking process dies?

This method has the characteristic of not being automatically released when the locking process dies/exits/etc you _might_ be after that behaviour.

Yes, you're probably right. E.g. you want to see the output that was generated by the process before it died, before getting back to letting other processes mess with it. Of course, for this whole file locking idea to work, the whole process of testing if the file exists and then creating it ought to be atomic, just in case.

Correct.. if it's not atomic you have to write something to the file, close it, re-open and read to double check it was you that locked it. The windows CreateFile function has a flag "CREATE_NEW" which "Creates a new file. The function fails if the specified file already exists." I wonder if it's guaranteed to be atomic or not. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 23 2004
parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Regan Heath wrote:

<snip>
 Of course, for this whole file locking idea to work, the whole process 
 of testing if the file exists and then creating it ought to be atomic, 
 just in case.

Correct.. if it's not atomic you have to write something to the file, close it, re-open and read to double check it was you that locked it.

Let's just hope that the two processes are sufficiently matched in speed (which may depend on various factors) that you're not going to get a sequence like: 1. Process A checks if file exists - and it doesn't 2. Process B checks if file exists - and it doesn't 3. Process A opens new file 4. Process A writes ID to file 5. Process A closes file 6. Process A reopens file 7. Process A reads back ID - they match - operation succeeded 8. Process B opens new file 9. Process B writes ID to file 10. Process B closes file 11. Process B reopens file 12. Process B reads back ID - they match - operation succeeded Stewart. -- My e-mail is valid but not my primary mailbox, aside from its being the unfortunate victim of intensive mail-bombing at the moment. Please keep replies on the 'group where everyone may benefit.
Jul 26 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Mon, 26 Jul 2004 11:16:49 +0100, Stewart Gordon <smjg_1998 yahoo.com> 
wrote:
 Regan Heath wrote:

 <snip>
 Of course, for this whole file locking idea to work, the whole process 
 of testing if the file exists and then creating it ought to be atomic, 
 just in case.

Correct.. if it's not atomic you have to write something to the file, close it, re-open and read to double check it was you that locked it.

Let's just hope that the two processes are sufficiently matched in speed (which may depend on various factors) that you're not going to get a sequence like: 1. Process A checks if file exists - and it doesn't 2. Process B checks if file exists - and it doesn't 3. Process A opens new file 4. Process A writes ID to file 5. Process A closes file 6. Process A reopens file 7. Process A reads back ID - they match - operation succeeded 8. Process B opens new file 9. Process B writes ID to file 10. Process B closes file 11. Process B reopens file 12. Process B reads back ID - they match - operation succeeded

It's a mine field all right I believe you have to use a well placed sleep to avoid the above. Eg. -check if file exists -open new file -write id -close file -sleep -re-open file -read id Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
prev sibling parent Derek <derek psyc.ward> writes:
On Thu, 22 Jul 2004 11:56:34 +0100, Stewart Gordon wrote:

 Derek Parnell wrote:
 <snip excessive quote>
 I've devised six codes that encompass these combinations:
 R : read access from start of file
 W : write access from start of file
 A : write access from end of file
 U : use existing file
 O : overwrite existing file
 C : create non-existing file
 
 So the useful combinations that either open a file or fail are (I've also
 show Regan's equivalent codes) ...
 
 RWUC      - read, write, use existing, create if not existing.
 RAUC "a+" - read, append (to existing), create if not exist.

By your system, RA together means that reads start from the beginning, and writes from the end. Which would mean separate read and write pointers, and extra functions needed to manipulate them.

Yes. So...? Though I'm not sure about needing two cursors. One could have it so that the first I/O action, if a read moved to the front, and if it was a write, move to the end. Or maybe even make sure that every write was at the end of the file.
  RWOC "w+" - read, write, overwrite existing(, create if not existing).
 RWU  "r+" - read, write, fails if file does not exist.
 RAU       - read, append to existing, fail if not exist.
 RWC       - read, write, fail if exists, create if not existing.
 RWO       - read, write, overwrite if exists, fail if not existing.
 RAO       - read, append if exists, fail if not existing.

That's read, append, overwrite. Doesn't make sense to me. Or at least it would be redundant as the end of an initially empty file is the same as the beginning.

Yep. This one that should have been culled. I removed all the other AO combinations but this slipped through.
 WUC       - write, use if exists, create if not existing.
 AUC  "a"  - write(, append if exists), create if not exist.
 WOC  "w"  - write, overwrite existing(, create if not existing).
 RUC       - read, use if exists, create if not existing.

Not sure about this one. To create an empty file if the file isn't there, for the benefit of dodgy programs that insist a file exists even if it may be empty?

Well it saves the coder having to check the file's existence before deciding to read it or not. Not sure what's dodgy about that. Oh well, each to their own.
 ROC       - read, overwrite if exists, create if not existing. (Used to
                  always create an empty file).
 RU   "r"  - read, fails if file does not exist.
 RC        - read, fail if exists, create if not existing. (Used to create
                  an empty file if it doesn't already exist).

Correction, to require that a file doesn't already exist, but create it as an empty file. Not sure about this one.

I have used this technique to create 'lock' files. If the file already exists then some other process created it but if not then my process creates it and others have to wait till I delete it.
 RO        - read, overwrite if exists, fail if not existing. (Used to wipe
                  an existing file).
 WU        - write, use if file exists, fail if not existing.
 AU        - write, append if file exists, fail if not existing.
 WC    ""  - write, fail if file exists(, create if not existing).
 WO        - write, overwrite if exists, fail if not existing.(Used to
                  replace an existing file).

Before I looked through your list, I did my own analysis of your enumeration of aspects, which seems the most logical system so far. I separated W and A, so that R simply means read, W simply means write and A simply means start at the end. I came up with 16 combinations as making sense: WUC RWUC WAUC RWAUC WOC RWOC RC RWC RU WU RWU RAU WAU RWAU WO RWO As you see, I hadn't thought of modes purely to create empty files. RA, WO and RWO make sense but are of questionable value. To read starting from the end does make a bit of sense, if you want to look at the end of a file. But you'd need to seek anyway before you can do anything, so there's little point using it. And you can recreate a file from scratch, making sure that you're indeed recreating a file that was already there, but I'm not sure of its practical uses.

Seems that we went through the same thought processes.
 But there's little point in validating the combinations to somebody's 
 conception of making sense, except for the obvious nonsensicality of UO 
 together.

I made this combination mutually exclusive by applying the rule that the file-exists-action can only have one of three options: Fail, Use, Overwrite. -- Derek Melbourne, Australia
Jul 22 2004
prev sibling next sibling parent "Ben Hinkle" <bhinkle mathworks.com> writes:
To get the behavior Jill describes on Windows, change the two occurrences of
OPEN_ALWAYS in stream.d to
 (mode&FileMode.Out)?OPEN_ALWAYS:OPEN_EXISTING
and recompile phobos. I don't know about Linux.

"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cdlm9m$2kle$1 digitaldaemon.com...
 On the Windows platform:

 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }

 creates the file "foo", does not throw any kind of exception, and then

 on executing as though everything were hunky dory.

 This is currently a very good reason not to use std.stream.File

 Arcane Jill

Jul 21 2004
prev sibling parent reply Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Arcane Jill wrote:
 On the Windows platform:
 
 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }
 
 creates the file "foo", does not throw any kind of exception, and then carries
 on executing as though everything were hunky dory.
 
 This is currently a very good reason not to use std.stream.File
 
 Arcane Jill
 
 

it to. Others requested that it be changed and it was. Just goes to show: you can't please everyone. No matter how hard you try! Andrew
Jul 21 2004
parent reply Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Andrew Edwards wrote:

 Arcane Jill wrote:
 
 On the Windows platform:

 #    import std.stream;
 #
 #    void main()
 #    {
 #        File f = new File("foo"); // where foo does not exist
 #    }

 creates the file "foo", does not throw any kind of exception, and then 
 carries
 on executing as though everything were hunky dory.

 This is currently a very good reason not to use std.stream.File

 Arcane Jill

it to. Others requested that it be changed and it was. Just goes to show: you can't please everyone. No matter how hard you try! Andrew

As a matter of fact, here's the post that prompted the change: http://www.digitalmars.com/d/archives/17539.html
Jul 21 2004
parent Andrew Edwards <ridimz_at yahoo.dot.com> writes:
Andrew Edwards wrote:
 
 As a matter of fact, here's the post that prompted the change:
 
   http://www.digitalmars.com/d/archives/17539.html

Teaches me for opening my mouth too fast. He was talking about "FileMode.Out". I'll shut up now!
Jul 21 2004