JAVA Development
Working with files,
HTTP requests
Reading & Writing Files
I/O Streams
• java.io package - classes for performing various input/output (I/O) operations
• stream = a sequence of data.
• two kinds of streams:
○ InputStream − used for reading data from a source
○ OutputStream − used for writing data to a destination
Byte Streams
• Byte streams are used to perform input and output for data encoded as a
sequence of 8-bit bytes
• There are many classes related to byte streams, the most frequently used ones
are: FileInputStream, FileOutputStream
Byte Streams - Example
Example: copying a file (one byte at a time):
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("C:\\wantsome\\week8\\input.txt");
out = new FileOutputStream("C:\\wantsome\\week8\\output.txt");
int c;
while ((c = in.read()) != -1) { //read one byte at a time, until input finished
out.write(c); //and write it to the output stream
}
} finally { //always need to cleanup (close the streams) at the end!
if (in != null) in.close();
if (out != null) out.close();
}
Character Streams
• Character streams are used to perform input and output for sequences of 16-bit
Unicode characters
• There are many classes related to character streams, the most frequently used
ones are: FileReader, FileWriter
Example: very similar to byte streams example, the only important difference is:
in = new FileReader("C:\\wantsome\\week8\\input.txt");
out = new FileWriter("C:\\wantsome\\week8\\output.txt");
Note: FileReader/Writer does use internally a FileInputStream/FileOutputStream
but the major difference is that FileReader/Writer reads/writes two bytes at a time
Standard I/O Streams
• Standard Input − used to feed the data to a program; usually a keyboard is
used for it and it’s represented as: System.in
• Standard Output − used to output the normal data produced by a program;
usually a computer screen is used for it and it’s represented as: System.out
• Standard Error − used to output the error data produced by a program;
usually a computer screen is used for it and it’s represented as: System.err
Standard Streams - Example (with try-finally)
InputStreamReader in = null;
OutputStreamWriter out = null;
try {
in = new InputStreamReader(System.in);
out = new OutputStreamWriter(System.out);
System.out.println("Enter characters (+Enter), 'E' to exit");
char c;
do {
c = (char) in.read();
out.write(c); //somehow equivalent to: System.out.print(c);
out.flush(); //needed to flush/show data after each Enter
} while (c != 'E');
} finally { //always need to cleanup (close the streams) at the end!
if (in != null) in.close();
if (out != null) out.close();
}
AutoCloseable, try-with-resources
All streams and readers implement the AutoCloseable interface.
This allows for try-with-resources statement to be used instead of try-finally:
try ( InputStreamReader in = new InputStreamReader(System.in);
OutputStreamWriter out = new OutputStreamWriter(System.out) ) {
System.out.println("Enter characters (+Enter), 'E' to exit");
char c;
do {
c = (char) in.read();
out.write(c); //equivalent to: System.out.print(c);
out.flush(); //needed to flush/show data after each Enter
} while (c != 'E');
} //at the end of try the resources (in,out) will be auto closed!
Note: this is the recommended way to do it, as is cleaner/safer than a simple try!
AutoCloseable - File copy example (with buffer)
Example of file copy using a bytes stream, with buffered operations (instead of one byte at a
time), and with try-with-resources:
try ( FileInputStream in = new FileInputStream(inputFilePath);
FileOutputStream out = new FileOutputStream(outputFilePath) ) {
byte[] buffer = new byte[1024]; //using a 1kb buffer
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
} //in/out auto closed
AutoCloseable - Zip file example
import java.io.BufferedWriter; import java.io.IOException;
import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths;
import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile;
static void writeZipFileContentsToFile(String zipFileName, String outputFileName) throws IOException {
Path outputFilePath = Paths.get(outputFileName);
//open zip file and create output file with try-with-resources statement
try ( ZipFile zf = new ZipFile(zipFileName);
BufferedWriter writer = Files.newBufferedWriter(outputFilePath, StandardCharsets.UTF_8)) {
//enumerate each entry in zip file
for (Enumeration entries = zf.entries(); entries.hasMoreElements(); ) {
//get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName = ((ZipEntry) entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
}
…
writeZipFileContentsToFile("F:\\java_books.zip", "F:\\java_books_list.txt");
I/O Streams - Class hierarchy
FileInputStream, FileOutputStream
Input:
InputStream in = new FileInputStream("C:\\wantsome\\week7\\in.txt");
or:
File inFile = new File("C:\\wantsome\\week7\\input.txt");
InputStream in = new FileInputStream(inFile);
Output:
OutputStream out = new FileOutputStream("C:\\wantsome\\week7\\out.txt");
or:
File outFile = new File("C:\\wantsome\\week7\\output.txt");
OutputStream out = new FileOutputStream(outFile);
FileInputStream - Methods
method description
public int read() throws IOException Reads the specified byte of data from the InputStream.
Returns an int. Returns the next byte of data and -1 will be
returned if it's the end of the file.
public int read(byte[] r) throws IOException Reads r.length bytes from the input stream into an array.
Returns the total number of bytes read. If it is the end of the
file, -1 will be returned.
public void close() throws IOException Closes the file output stream. Releases any system
resources associated with the file.
public int available() throws IOException Gives the number of bytes that can be read from this file
input stream. Returns an int.
FileOutputStream - Methods
method description
public void write(int w) throws IOException Writes the specified byte to the output stream.
public void write(byte[] w) throws IOException Writes w.length bytes from the mentioned byte array to
the OutputStream.
public void close() throws IOException Closes the file output stream. Releases any system
resources associated with the file.
Reading files with Scanner
java.util.Scanner class can be used to read from all kinds of input streams, including files.
It has the advantage of having nice methods like: nextLine/Long/Float/.., hasNextLine/Long/Float..
Scanner keyScanner = new Scanner(System.in);
int maxLines = keyScanner.nextInt();
File file = new File("some/file/path/here.txt");
Scanner fileScanner = new Scanner(file);
System.out.println("First " + maxLines + " lines of " + file.getAbsolutePath() + ":");
int lineCount = 0;
while (lineCount < maxLines && fileScanner.hasNext()) {
String line = fileScanner.nextLine();
lineCount++;
System.out.println(lineCount + ": " + line);
}
Filesystem - Structure
- A filesystem stores a collection of files, usually in a tree structure:
- it has a root directory (folder)
- under it it has a list of direct children, which are either regular files or subdirectories
- each subdirectory may have a similar structure under it; there is usually no limit (or a very
high limit) on the total number of such levels.
So it’s basically a recursive structure! (we can use recursive functions to traverse it)
- Each file (directory or regular one) is identified by its path, specified in two possible ways:
- absolute: the full path, starting with the root directory
- relative: a path relative to the current directory (=the dir where the app started, or the user
home dir, etc..)
- File path format:
- a list of file names (parent folders + the file’s name), joined by a specific separator ( ‘\’, ‘/’)
- it may use also a few special symbols, like ‘.’ (=the dir itself) and ‘..’ (=parent dir)
Filesystem - Structure
Example of a Windows filesystem:
- there is one root folder/tree per each disk (C, D)
- file path separator is: ‘\’
- absolute paths start with: “<disk>:”)
If current dir is ‘C:\Users\Ana’, these are some valid paths:
- “.” => the dir itself (Ana)
- “..” => parent dir (Users)
- “..\Ionel\file1” => C:\Users\Ionel\file1
- “dir1\file4” , “C:\Users\Ionel\..\Ana\dir1\file4”
Path “dir1\..\file3” - is a relative path (no disk letter at start)
- its absolute path is: “C:\Users\Ana\file3”
Note:
- absolute paths uniquely identify a file
- relative paths meaning depend on current dir
- ‘.\file1’ means different files depending if
current dir is “Ana”, “Ana\dir1” or “Ionel”
Filesystem - Structure
The filesystem structure and details depend on the platform/OS!
- Windows:
- path separator is “\” (but “/” is also usable, as is recognized as separator)
- there are multiple root folders (one per disk); absolute paths start with “<disk letter>:”
- file names are case insensitive (“C:\Users” and “c:\users” mean the same folder)
- examples: “C:\Users\Ana”, “D:\media\movie1.avi”
- Linux, MacOS:
- path separator is “/” (and “\” is NOT a separator, can be used to name files!)
- there is only one global root folder (/); absolute paths start with just “/”
- file names are case sensitive (“/home/Ana” and “/home/ana” are 2 different folders!)
- examples: “/var”, “/home/public/Ana/file1.txt”
Java is platform independent, but your code still needs to consider these differences! (it needs to
pass correct/meaningful values for file paths to the OS in order to work)
- for portability, use the constant File.separator (instead of ‘\’ or ‘/’) when working with paths
File properties
A File object represents a file on disk, and gives us access to properties and operations on it:
//String path = "C:\\dir1\\file1.txt"; //absolute, windows style
//String path = "/dir1/file1.txt"; //absolute, linux style
String path = "dir1" + File.separator + "file1.txt"; //relative, portable format!
File file = new File(path);
System.out.println(file.getAbsolutePath()); //absolute path (works even if it doesn’t exist)
System.out.println(file.exists()); //check if file exists (is accessible)
System.out.println(file.isDirectory()); //check if is dir or regular
System.out.println(file.length()); //file size (in bytes)
System.out.println(file.lastModified()); //date of last update (type is 'long', in ms!)
System.out.println(new Date(file.lastModified()).toString()); //date in readable format..
Other methods:
canExecute(), canRead(), canWrite() - show if operation is allowed for file
list(), listFiles() - list the direct children files (if current file is a dir)
renameTo(String), delete() - renames/deletes this file
setLastModified(long), setExecutable/setWritable/setReadonly(boolean) - update properties
Creating Directories
File class contains some methods which can be used to create directories:
• mkdir() - creates a directory, returning true on success and false on failure. Failure
indicates that the path specified in the File object already exists, or that the directory
cannot be created because the entire path does not exist yet.
• mkdirs() - creates both a directory and all its missing parents.
String dirName = "C:\\wantsome\\week7\\parent_dir\\child_dir";
File dir = new File(dirName);
dir.mkdirs(); //creates the directory (including missing parents)
Listing Directories
try {
File dir = new File("C:\\"); // create new file object
String[] paths = dir.list(); // get child files/folders
System.out.println("Contents of folder '" + file.getPath() + "'");
for (String path : paths) { // for each name in the path array
System.out.println(path); // prints file path
}
} catch (Exception e) { // if any error occurs
e.printStackTrace();
}
Properties files
Properties files are files with a specific format, holding ‘key=value’ pairs (one per line), usually used to
hold configuration details. Java has built-in support for working with them, using the Properties class:
void writeProperties(String fileName) throws IOException{ - Usage:
Properties prop = new Properties();
writeProperties("config.properties");
prop.setProperty("key1", "value1");
readProperties("config.properties");
prop.setProperty("key2", "value2");
System.out.println("Writing properties to: " + fileName); - Console output:
try (OutputStream out = new FileOutputStream(fileName)) { Writing properties to: config.properties
prop.store(out, "some comments here"); Reading properties from: config.properties
} Loaded properties: {key2=value2, key1=value1}
}
- Content of config.properties file:
void readProperties(String fileName) throws IOException {
System.out.println("Reading properties from: " + fileName); #some comments here
Properties prop = new Properties(); #Mon Jan 14 23:39:01 EET 2019
key2=value2
try (InputStream in = new FileInputStream(fileName)) {
key1=value1
prop.load(in);
}
System.out.println("Loaded properties: " + prop);
}
Files - Extra reading
About working with files:
● http://tutorials.jenkov.com/java-io/index.html
● http://tutorials.jenkov.com/java-io/file.html
● http://tutorials.jenkov.com/java-exception-handling/try-with-resources.html
Recommended libraries for other formats:
• for Excel – apache POI https://poi.apache.org/spreadsheet/quick-guide.html
• for CSV – https://mvnrepository.com/artifact/com.opencsv/opencsv/4.4
HTTP Requests
HTTP Protocol
What happens when you type an url in a web browser?
- DNS resolution: domain name resolved to an IP address
- TCP/IP connection to the web server is opened
- if HTTPS, certificates are checked and secure communication is initiated
- An HTTP request is sent to the server
- An HTTP response is received from the server
A more complete story:
● https://medium.com/@maneesha.wijesinghe1/what-happens-when-you-type-an-url-in-the-browser-and-press-enter-bb0aa2449c1a
HTTP Protocol
HTTP:
● most common protocol for web pages
● commonly used for web services as well
● built on top of TCP/IP
HTTP Requests
What’s an HTTP request?
GET /wiki/Hypertext_Transfer_Protocol HTTP/1.1
Host: en.wikipedia.org
User-Agent: curl/7.54.0
Accept: */*
Note: details on each request are also visible in browsers in the developer tools/console
(F12 in Chrome, then Network tab)...
HTTP Requests
What’s an HTTP request?
GET /wiki/Hypertext_Transfer_Protocol HTTP/1.1
Starts with the HTTP request method (verb):
● GET: for reading resources
● HEAD: similar but get just summary info (headers) not full content
● POST / PUT / DELETE etc: for modifying resources (e.g uploading a file,
sending a form, etc.)
HTTP Requests
After the method comes the path:
GET /wiki/Hypertext_Transfer_Protocol HTTP/1.1
And then a list of request headers, each a pair of name and value, like:
Header-Name: some-text-value
Host: en.wikipedia.org
User-Agent: curl/7.54.0
Accept: */*
HTTP Responses
What’s an HTTP response?
HTTP/1.1 200
Content-Type: text/html; charset=UTF-8
Content-Length: 193139
Cache-Control: max-age=0
Accept-Ranges: bytes
<!DOCTYPE html>
<html class="client-nojs" lang="en" dir="ltr">
<head>
<title>Hypertext Transfer Protocol - Wikipedia</title>
…
HTTP Responses
First row contains the response code:
HTTP/1.1 200
Meaning of codes (by prefix):
● 2**: No errors
○ 200: OK
○ 201: Created
● 3**: Redirections
● 4**: Client Errors
● 5**: Server Errors
HTTP Responses
Followed by response headers:
Content-Type: text/html; charset=UTF-8
Content-Length: 193139
Cache-Control: max-age=0
Accept-Ranges: bytes
And finally the content (e.g the actual HTML page), also called body:
<!DOCTYPE html>
<html class="client-nojs" lang="en" dir="ltr">
<head>
<title>Hypertext Transfer Protocol - Wikipedia</title>
URL
What’s an URL?
URL = Universal Resource Locator
General format:
● protocol://hostname:port/rest_of_the_url
Examples:
● http://example.com - only protocol and hostname
● https://en.wikipedia.org/wiki/HTTP - “/wiki/HTTP” is called the path
● http://google.com/search?q=java+url - “/search” is the path, “q=java+url” is the query string
java.net.URL
● Class for handling URLs and validating that a string is a valid URL
HttpURLConnection
java.net.HttpURLConnection
● Class for making HTTP requests and reading responses
● One instance per request!
Also contains many constants for checking response codes:
HttpURLConnection.HTTP_OK = 200
Can be created from an URL instance (with some forced casting):
HttpURLConnection conn = (HttpURLConnection)
(new URL("http://example.com").openConnection());
HttpURLConnection - Example
import java.net.HttpURLConnection;
import java.net.URL;
void performGetRequest() throws IOException {
URL url = new URL("https://www.wikipedia.org/");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
int responseCode = con.getResponseCode(); //read the response code
System.out.println("Response Code: " + responseCode); //hopefully 200…
}
HttpURLConnection - Example
//to also read the response body:
try (BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()))) {
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
System.out.println(response.toString());
}
Questions?
HTTP - Extra reading
https://www.baeldung.com/java-http-request
https://www.testingexcellence.com/http-basics/