PDA

View Full Version : Filehandle, wrappers etc




mdeh
Feb 16, 2009, 08:10 AM
I have been searching the docs, and ( where else) wikipedia for some very basic understanding of exactly **what** a filehandle "is".

Wikipedia says this.

In computer programming, a file descriptor is an abstract key for accessing a file. The term is generally used in POSIX operating systems. In Microsoft Windows terminology and in the context of the C standard I/O library, "file handle" is preferred, though the latter case is technically a different object (see below).

and

The FILE * file handle in the C standard I/O library routines is technically a pointer to a data structure managed by those library routines; one of those structures usually includes an actual low level file descriptor for the object in question on Unix-like systems. Since file handle refers to this additional layer, it is not interchangeable with file descriptor.


As the word "wrapper" seems to pop-up ( often in the documentation in Xcode,without ever formally defining it..well, I could not find it) again, I wonder if someone could just briefly and conceptually define these 2 terms.

thanks in advance.



lee1210
Feb 16, 2009, 08:48 AM
I don't have ready access to an OS X machine, but on a linux machine this is what the definition of _IO_FILE is, which is what FILE is typedef'd to:

struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

/* The following pointers correspond to the C++ streambuf protocol. */
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */

struct _IO_marker *_markers;

struct _IO_FILE *_chain;

int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */

#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];

/* char* _save_gptr; char* _save_egptr; */

_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};


In this case, the int _fileno will actually hold a file descriptor. On a unix or unix-like system such as linux or OS X, everything is treated as a file, so any network connection, actual filesystem object, pipe, etc. will have a file descriptor.

The file descriptor is the "lowest level" description of the file for that process. The library that is responsible for I/O will keep track of other things about the file based on the descriptor, so you don't have to carry all of that info around with you in your own code.

The FILE structure takes a different approach, in that you will take a lot of information about the file being accessed with you in your own code. A lot of "state" in terms of the file's current offset, etc. is available in the FILE structure for use by I/O routines.

The term "wrapper" in this case would refer to the FILE structure, as it obscures the low-level file descriptor from the programmer, wrapping it in a structure that for the most part can be unknown to the programmer using it. Generally a wrapper is any additional code, data structures, objects, etc. that abstract something low-level, hopefully with the intent of making it easier to use. An example would be a simple network communication library. The programmer using it would just need to call a few simple methods, and all of the "dirty work" of setting up sockets, etc. would be abstracted away. This would be considered a wrapper for low-level networking code.

Sometimes a wrapper might also be used to make it easier to call a complex function. Perhaps you have everything you need to call the function in a structure, but don't want to type out the names of all the fields each time you want to invoke the function. You could write a wrapper that takes your structure, then calls the function, and returns the result, etc. This way in your code you'd just call the wrapper with the structure being the sole argument, and it looks much cleaner.

Other times you might want to use this kind of abstraction would be in making calls between programming languages, etc. You might need to massage values, change any passes by value to passes by reference, etc. that is easier to do correctly once, then reuse in the future, rather than always doing all of the nitty-gritty work for each invocation.

-Lee

mdeh
Feb 16, 2009, 09:17 AM
I don't have ready access to an OS X machine, but on a linux machine this is what the definition of _IO_FILE is, which is what FILE is typedef'd to:

struct _IO_FILE {
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */
#define _IO_file_flags _flags

.....snip.....
int _fileno;
#if 0
int _blksize;
#else
int _flags2;
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */

#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];

/* char* _save_gptr; char* _save_egptr; */

_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE
};




[QUOTE]
The file descriptor is the "lowest level" description of the file for that process. The library that is responsible for I/O will keep track of other things about the file based on the descriptor, so you don't have to carry all of that info around with you in your own code.

So, clearly that has to be a unique number?



The FILE structure takes a different approach, in that you will take a lot of information about the file being accessed with you in your own code. A lot of "state" in terms of the file's current offset, etc. is available in the FILE structure for use by I/O routines.


I **think** you are implying that the FILE * ( as used in C) is of this approach.



The term "wrapper" in this case would refer to the FILE structure, as it obscures the low-level file descriptor from the programmer, wrapping it in a structure that for the most part can be unknown to the programmer using it. Generally a wrapper is any additional code, data structures, objects, etc. that abstract something low-level
............snip..........
Sometimes a wrapper might also be used to make it easier to call a complex function.

Thank you ....thank you. You hit the essence of my question.

All of this has come up as I am on Chap 16 of Kochans Book, and was trying to understand the essence of the differences in the use of NSFileHandle vs NSFileManager/Utilities classes.
So, to stick my neck out:

NSFileHandle seems to deal with "intra-file" operations, like reading, writing, etc/

vs

NSFileManager seems to deal with "bigger picture" type file operations,like creating, copying etc.

One last question...well, hopefully last....:) ...seemingly unrelated but perhaps not.

I **think** a (file) path can exist without a file/directory existing, but an existing file/directory cannot exist without a path. So, is my understanding correct that in creating a file, one first needs to create a path, then create that file?

Lee...thank you again for always taking the time to answer these questions. Hopefully, one day, I too will be as knowledgeable.

Cromulent
Feb 16, 2009, 09:49 AM
I **think** a (file) path can exist without a file/directory existing, but an existing file/directory cannot exist without a path. So, is my understanding correct that in creating a file, one first needs to create a path, then create that file?

Lee...thank you again for always taking the time to answer these questions. Hopefully, one day, I too will be as knowledgeable.

A path is just a high level representation of where a file is stored. It bears no relation to where the file is actually stored as generally files can be spread out in lots of different areas of the disk.

Without a file there is no path, as the path is just a way of describing the location of a file. Also a directory is just a file. Unix treats everything as a file. Serial connections, text documents, sockets, all can be read and written too in the same way.

Hopefully my inane ramblings have been helpful.

lee1210
Feb 16, 2009, 10:02 AM
So, clearly that has to be a unique number?


At any given time, each file opened by a process has a unique number, yes. Once a file is closed, the number may be reused, though. This means you should be sure to set the file descriptor in your code to 0 after you close it, so you don't get confused later and reuse the file descriptor that may now be referring to a new file that you've opened since closing the original.


I **think** you are implying that the FILE * ( as used in C) is of this approach.


I included the code to show what was actually being pointed to by a FILE *. There's a lot of extra information available in this structure, so the library doesn't have to keep track of as much internally.


NSFileHandle seems to deal with "intra-file" operations, like reading, writing, etc/

Yes, and this is a wrapper for a file descriptor. It abstracts the lower-level functions actually used for accessing a file.


NSFileManager seems to deal with "bigger picture" type file operations,like creating, copying etc.

Right.


I **think** a (file) path can exist without a file/directory existing, but an existing file/directory cannot exist without a path. So, is my understanding correct that in creating a file, one first needs to create a path, then create that file?

A path is pretty much an address. You can write the address 7384 Poppy Lane on a sheet of paper, and that seems like an address, but it doesn't mean there's anything at that address, or that there is such an address, or that there is even a Poppy Lane. That's pretty much what a path is. You can create any path you'd like, but the existence of a file/directory at that location is not assured. The address metaphor sort of breaks down going the other direction... i suppose you could have a house without an address... but basically, yes, once a file or directory exists in the file system, there is a path (perhaps many with symlinks, etc.) to that file (a directory is also a file). As for "creation"... i guess i'd say that the act of creating a file also cements its path. You'd need to know where you wanted to put it, so I guess technically, yes, you'd need to "create" the path first.


Lee...thank you again for always taking the time to answer these questions. Hopefully, one day, I too will be as knowledgeable.

No problem. Everyone starts somewhere. The more knowledge that's out there, the better off we all are, in my opinion.

-Lee

mdeh
Feb 16, 2009, 10:06 AM
Lee...thanks again. Your explanations are very helpful.

mdeh
Feb 16, 2009, 10:07 AM
Hopefully my inane ramblings have been helpful.

Don't sell yourself short. Your input to me is very helpful and much appreciated.