Exercises:Files: Difference between revisions

From COMP15212 Wiki
pc>Yuron
No edit summary
 
gravatar W81054ch [userbureaucratinterface-adminsysopPHRhYmxlIGNsYXNzPSJ0d3BvcHVwIj48dHI+PHRkIGNsYXNzPSJ0d3BvcHVwLWVudHJ5dGl0bGUiPkdyb3Vwczo8L3RkPjx0ZD51c2VyPGJyIC8+YnVyZWF1Y3JhdDxiciAvPmludGVyZmFjZS1hZG1pbjxiciAvPnN5c29wPGJyIC8+PC90ZD48L3RyPjwvdGFibGU+] (talk | contribs)
m (1 revision imported)
 
(2 intermediate revisions by 2 users not shown)
Line 12: Line 12:
----
----
<blockquote>
<blockquote>
This exercise uses C calls for access to the file system, not the
This exercise uses C calls for access to the file system, not the underlying O.S. calls.  However, although <em>details</em> vary the <strong>principles</strong> are similar.
underlying O.S. calls.  However, although <em>details</em> vary the
<strong>principles</strong> are similar.
</blockquote>
</blockquote>


==== Part 1 ====
==== Part 1 ====
Compile and run the example <code>file_output.c</code> on a Unix machine.
Compile and run the example <code>file_output.c</code> on a Unix machine. <strong>Be patient!</strong>
<strong>Be patient!</strong>


The code copies input from an internal string to an output
The code copies input from an internal string to an output ‘file’; initially this is the stream <code>stdout</code> but the
‘file’; initially this is the stream <code>stdout</code> but the
behaviour is very similar.
behaviour is very similar.
<blockquote>
<blockquote>
You can check this later by swapping the <code>fputc()</code> (<strong>f</strong>ile <strong>put</strong>
You can check this later by swapping the <code>fputc()</code> (<strong>f</strong>ile <strong>put</strong> <strong>c</strong>haracter) call for the <code>printf()</code>.
<strong>c</strong>haracter) call for the <code>printf()</code>.
</blockquote>
</blockquote>
To make a visible point here, there is a 1 s pause between each
To make a visible point here, there is a 1 s pause between each character output.  The issue is that the characters are output to a
character output.  The issue is that the characters are output to a
<strong>buffer</strong> and the buffer is copied to the display at some later time. In the case of the display (<code>stdout</code>) the buffer is flushed at each newline (’<code>\n</code>’), hence the long wait and then a whole line ‘pops up’.
<strong>buffer</strong> and the buffer is copied to the display at some later time.
In the case of the display (<code>stdout</code>) the buffer is flushed at each
newline (’<code>\n</code>’), hence the long wait and then a whole line
‘pops up’.


Uncomment the line with the <code>fflush()</code> call and repeat the exercise.
Uncomment the line with the <code>fflush()</code> call and repeat the exercise. This is slightly more interesting to watch as buffer-flushing is <em>forced</em> each time around the loop.  This is generally less efficient as many more O.S. calls can be needed.
This is slightly more interesting to watch as buffer-flushing is
<em>forced</em> each time around the loop.  This is generally less efficient
as many more O.S. calls can be needed.


<strong>Experiment</strong> with writing to a <strong>file</strong> instead of (or as well as)
<strong>Experiment</strong> with writing to a <strong>file</strong> instead of (or as well as) <code>stdout</code>.  There is already a call in place (commented) which writes to a file handle and the <code>fopen()</code> and <code>fclose()</code> are also in place.
<code>stdout</code>.  There is already a call in place (commented) which writes
to a file handle and the <code>fopen()</code> and <code>fclose()</code> are also in place.


It should be possible to demonstrate that the file output buffer is
It should be possible to demonstrate that the file output buffer is not flushed on a ‘<code>\n</code>’, only when it has assembled enough data to make a write operation to the disk worthwhile – or the file is closed — or you flush it yourself.
not flushed on a ‘<code>\n</code>’, only when it has assembled enough data to
make a write operation to the disk worthwhile – or the file is closed
— or you flush it yourself.
<blockquote>
<blockquote>
<strong>Exercise</strong>: work out how to <em>input</em> from a file and prove (to
<strong>Exercise</strong>: work out how to <em>input</em> from a file and prove (to yourself) that you have read the information.
yourself) that you have read the information.
Try to do this – at least on paper – before proceeding to Part 2.
Try to do this – at least on paper – before proceeding to Part 2.
</blockquote>
</blockquote>


==== Part 2 ====
==== Part 2 ====
Compile and run the example <code>file_input.c</code> on a Unix machine.  We
Compile and run the example <code>file_input.c</code> on a Unix machine.  We recommend you also download the test file <code>Hamlet.txt</code>.
recommend you also download the test file <code>Hamlet.txt</code>.


Run the application with a filename (string) and two numeric
Run the application with a filename (string) and two numeric arguments, like this:
arguments, like this:
<blockquote>
<blockquote>
<code>./file_input Hamlet.txt 88840 382</code>
<code>./file_input Hamlet.txt 88840 382</code>
Line 76: Line 56:


==== Part 3 ====
==== Part 3 ====
Compile and run the example <code>file_stat.c</code> on a Unix machine.  This
Compile and run the example <code>file_stat.c</code> on a Unix machine.  This illustrates the extraction of [[File Attributes|file <em>attributes</em>]] and will print out some of the attributes for a file name which you supply.  For example (as supplied) it prints <code>UID</code> which is the unique <strong>U</strong>ser <strong>ID</strong>entifier (on that system) for the file’s owner.
illustrates the extraction of [[File_Attributes | file <em>attributes</em>]] and
will print out some of the attributes for a file name which you supply.  For example (as supplied) it prints <code>UID</code> which is the unique <strong>U</strong>ser <strong>ID</strong>entifier (on that system) for the file’s owner.
<blockquote>
<blockquote>
You can find your own UID – or anyone else’s – with the shell
You can find your own UID – or anyone else’s – with the shell command <code>id -u <username></code>.
command <code>id -u <username></code>.
</blockquote>
</blockquote>
Try this with (e.g.) a system file too – probably owned by <code>root</code> (UID 0).
Try this with (e.g.) a system file too – probably owned by <code>root</code> (UID 0).


The example also includes a simple use of <code>errno</code>, the [[Errors | error
The example also includes a simple use of <code>errno</code>, the [[Errors|error code]] returned by the system call.  Include a non-existent filename in your experiments too.
code]] returned by the system call.  Include a non-existent
filename in your experiments too.


<span style="color:green">
<span style="color:green">
Line 94: Line 69:


==== Puzzle/challenge ====
==== Puzzle/challenge ====
Show something of what you now understand with file manipulation with
Show something of what you now understand with file manipulation with a little example.  Here’s one suggestion, using techniques included above:
a little example.  Here’s one suggestion, using techniques included above:


Create a program to which you give a <strong>directory</strong> name and it
Create a program to which you give a <strong>directory</strong> name and it plants creates a short text file <em>within</em> that directory.  BUT it should detect and inform the user (as politely as you wish!) if:
plants creates a short text file <em>within</em> that directory.  BUT it
should detect and inform the user (as politely as you wish!) if:


*the specified directory does not exist
*the specified directory does not exist
*the specified ‘directory’ exists, but is not a directory
*the specified ‘directory’ exists, but is not a directory
----
=== Submission ===
A single text file [<code>ex10.txt</code>] combining a <em>short</em> description of
what your most sophisticated experiment/demonstration does, plus the
source code text.  This should include some examination of file
attributes.
----


==== Revision ====
==== Revision ====
Line 122: Line 85:
There is also some use of [[Exercises:Arguments|command line arguments]].
There is also some use of [[Exercises:Arguments|command line arguments]].
----
----
{{PageGraph}}
{{PageGraph}}
{{Category|Exercises}}
{{Category|Exercises}}

Latest revision as of 10:22, 9 August 2019

On path: Exercises 0: Exercises • 1: Pointer Exercise • 2: Arguments Exercise • 3: Malloc Exercise • 4: Structs Exercise • 5: Processes Exercise • 6: Shared memory Exercise • 7: Pipes Exercise • 8: Exceptions Exercise • 9: Synchronisation Exercise • 10: Files Exercise • 11: Threads Exercise • 12: Unix proc Exercise
Depends on Pointers

Download exercise files

This exercise is concerned with file access and file attributes. The purposes of this exercise are:

  • to demonstrate some basic principles of file handling
  • to reveal some details of a file’s attributes

This exercise uses C calls for access to the file system, not the underlying O.S. calls. However, although details vary the principles are similar.

Part 1

Compile and run the example file_output.c on a Unix machine. Be patient!

The code copies input from an internal string to an output ‘file’; initially this is the stream stdout but the behaviour is very similar.

You can check this later by swapping the fputc() (file put character) call for the printf().

To make a visible point here, there is a 1 s pause between each character output. The issue is that the characters are output to a buffer and the buffer is copied to the display at some later time. In the case of the display (stdout) the buffer is flushed at each newline (’\n’), hence the long wait and then a whole line ‘pops up’.

Uncomment the line with the fflush() call and repeat the exercise. This is slightly more interesting to watch as buffer-flushing is forced each time around the loop. This is generally less efficient as many more O.S. calls can be needed.

Experiment with writing to a file instead of (or as well as) stdout. There is already a call in place (commented) which writes to a file handle and the fopen() and fclose() are also in place.

It should be possible to demonstrate that the file output buffer is not flushed on a ‘\n’, only when it has assembled enough data to make a write operation to the disk worthwhile – or the file is closed — or you flush it yourself.

Exercise: work out how to input from a file and prove (to yourself) that you have read the information. Try to do this – at least on paper – before proceeding to Part 2.

Part 2

Compile and run the example file_input.c on a Unix machine. We recommend you also download the test file Hamlet.txt.

Run the application with a filename (string) and two numeric arguments, like this:

./file_input Hamlet.txt 88840 382

When that has worked okay, explore and understand the source code. It:

  • establishes that it has the arguments it needs
    • using a library to convert some strings to integers
  • opens the chosen file
    • testing that this was successful
  • seeks the chosen position
  • loops, outputting characters in a rather crude way
    • but remembering to check if you’ve fallen out of the file extent
  • reports the new file position indicator (ftell())
  • closes the file

Part 3

Compile and run the example file_stat.c on a Unix machine. This illustrates the extraction of file attributes and will print out some of the attributes for a file name which you supply. For example (as supplied) it prints UID which is the unique User IDentifier (on that system) for the file’s owner.

You can find your own UID – or anyone else’s – with the shell command id -u <username>.

Try this with (e.g.) a system file too – probably owned by root (UID 0).

The example also includes a simple use of errno, the error code returned by the system call. Include a non-existent filename in your experiments too.

Now play!

Puzzle/challenge

Show something of what you now understand with file manipulation with a little example. Here’s one suggestion, using techniques included above:

Create a program to which you give a directory name and it plants creates a short text file within that directory. BUT it should detect and inform the user (as politely as you wish!) if:

  • the specified directory does not exist
  • the specified ‘directory’ exists, but is not a directory

Revision

Three types of pointer operation have been included in this example:

  • *p_char” gets the item (char, in this case) at the address held by p_char.
  • p_char++;” increments the pointer by one element, moving it along the string.
  • &(buffer.st_mtime)” finds the address of a particular field in the struct called “buffer”.

There is also some use of command line arguments.