0% found this document useful (0 votes)
3 views

Advanced Programming ch2

Chapter 2 discusses systems programming, focusing on file descriptors, file handling, and stream classes in Java. It explains how file descriptors represent open files and how Java's FileDescriptor class manages them, along with methods for reading and writing files using various stream classes. Additionally, it covers file locking mechanisms and creating processes using the ProcessBuilder and Runtime classes.

Uploaded by

eyob.ketemaw
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Advanced Programming ch2

Chapter 2 discusses systems programming, focusing on file descriptors, file handling, and stream classes in Java. It explains how file descriptors represent open files and how Java's FileDescriptor class manages them, along with methods for reading and writing files using various stream classes. Additionally, it covers file locking mechanisms and creating processes using the ProcessBuilder and Runtime classes.

Uploaded by

eyob.ketemaw
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 97

CHAPTER 2

SYSTEMS PROGRAMMING
FILE DESCRIPTOR

■ Whenever a file is opened, the operating system creates an entry to


represent this file and stores its information.

■ Each entry is represented by an integer value and this entry is


termed as file descriptor.

■ A File Descriptor is an integer number assigned by the OS to


represent an open file or other I/O resource.

■ In Java, this is managed through the java.io.FileDescriptor class,


which acts as a wrapper around the system file descriptor.
CONT…

■ Basically, Java class FileDescriptor provides a handle to the underlying


machine-specific structure representing an open file, an open
socket, or another source or sink of bytes.

■ The applications should not create FileDescriptor objects, they are


mainly used in creation
of FileInputStream or FileOutputStream objects to contain it.
CONT…
■ Java internally uses native file descriptors when working with files
and sockets.
■ FileDescriptor class provides a way to manipulate these
descriptors directly.
■ Common use cases include reading/writing files, network
communication, and interprocess communication.
■ Most operating systems define three standard file descriptors:
– in Standard input (keyboard input)
– out Standard output (console output)
– err Standard error (error messages)
CONT …

■ FileDescriptor fdIn = FileDescriptor.in; //


Standard Input
■ FileDescriptor fdOut = FileDescriptor.out; //
Standard Output
■ FileDescriptor fdErr = FileDescriptor.err; //
Standard Error
METHODS IN FILEDESCRIPTOR

■ valid() Checks if the file descriptor is still valid


■ sync() Forces any updates to be written to the disk immediately
FILES
FILES AND STREAMS (CONT.)

■ File streams can be used to input and output data as bytes or characters.

■ Streams that input and output bytes are known as byte-based streams, representing data in

its binary format.

■ Streams that input and output characters are known as character-based streams,

representing data as a sequence of characters.

■ Files that are created using byte-based streams are referred to as binary files.

■ Files created using character-based streams are referred to as text files.

■ Text files can be read by text editors.

■ Binary files are read by programs that understand the specific content of the file and the

ordering of that content.


FILES AND STREAMS (CONT.)

■ A Java program opens a file by creating an object and associating a stream of bytes or

characters with it.


– Can also associate streams with different devices.

■ Java creates three stream objects when a program begins executing


– System.in (the standard input stream object) normally inputs bytes from the keyboard
– System.out (the standard output stream object) normally outputs character data to the
screen
– System.err (the standard error stream object) normally outputs character-based error
messages to the screen.

■ Class System provides methods setIn, setOut and setErr to redirect the standard input, output

and error streams, respectively.


FILES AND STREAMS (CONT.)

■ Java programs perform file processing by using classes from package java.io.

■ Includes definitions for stream classes


– FileInputStream (for byte-based input from a file)
– FileOutputStream (for byte-based output to a file)

– FileReader (for character-based input from a file)


– FileWriter (for character-based output to a file)

■ You open a file by creating an object of one these stream classes. The object’s

constructor opens the file.


FILES AND STREAMS (CONT.)
■ Can perform input and output of objects or variables of
primitive data types without having to worry about the details
of converting such values to byte format.
■ To perform such input and output, objects of classes
ObjectInputStream and ObjectOutputStream can be used
together with the byte-based file stream classes
FileInputStream and FileOutputStream.
■ The complete hierarchy of classes in package java.io can be
viewed in the online documentation at
■ http://download.oracle.com/javase/6/docs/api/java/io/package-tr
ee.html
FILES AND STREAMS (CONT.)

■ Class File provides information about files and directories.


■ Character-based input and output can be performed with classes Scanner and
Formatter.
– Class Scanner is used extensively to input data from the keyboard. This
class can also read data from a file.
– Class Formatter enables formatted data to be output to any text-based
stream in a manner similar to method System.out.printf.
CLASS FILE
■ Although most of the classes defined by java.io operate on streams,
the File class
does not.
■ It deals directly with files and the file system.
■ That is, the File class does not specify how information is retrieved
from or stored in files; it describes the properties of a file itself.
■ A File object is used to obtain or manipulate the information
associated with a disk file, such as the permissions, time,
date, and directory path, and to navigate
subdirectory hierarchies.

13
CLASS FILE
■ A directory in Java is treated simply as a File with one additional property—a list of
filenames that can be examined by the list( ) method.
■ Class File provides four constructors.
– File(String directoryPath)
– File(String directoryPath, String filename)
– File(File dirObj, String filename)
– File(URI uriObj)

■ The one with a String argument specifies the name of a file or directory to associate
with the File object.
– The name can contain path information as well as a file or directory name.
– A file or directory’s path specifies its location on disk.
– An absolute path contains all the directories, starting with the root directory, that
lead to a specific file or directory.
– A relative path normally starts from the directory in which the application began
executing and is therefore “relative” to the current directory.
CLASS FILE (CONT.)
■ The SECOND constructor with two String arguments specifies

– an absolute or relative path and

– the file or directory to associate with the File object.

■ The THIRD constructor with File and String arguments uses an existing File object that
specifies the parent directory of the file or directory specified by the String argument.

■ The fourth constructor uses a URI object to locate the file.

– A Uniform Resource Identifier (URI) is a more general form of the Uniform Resource
Locators (URLs) that are used to locate websites.

■ Figure 17.2 lists some common File methods. The

■ http://download.oracle.com/javase/6/docs/api/java/io/File.html
METHODS
■ File defines many methods that obtain the standard properties of a
File object.
■ For example,
– getName( ) returns the name of the file;
– getParent( ) returns the name of the parent directory; and
– exists( ) returns true if the file exists, false if it does not.

16
EXAMPLE

17
CLASS FILE (CONT.)

■ A separator character is used to separate directories and files in the path.


■ On Windows, the separator character is a backslash (\).
■ On Linux/UNIX, it’s a forward slash (/).
■ Java processes both characters identically in a path name.
■ When building Strings that represent path information, use File.separator to
obtain the local computer’s proper separator.
– This constant returns a String consisting of one character—the proper
separator for the system.
DIRECTORY
DIRECTORY
■ A directory is a File that contains a list of other files and directories.
■ When you create a File object that is a directory, the isDirectory( )
method will return true.
■ In this case, you can call list( ) on that object to extract the list of other
files and
directories inside. It has two forms.
■ The first is shown here:
String[ ] list( )
The list of files is returned in an array of String objects

27
EXAMPLE

28
THE LISTFILES( ) ALTERNATIVE
■ There is a variation to the list( ) method, called listFiles( ), which you might find
useful.
■ The signatures for listFiles( ) are shown here:

– File[ ] listFiles( )
– File[ ] listFiles(FilenameFilter FFObj)
– File[ ] listFiles(FileFilter FObj)

■ These methods return the file list as an array of File objects instead of strings.
■ The first method returns all files, and
■ the second returns those files that satisfy the specified FilenameFilter.
■ The third version of listFiles( ) returns those files with path names that satisfy the specified
FileFilter.
■ FileFilter defines only a single method, accept( ), which is called once for each file in a list.
– The accept( ) method returns true for files that should be included in the list (that is,
those that match the path argument) and false for those that should be excluded.

29
CREATING
DIRECTORIES
■ Another two useful File utility methods are mkdir( ) and mkdirs( ).
■ The mkdir( ) method creates a directory, returning true on success
and false on failure.
– Failure can occur for various reasons, such as the path specified in
the File object already exists, or the directory cannot be created
because the entire path does not exist yet.
■ To create a directory for which no path exists, use the mkdirs( )
method. It creates

30
I/O EXCEPTIONS
■ Two exceptions play an important role in I/O handling.
– The first is IOException.
– if a file cannot be opened, a FileNotFoundException is thrown.
■ FileNotFoundException is a subclass of IOException, so both can be
caught with a single catch that catches IOException.

■ Another exception class that is sometimes important when performing I/O


is
SecurityException thrown when A security violation occurs when
attempting to open a file.

31
READ & WRITING
FILES
CONT …
■ Java provides a number of classes and methods that allow you to read and write
files.

■ Two of the most often-used stream classes are FileInputStream and


FileOutputStream, which create byte streams linked to files.
■ To open a file, you simply create an object of one of these classes, specifying the
name of the file as an
argument to the constructor. Although both classes support additional constructors,
the following are the forms that we will be using:
– FileInputStream(String fileName) throws FileNotFoundException
– FileOutputStream(String fileName) throws FileNotFoundException

■ Here, fileName specifies the name of the file that you want to open.

33
CONT…
■ When you create an input stream, if the file does not exist, then
FileNotFoundException is thrown.
■ For output streams, if the file cannot be opened or created, then
FileNotFoundException is thrown.
■ FileNotFoundException is a subclass of IOException.

■ When an output file is opened, any preexisting file by the same name is
destroyed.
■ When you are done with a file, you must close it.
■ This is done by calling the close( ) method, which is implemented by both
FileInputStream and FileOutputStream. It is shown here:

– void close( ) throws IOException

34
FILEINPUTSTREAM
■ The FileInputStream class creates an InputStream that you can use to read
bytes from a file.
■ Two commonly used constructors are shown here:
FileInputStream(String filePath)
FileInputStream(File fileObj)

■ To read from a file, you can use a version of read( ) that is defined within
FileInputStream.
■ The one that we will use is shown here:
int read( ) throws IOException
■ Each time that it is called, it reads a single byte from the file and returns the
byte as
an integer value. read( ) returns –1 when an attempt is made to read at the
end of the
stream.
■ It can throw an IOException.
35
FILEOUTPUTSTREAM
■ FileOutputStream creates an OutputStream that you can use to write bytes to a
file.
■ It implements the AutoCloseable, Closeable, and Flushable interfaces.
■ Four of its constructors are shown here:
FileOutputStream(String filePath)
FileOutputStream(File fileObj)
FileOutputStream(String filePath, boolean append)
FileOutputStream(File fileObj, boolean append)

■ They can throw a FileNotFoundException. Here, filePath is the full path name of a
file, and fileObj is a File object that describes the file. If append is true, the file is
opened in append mode.

■ Creation of a FileOutputStream is not dependent on the file already existing.


■ FileOutputStream will create the file before opening it for output when you create
the object.
■ In the case where you attempt to open a read-only file, an exception will
be thrown.
36
FILEREADER
■ The FileReader class creates a Reader that
you can use to read the contents of a
file.
■ Two commonly used constructors are shown
here:

– FileReader(String filePath)

– FileReader(File fileObj)

■ Either can throw a FileNotFoundException.


– Here, filePath is the full path name of a file,
and
– fileObj is a File object that describes the
file.

– The following example shows how to read


lines from a file and display them on
the standard output device.
– It reads its own source file, which must be
in the current directory.
37
FILEWRITER
■ creates a Writer that you can use to write
to a file. Four commonly used constructors • FileWriter will create the file before opening it
are shown here:
for output when you create the object.
• In the case where you attempt to open a read-
– FileWriter(String filePath)
only file, an IOException will be thrown.
– FileWriter(String filePath, boolean
append)
– FileWriter(File fileObj)
– FileWriter(File fileObj, boolean
append)

■ They can all throw an IOException.


■ Here, filePath is the full path name of a
file,and
■ fileObj is a File object that describes the
file.
■ If append is true, then output is appended
to the end of the file.

■ Creation of a FileWriter is not dependent


38
on the file already existing.
FILE LOACKING
FILE LOCKING

■ File locking is a mechanism that allows you to prevent multiple processes or threads from
concurrently accessing or modifying the same file.
■ In Java, you can use the java.nio.channels package to lock a file or a portion of a file.
■ There are two types of file locks: shared locks and exclusive locks.
■ A shared lock allows multiple processes or threads to read from the locked file, but only one process
or thread can hold an exclusive lock, which allows it to read from and write to the locked file.
FILE LOCKING …
■ Here's an example of how to obtain a file lock in Java :
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
public class FileLockExample {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile("myFile.txt",
"rw");
FileChannel channel = file.getChannel();
// Obtain an exclusive lock on the entire file
FileLock lock = channel.lock();
// Do some work with the file // ... // Release the lock lock.release();
channel.close();
file.close();
PROCESS
CREATING PROCESSES
■ In Java, you can create a new process using the ProcessBuilder or Runtime class.
■ Both classes provide a way to execute an external program as a separate process from your
Java application.
■ Here's an example of how to use ProcessBuilder to create a new process:

import java.io.*;
public class CreateProcessExample {
public static void main(String[] args) throws IOException, InterruptedException
{ // Create a ProcessBuilder instance for the external program
ProcessBuilder processBuilder = new ProcessBuilder("notepad.exe", "test.txt"); // Start the external program
Process process = processBuilder.start(); // Wait for the process to finish
int exitCode = process.waitFor(); // Print the exit code of the process
System.out.println("Process exited with code " + exitCode);
}
}
CONT…

• In this example, we create a ProcessBuilder instance for the "notepad.exe" program


and pass it the "test.txt" file as an argument.
• We then start the external program using the start() method of the ProcessBuilder
class.
• Finally, we wait for the process to finish using the waitFor() method of the Process
class, and print the exit code of the process.
• Alternatively, you can use the Runtime class to create a new process. Here's an
example:
PROCESSES …
import java.io.*;
public class CreateProcessExample {
public static void main(String[] args) throws IOException, InterruptedException {
// Create a Runtime instance
■ In this example, we create a Runtime instance and use its
Runtime runtime = Runtime.getRuntime(); exec() method to start the external program.
// Start the external program ■ The arguments for the program are passed as a single
string. We then wait for the process to finish and print the
Process process = runtime.exec("notepad.exe test.txt"); exit code.
// Wait for the process to finish ■ Note that creating a new process in Java can be a
int exitCode = process.waitFor(); complex operation, and you need to handle errors and
exceptions properly.
// Print the exit code of the process
■ You should also be careful when executing external
System.out.println("Process exited with code " + exitCode); programs, especially if they are provided by untrusted
sources.
}
}
1. PROCESS MANAGEMENT
■ In Java, you can manage processes using the Process class, which represents an external process that
is running on the operating system.
■ The Process class provides methods for controlling and monitoring the execution of the process.
■ Here are some of the methods provided by the Process class:
•destroy(): Terminates the process abruptly.
•waitFor(): Waits for the process to terminate and returns the exit code of the process.
•exitValue(): Returns the exit code of the process if it has already terminated.
•isAlive(): Returns true if the process is still running.
•getInputStream(), getOutputStream(), and getErrorStream(): Provide input, output, and error
streams for the process, respectively.
PROCESS MANAGEMENT …
import java.io.*;
public class ProcessManagementExample {
public static void main(String[] args) throws IOException, InterruptedException {
// Start the external program
Process process = Runtime.getRuntime().exec("notepad.exe test.txt");
// Check if the process is still running
if (process.isAlive()) {
// Print the process ID
System.out.println("Process ID: " + process.pid());
// Get the input and error streams of the process
PROCESS MANAGEMENT …
BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
// Print the output and error messages of the process
String line;
while ((line = input.readLine()) != null) {
System.out.println("Output: " + line);
}
while ((line = error.readLine()) != null) {
System.out.println("Error: " + line);
}
// Wait for the process to finish
int exitCode = process.waitFor();
System.out.println("Process exited with code " + exitCode);
} ■ In this example, we start the external program "notepad.exe" and check if it is still running using the isAlive()
} method.
}
■ We then print the process ID, and get the input and error streams of the process using the getInputStream() and
getErrorStream() methods.
■ We then print the output and error messages of the process, and wait for it to finish using the waitFor() method.
Finally, we print the exit code of the process.
2. PIPES AND SIGNALS
■ In Java, you can use pipes and signals to communicate between processes.
■ Pipes allow you to send data between two processes. In Java, you can use the
PipedInputStream and PipedOutputStream classes to implement pipes. Here's an
example:

import java.io.*;
public class PipeExample {
public static void main(String[] args) throws IOException {
// Create a PipedInputStream and a PipedOutputStream
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream(in);
// Write some data to the output stream
out.write("Hello, world!".getBytes());
PIPEEXAMPLE

// Read the data from the input stream


byte[] buffer = new byte[1024];
int bytesRead = in.read(buffer);
String message = new String(buffer, 0, bytesRead);
System.out.println(message);
// Close the streams out.close();
in.close();
}
}
PIPES AND SIGNALS
■ In this example, we create a PipedInputStream and a PipedOutputStream. We write some data to the output stream
using the write() method of the PipedOutputStream, and then read the data from the input stream using the read()
method of the PipedInputStream.
■ Signals allow you to send notifications between processes. In Java, you can use the Signal class to send and receive
signals.
■ However, note that signal handling is platform-specific and may not work on all operating systems. Here's an
example:
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class SignalExample {
public static void main(String[] args) throws InterruptedException
{
// Create a signal handler
SignalHandler handler = new SignalHandler() {
@Override
public void handle(Signal signal) {
System.out.println("Received signal: " + signal.getName());
}
SIGNAL EXAMPLE

// Register the signal handler for the TERM signal


Signal.handle(new Signal("TERM"), handler);
// Wait for the TERM signal
Thread.sleep(Long.MAX_VALUE);
}
}
PIPES AND SIGNALS

■ In this example, we create a signal handler that prints a message when a signal is
received.
■ We register the signal handler for the TERM signal using the Signal.handle() method,
and then wait for the TERM signal using the Thread.sleep() method.
■ Note that signal handling is not recommended for general use in Java, and should be
used only when necessary.
■ Also note that the Signal class is not part of the public API and may not be available on
all platforms.
MEMORY-MAPPED I/O
■ Memory-mapped I/O (MMIO) is a technique for accessing hardware devices from a computer
program by mapping device registers into the computer's address space, allowing them to be
accessed as if they were normal memory locations.

■ Java provides support for MMIO through the java.nio package.


■ To use memory-mapped I/O in Java, you first need to create a memory-mapped buffer.

■ This buffer can be created using the java.nio.MappedByteBuffer class, which provides
methods for reading and writing to the mapped buffer.

■ Here's an example of how to create and use a memory-mapped buffer in Java:


MEMORY-MAPPED I/O
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
public class MemoryMappedIOExample {
public static void main(String[] args) throws
Exception {
RandomAccessFile file = new
RandomAccessFile("example.txt", "rw");
FileChannel channel = file.getChannel();
// Map the file into memory
MappedByteBuffer buffer =
channel.map(FileChannel.MapMode.READ_WRITE, 0,
channel.size());
MEMORY-MAPPED I/O
// Write to the buffer
buffer.putChar('H');
buffer.putChar('e');
buffer.putChar('l');
buffer.putChar('l');
buffer.putChar('o');
// Flush changes to disk
buffer.force();
// Read from the buffer
buffer.position(0);
while (buffer.hasRemaining()) { System.out.print(buffer.getChar()); }
// Unmap the buffer
channel.close();
MEMORY-MAPPED I/O
In this example, we create a MappedByteBuffer
by mapping a file channel to memory using the
map method.
We then write characters to the buffer and flush
the changes to disk using the force method.
Finally, we read the characters from the buffer and
unmap the buffer by closing the channel and file.
SEQUENTIAL-ACCESS TEXT FILES

■ Sequential-access files store records in order by the record-key field.


■ Text files are human-readable files.
CREATING A SEQUENTIAL-ACCESS
TEXT FILE

■ Java imposes no structure on a file


– Notions such as records do not exist as part of the Java language.
– You must structure files to meet the requirements of your applications.
CREATING A SEQUENTIAL-ACCESS
TEXT FILE (CONT.)

■ Formatter outputs formatted Strings to the specified stream.


■ The constructor with one String argument receives the name of the file, including its
path.
– If a path is not specified, the JVM assumes that the file is in the directory from
which the program was executed.
■ If the file does not exist, it will be created.
■ If an existing file is opened, its contents are truncated.
CREATING A SEQUENTIAL-ACCESS TEXT
FILE (CONT.)

■ A SecurityException occurs if the user does not have permission to write data to
the file.
■ A FileNotFoundException occurs if the file does not exist and a new file cannot
be created.
■ static method System.exit terminates an application.
– An argument of 0 indicates successful program termination.
– A nonzero value, normally indicates that an error has occurred.
– The argument is useful if the program is executed from a batch file on Windows or
a shell script on UNIX/Linux/Mac OS X.
CREATING A SEQUENTIAL-ACCESS TEXT
FILE (CONT.)

■ Scanner method hasNext determines whether the end-of-file key


combination has been entered.
■ A NoSuchElementException occurs if the data being read by a
Scanner method is in the wrong format or if there is no more data to input.
■ Formatter method format works like System.out.printf
■ A FormatterClosedException occurs if the Formatter is closed
when you attempt to output.
■ Formatter method close closes the file.
– If method close is not called explicitly, the operating sys-tem normally will close the
file when program execution terminates.
CREATING A SEQUENTIAL-ACCESS TEXT
FILE (CONT.)

■ Different platforms use different line-separator characters.


■ On UNIX/Linux-/Mac OS X, the line separator is a newline (\n).
■ On Windows, it is a combination of a carriage return and a line feed—
represented as \r\n.
■ You can use the %n format specifier in a format control string to output a
platform-specific line separator.
■ Method System.out.println outputs a platform-specific line separator
after its argument.
■ Regardless of the line separator used in a text file, a Java program can still
recognize the lines of text and read them.
READING DATA FROM A SEQUENTIAL-
ACCESS TEXT FILE

■ The application in Figs. 17.9 and 17.10 reads records from the file "clients.txt"
created by the application of Section 17.4.1 and displays the record contents.
READING DATA FROM A SEQUENTIAL-
ACCESS TEXT FILE

■ If a Scanner is closed before data is input, an IllegalStateException occurs.


CASE STUDY: A CREDIT-INQUIRY PROGRAM

■ To retrieve data sequentially from a file, programs start from the beginning of the file
and read all the data consecutively until the desired information is found.
■ It might be necessary to process the file sequentially several times (from the beginning
of the file) during the execution of a program.
■ Class Scanner does not allow repositioning to the beginning of the file.
– The program must close the file and reopen it.
UPDATING SEQUENTIAL-ACCESS FILES

■ The data in many sequential files cannot be modified without the risk of
destroying other data in the file.
■ If the name “White” needed to be changed to “Worthington,” the
old name cannot simply be overwritten, because the new name requires
more space.
■ Fields in a text file—and hence records—can vary in size.
■ Records in a sequential-access file are not usually updated in place.
Instead, the entire file is usually rewritten.
■ Rewriting the entire file is uneconomical to update just one record, but
reasonable if a substantial number of records need to be updated.

You might also like