ADVERTISEMENT
Responsive Ad Unit • Systems Architecture & Low-Level Engineering

Standard I/O Library in UNIX/Linux

The Standard I/O Library provides a high-level interface for performing input and output operations. Instead of directly using low-level system calls such as read() and write(), applications can use buffered streams that simplify programming and improve performance.

Learning Objectives

  • Understand the purpose of the Standard I/O Library.
  • Learn the concept of streams.
  • Understand the three standard streams.
  • Understand buffered I/O.
  • Prepare for Standard I/O functions.

1. What is the Standard I/O Library?

The Standard I/O Library is a collection of library functions that provide a portable and convenient interface for performing input and output operations. Instead of accessing files directly through low-level system calls, programs interact with streams managed by the library.

2. Why is Standard I/O Needed?

  • Simplifies file input and output.
  • Provides a portable programming interface.
  • Supports buffered I/O for improved efficiency.
  • Offers formatted input and output functions.
  • Reduces the number of direct system calls.

3. Relationship Between Standard I/O and System Calls

Application ↓ Standard I/O Library ↓ read() / write() ↓ Kernel ↓ File

The Standard I/O Library is implemented on top of the low-level file I/O system calls provided by the operating system.

4. What is a Stream?

A stream is an abstraction representing a sequence of bytes flowing between a program and an input or output source. The Standard I/O Library performs all operations using streams.

5. Types of Streams

Stream Type Purpose
Input Stream Transfers data into the program.
Output Stream Transfers data out of the program.
Update Stream Supports both reading and writing.

6. Standard Streams

Stream Description Default Device
stdin Standard Input Keyboard
stdout Standard Output Terminal
stderr Standard Error Terminal

7. Stream Communication

Keyboard ↓ stdin ↓ Application ↓ stdout ↓ Terminal ↓ stderr ↓ Error Messages

8. Advantages of Standard I/O

  • Portable across UNIX systems.
  • Supports buffering automatically.
  • Simplifies formatted input and output.
  • Provides convenient file handling functions.
  • Built on top of low-level file descriptors.

9. Standard I/O vs Low-Level I/O

Standard I/O Low-Level I/O
Uses streams Uses file descriptors
Buffered by default Generally unbuffered
Uses FILE * Uses integer file descriptors
Higher-level interface Lower-level interface

10. Interview Questions

  1. What is the Standard I/O Library?
  2. Why is the Standard I/O Library used instead of low-level system calls?
  3. What is a stream?
  4. What are the three standard streams?
  5. What is the difference between Standard I/O and low-level I/O?
  6. Why does buffering improve I/O performance?
  7. What is an update stream?
  8. What is the relationship between the Standard I/O Library and read()/write()?
  9. Which abstraction does Standard I/O use to perform input and output?
  10. Why is the Standard I/O Library considered portable?

11. The FILE Structure

The Standard I/O Library represents every stream using a FILE object. Applications access streams through a pointer to this object rather than accessing its internal members directly.

#include <stdio.h> FILE *fp;

12. What is FILE *?

A FILE * is a pointer to a Standard I/O stream. It identifies an open stream that can be used by Standard I/O functions such as fopen(), fclose(), fread(), and fprintf().

13. FILE Object Lifecycle

Application ↓ fopen() ↓ FILE * ↓ Read / Write ↓ fflush() (Optional) ↓ fclose() ↓ Resources Released

14. Predefined Standard Streams

Every UNIX process begins execution with three predefined Standard I/O streams.

Stream Purpose Type
stdin Standard input FILE *
stdout Standard output FILE *
stderr Standard error FILE *

15. stdin

stdin is the predefined input stream. By default, it receives input from the keyboard, although it may be redirected to another source such as a file or pipe.

16. stdout

stdout is the predefined output stream. By default, output is displayed on the terminal, but it may also be redirected to a file or another process.

17. stderr

stderr is the predefined stream used for error messages. Keeping error output separate from normal program output makes it easier to diagnose problems and redirect outputs independently.

18. fileno()

The fileno() function returns the underlying file descriptor associated with an open Standard I/O stream.

#include <stdio.h> int fileno( FILE *stream );

This function allows interaction between the Standard I/O Library and low-level file descriptor interfaces.

19. Example: Using fileno()

#include <stdio.h> int main() { printf("stdout file descriptor: %d\n", fileno(stdout)); return 0; }

On most UNIX systems, the file descriptor associated with stdout is typically 1, although portable programs should not rely on hard-coded descriptor values when a stream is available.

20. Interview Questions

  1. What is the purpose of the FILE structure?
  2. What does a FILE * represent?
  3. Why should applications avoid accessing the internal members of FILE?
  4. Name the three predefined Standard I/O streams.
  5. What is the default input source for stdin?
  6. What is the default output destination for stdout?
  7. Why is stderr provided separately from stdout?
  8. What is the purpose of fileno()?
  9. How does fileno() connect Standard I/O with low-level I/O?
  10. What type does fileno() return?

21. fopen()

The fopen() function opens a file and associates it with a Standard I/O stream. If successful, it returns a pointer to a FILE object that can be used for subsequent input and output operations.

#include <stdio.h> FILE *fopen( const char *pathname, const char *mode );

22. File Opening Modes

Mode Description
"r" Open an existing file for reading.
"w" Create a new file or truncate an existing file for writing.
"a" Open a file for writing at the end of the file (append).
"r+" Open an existing file for both reading and writing.
"w+" Create or truncate a file for both reading and writing.
"a+" Open or create a file for reading and appending.

23. Example: Using fopen()

#include <stdio.h> int main() { FILE *fp; fp = fopen("sample.txt", "r"); if (fp == NULL) { perror("fopen"); return 1; } fclose(fp); return 0; }

24. freopen()

The freopen() function closes an existing stream and reopens it using a new file and mode. It is commonly used to redirect one stream to another file.

#include <stdio.h> FILE *freopen( const char *pathname, const char *mode, FILE *stream );

25. Example: Using freopen()

#include <stdio.h> int main() { freopen("output.txt", "w", stdout); printf("This goes to the file.\n"); return 0; }

26. fdopen()

The fdopen() function associates an existing file descriptor with a Standard I/O stream. Unlike fopen(), it does not open a new file. Instead, it creates a FILE * that uses an already-open file descriptor.

#include <stdio.h> FILE *fdopen( int fd, const char *mode );

27. Example: Using fdopen()

#include <fcntl.h> #include <stdio.h> #include <unistd.h> int main() { int fd; FILE *fp; fd = open("sample.txt", O_RDONLY); if (fd == -1) return 1; fp = fdopen(fd, "r"); if (fp == NULL) { close(fd); return 1; } fclose(fp); return 0; }

28. fclose()

The fclose() function flushes any buffered output, closes the associated stream, and releases the resources used by the FILE object.

#include <stdio.h> int fclose( FILE *stream );

Returns 0 on success. Returns EOF on failure.

29. Stream Opening and Closing Flow

Application ↓ fopen() ↓ FILE * ↓ Read / Write Operations ↓ fclose() ↓ Buffered Data Flushed ↓ Resources Released

30. Interview Questions

  1. What is the purpose of fopen()?
  2. What is the difference between "w" and "a" modes?
  3. When should freopen() be used?
  4. How does fdopen() differ from fopen()?
  5. Does fdopen() create a new file descriptor?
  6. What happens when fclose() is called?
  7. What does fclose() return on failure?
  8. Why should every successful fopen() eventually be matched with fclose()?
  9. Which function is commonly used to redirect stdout to a file?
  10. Which function associates a Standard I/O stream with an existing file descriptor?

31. Character-Oriented I/O

Character-oriented I/O functions transfer one character at a time between a stream and a program. These functions are useful for processing text files character by character.

32. fgetc()

The fgetc() function reads the next character from the specified input stream.

#include <stdio.h> int fgetc( FILE *stream );

Returns the next character as an unsigned char converted to an int, or EOF if the end of file is reached or an error occurs.

33. getc()

The getc() function performs the same logical operation as fgetc() by reading the next character from a stream. On many implementations, getc() may be implemented as a macro, allowing efficient character input.

#include <stdio.h> int getc( FILE *stream );

34. fgetc() vs getc()

fgetc() getc()
Always implemented as a function. May be implemented as a macro.
Evaluates its argument once. Macro implementations may evaluate arguments differently depending on the implementation.
Portable function interface. Provides the same behavior from the programmer's perspective.

35. Example: Using fgetc()

#include <stdio.h> int main() { FILE *fp; int ch; fp = fopen("sample.txt", "r"); if (fp == NULL) return 1; while ((ch = fgetc(fp)) != EOF) { putchar(ch); } fclose(fp); return 0; }

36. fputc()

The fputc() function writes a single character to the specified output stream.

#include <stdio.h> int fputc( int c, FILE *stream );

Returns the character written as an unsigned char converted to an int, or EOF on failure.

37. putc()

The putc() function performs the same logical operation as fputc() by writing a character to a stream. Like getc(), it may be implemented as a macro.

#include <stdio.h> int putc( int c, FILE *stream );

38. ungetc()

The ungetc() function pushes a character back onto an input stream. The pushed-back character is returned by the next read operation on that stream.

#include <stdio.h> int ungetc( int c, FILE *stream );

Only one pushed-back character is guaranteed to be supported by the C standard, although some implementations may allow more.

39. Character I/O Flow

Input File ↓ fgetc() ↓ Application ↓ Process Character ↓ fputc() ↓ Output File

40. Interview Questions

  1. What is the purpose of fgetc()?
  2. What is the difference between getc() and fgetc()?
  3. Why do fgetc() and getc() return int instead of char?
  4. What value indicates end-of-file for fgetc()?
  5. What is the purpose of fputc()?
  6. How does putc() differ from fputc()?
  7. What does ungetc() do?
  8. How many pushed-back characters does the C standard guarantee?
  9. When is character-oriented I/O preferred?
  10. Why is EOF represented as an int value?

41. Line-Oriented I/O

Line-oriented I/O transfers an entire line of text between a stream and a program. These functions are commonly used for reading and writing text files one line at a time.

42. fgets()

The fgets() function reads at most n - 1 characters from a stream and stores them in a buffer. Reading stops when a newline character is read, the end of file is reached, or the buffer becomes full.

#include <stdio.h> char *fgets( char *str, int n, FILE *stream );

On success, fgets() returns str. On failure or end-of-file before any characters are read, it returns NULL.

43. Example: Using fgets()

#include <stdio.h> int main() { FILE *fp; char buffer[100]; fp = fopen("sample.txt", "r"); if (fp == NULL) return 1; while (fgets(buffer, sizeof(buffer), fp) != NULL) { printf("%s", buffer); } fclose(fp); return 0; }

44. fputs()

The fputs() function writes a null-terminated string to the specified output stream. Unlike puts(), it does not automatically append a newline character.

#include <stdio.h> int fputs( const char *str, FILE *stream );

Returns a non-negative value on success. Returns EOF on failure.

45. Example: Using fputs()

#include <stdio.h> int main() { FILE *fp; fp = fopen("output.txt", "w"); if (fp == NULL) return 1; fputs("Welcome to APUE.\n", fp); fputs("Standard I/O Example\n", fp); fclose(fp); return 0; }

46. Binary I/O

Binary I/O transfers raw bytes between memory and a stream. Unlike text-oriented I/O, binary I/O does not interpret newline characters or text formatting.

47. fread()

The fread() function reads binary data from a stream into memory.

#include <stdio.h> size_t fread( void *ptr, size_t size, size_t nmemb, FILE *stream );
Parameter Description
ptr Destination memory buffer.
size Size of each object in bytes.
nmemb Number of objects to read.
stream Input stream.

Returns the number of complete objects successfully read.

48. fwrite()

The fwrite() function writes binary data from memory to a stream.

#include <stdio.h> size_t fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream );

Returns the number of complete objects successfully written.

49. Example: Binary File Copy

#include <stdio.h> int main() { FILE *src; FILE *dst; char buffer[512]; size_t bytes; src = fopen("input.bin", "rb"); dst = fopen("output.bin", "wb"); if (src == NULL || dst == NULL) return 1; while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) { fwrite(buffer, 1, bytes, dst); } fclose(src); fclose(dst); return 0; }

50. Interview Questions

  1. What is the purpose of fgets()?
  2. How does fgets() differ from gets()?
  3. Why is gets() considered unsafe?
  4. Does fputs() automatically append a newline character?
  5. What is the return value of fputs() on failure?
  6. What is binary I/O?
  7. Explain the parameters of fread().
  8. What does fwrite() return?
  9. When should binary I/O be preferred over text I/O?
  10. How can fread() be used to copy a binary file?

51. Formatted Input and Output

Formatted I/O functions convert data between its internal binary representation and a human-readable text representation. These functions support conversion specifications that control how data is read from or written to streams.

52. printf() and fprintf()

The printf() function writes formatted output to stdout. The fprintf() function writes formatted output to any specified stream.

#include <stdio.h> int printf( const char *format, ... ); int fprintf( FILE *stream, const char *format, ... );

53. Example: Using printf() and fprintf()

#include <stdio.h> int main() { FILE *fp; fp = fopen("result.txt", "w"); if (fp == NULL) return 1; printf("Value = %d\n", 100); fprintf(fp, "Value = %d\n", 100); fclose(fp); return 0; }

54. sprintf()

The sprintf() function writes formatted output to a character array instead of a stream. The destination buffer must be large enough to hold the resulting string.

#include <stdio.h> int sprintf( char *str, const char *format, ... );

55. snprintf()

The snprintf() function performs the same operation as sprintf() but limits the maximum number of bytes written to the destination buffer. This makes it safer for fixed-size buffers.

#include <stdio.h> int snprintf( char *str, size_t size, const char *format, ... );

56. Example: Using snprintf()

#include <stdio.h> int main() { char buffer[50]; snprintf(buffer, sizeof(buffer), "Temperature = %d C", 35); printf("%s\n", buffer); return 0; }

57. scanf(), fscanf(), and sscanf()

The formatted input functions convert text into program variables.

Function Input Source
scanf() stdin
fscanf() Specified stream
sscanf() Character string

58. Example: Using fscanf()

#include <stdio.h> int main() { FILE *fp; int number; fp = fopen("number.txt", "r"); if (fp == NULL) return 1; fscanf(fp, "%d", &number); printf("Number = %d\n", number); fclose(fp); return 0; }

59. Formatted I/O Flow

Application Variables ↓ printf() ↓ Formatting Engine ↓ FILE Stream ↓ Output Device Input Device ↓ FILE Stream ↓ scanf() ↓ Application Variables

60. Interview Questions

  1. What is formatted I/O?
  2. What is the difference between printf() and fprintf()?
  3. When should sprintf() be avoided?
  4. Why is snprintf() considered safer?
  5. How does fprintf() differ from fputs()?
  6. What is the purpose of scanf()?
  7. Compare scanf(), fscanf(), and sscanf().
  8. Why should the return value of formatted input functions be checked?
  9. What happens if the destination buffer is too small when using sprintf()?
  10. Which function writes formatted output to a character array with a size limit?

61. Stream Buffering

The Standard I/O Library uses buffers to reduce the number of system calls required for input and output operations. Instead of immediately performing every read or write request, data is temporarily stored in memory and transferred in larger blocks.

62. setbuf() and setvbuf()

The setbuf() and setvbuf() functions control the buffering behavior of a stream.

#include <stdio.h> void setbuf( FILE *stream, char *buf ); int setvbuf( FILE *stream, char *buf, int mode, size_t size );
Mode Description
_IOFBF Fully buffered
_IOLBF Line buffered
_IONBF Unbuffered

63. fflush()

The fflush() function forces any buffered output for a stream to be written to its underlying file.

#include <stdio.h> int fflush( FILE *stream );

Returns 0 on success. Returns EOF on failure.

64. File Positioning

The Standard I/O Library provides functions for moving and querying the current file position within a stream. These functions support random access to files.

65. fseek(), ftell(), and rewind()

Function Purpose
fseek() Move the file position indicator.
ftell() Return the current file position.
rewind() Move to the beginning of the file.
#include <stdio.h> int fseek(FILE *stream, long offset, int whence); long ftell(FILE *stream); void rewind(FILE *stream);

66. fgetpos() and fsetpos()

The fgetpos() function saves the current file position, while fsetpos() restores a previously saved position. These functions use the portable fpos_t type instead of a numeric file offset.

#include <stdio.h> int fgetpos( FILE *stream, fpos_t *pos ); int fsetpos( FILE *stream, const fpos_t *pos );

67. Stream Error Handling

Function Purpose
feof() Test the end-of-file indicator.
ferror() Test the stream error indicator.
clearerr() Clear both EOF and error indicators.
perror() Display a message describing the current errno value.

68. Standard I/O Workflow

Open Stream ↓ Configure Buffer ↓ Read / Write ↓ Flush Buffer ↓ Move File Position ↓ Check EOF / Errors ↓ Close Stream

70. Key Takeaways

  • Standard I/O operates on FILE * streams.
  • Buffering improves I/O efficiency by reducing system calls.
  • fopen() and fclose() manage stream lifetime.
  • Character, line, binary, and formatted I/O each serve different purposes.
  • snprintf() is generally preferred over sprintf() for fixed-size buffers.
  • fseek(), ftell(), rewind(), fgetpos(), and fsetpos() provide file positioning.
  • feof(), ferror(), and clearerr() help detect and recover from stream status conditions.
  • Always close streams with fclose() after use.

71. Advanced Interview Questions

  1. Explain the relationship between Standard I/O streams and low-level file descriptors.
  2. When should fdopen() be preferred over fopen()?
  3. Compare character-oriented, line-oriented, binary, and formatted I/O.
  4. Explain the difference between sprintf() and snprintf().
  5. Describe the three buffering modes supported by setvbuf().
  6. Differentiate fflush() and fclose().
  7. Compare fseek()/ftell() with fgetpos()/fsetpos().
  8. How can a program distinguish between end-of-file and an input error?
  9. Why should the return value of formatted input functions always be checked?
  10. Design a program that copies one file to another while preserving binary data.
Knowledge Check

Concept Mastery Assessment — Module 25

Verify your conceptual understanding with 12 targeted technical assessment questions. Instant feedback and explanations are provided for every choice.

Question 1 of 12
What is the primary architectural purpose of Standard I/O Library, Buffering & Streams in operating systems?
Explanation
Standard I/O Library, Buffering & Streams is designed to manage file pointer streams, unbuffered (_ionbf), line-buffered (_iolbf), fully buffered (_iofbf), fflush mechanics, and temporary files. within the operating system architecture.
Question 2 of 12
Which system interface or data structure is centrally associated with Standard I/O Library, Buffering & Streams?
Explanation
Under POSIX and Linux, Standard I/O Library, Buffering & Streams operates through standardized system calls and kernel control structures.
Question 3 of 12
What safety or concurrency constraint must developers consider when implementing Standard I/O Library, Buffering & Streams?
Explanation
Proper synchronization, avoidance of race conditions, and handling reentrant execution are critical when working with Standard I/O Library, Buffering & Streams.
Question 4 of 12
When a system call related to Standard I/O Library, Buffering & Streams fails in C, how does the POSIX runtime conventionally report the failure?
Explanation
Standard POSIX system calls return -1 or NULL on error, assigning an error integer (e.g. EINVAL, EPERM, EAGAIN) to the thread-local errno variable.
Question 5 of 12
What is the primary performance tradeoff associated with Standard I/O Library, Buffering & Streams?
Explanation
Operations involving Standard I/O Library, Buffering & Streams balance performance against kernel transition, memory bandwidth, and cache locality tradeoffs.
Question 6 of 12
What security principle governs access to resources in Standard I/O Library, Buffering & Streams?
Explanation
The kernel validates credentials, effective permissions, and Linux capabilities before granting access to protected operations.
Question 7 of 12
How does execution of Standard I/O Library, Buffering & Streams transition between User Space and Kernel Space?
Explanation
User space transitions to kernel mode securely via software traps or SYSCALL instructions that switch processor rings to Ring 0.
Question 8 of 12
What happens to resources allocated by Standard I/O Library, Buffering & Streams when the owning process terminates?
Explanation
Process resources (open fds, memory maps) are automatically reclaimed by the kernel on termination, while kernel-persistent objects survive.
Question 9 of 12
In production Linux server environments, how is Standard I/O Library, Buffering & Streams optimized for high throughput?
Explanation
Linux optimizes throughput via zero-copy data paths, asynchronous kernel events, and scalable concurrency primitives.
Question 10 of 12
What standard governs the portability of Standard I/O Library, Buffering & Streams across Unix, Linux, and macOS platforms?
Explanation
IEEE POSIX standards define consistent APIs across Unix-like platforms ensuring portable source code execution.
Question 11 of 12
Which command-line diagnostic tool is most effective for inspecting and troubleshooting Standard I/O Library, Buffering & Streams at runtime?
Explanation
Utilities like strace, lsof, and the /proc filesystem provide direct visibility into kernel interactions and resource status.
Question 12 of 12
What is a critical production best practice when developing systems software involving Standard I/O Library, Buffering & Streams?
Explanation
Defensive programming requires explicit error checking on all system operations, proper resource cleanup, and avoiding memory corruption.
0 / 12 (0%)
Great job! Review the concepts above and proceed when ready.
ADVERTISEMENT
Responsive Ad Unit • Technical Courses & Certifications