(Working with File)
| InputStream | Reader And Writer for Text | Abstract Class InputStream |
| Abstract Class Reader | Abstract Class Writer | Console Class |
| Serialization |
- using special class File enables one to create File objects
- from which actual physical files on the hard disk can be created
- many of the classes mentioned in previous slides are intended to be wrapped
- this enables low-level classes to get access to higher-level functionality
- which results with efficiency (buffering)
- all classes in this lesson are in
java.io.*package - Java reads/writes either
charactersorbytes - Classes with Stream in their name read/write binary: (usually used for images, executable files, etc.)
- FileInputStream
- FileOutputStream
- ObjectInputStream
- ObjectOutputStream
Read And Write File (Byte)
//Convert From Byte[] to String
public static String read(byte[] bytes) {
return new String(bytes, StandardCharsets.UTF_8);
}
//Get Byte[] from file
public static byte[] copy(String filePath){
try (FileInputStream fis = new FileInputStream(filePath)) {
return fis.readAllBytes();
} catch (IOException e) {
throw new RuntimeException("Error copy file " + filePath, e);
}
}
//create a new File From Byte[] Content
public static void paste(String filePath, byte[] bytes){
try (FileOutputStream fos = new FileOutputStream(filePath)) {
fos.write(bytes);
} catch (IOException e) {
throw new RuntimeException("Error paste file " + filePath, e);
}
}Read/Write(Char)
//read String File
public static String read(String filePath){
StringBuilder stringBuilder = new StringBuilder();
try (FileInputStream fis = new FileInputStream(filePath)) {
int data;
while ((data = fis.read()) != -1) {
stringBuilder.append((char) data);
}
} catch (IOException e) {
throw new RuntimeException("Error reading file " + filePath, e);
}
return stringBuilder.toString();
}
//Write String File
public static void write(String filePath, String bodyFile){
try (FileOutputStream fos = new FileOutputStream(filePath)) {
byte[] bytes = bodyFile.getBytes();
fos.write(bytes);
} catch (IOException e) {
throw new RuntimeException("Error writing file " + filePath, e);
}
}Class here: FileIOStream.java
- Readers and Writers are used to read/write text:
- FileReader
- BufferedReader
- FileWriter
- BufferedWriter
- PrintWriter
- these are used for text files (data which consist of characters or strings)
Example:
public static String read(String filePath) {
StringBuilder sb = new StringBuilder();
try (FileReader reader = new FileReader(filePath)) {
int ch;
while ((ch = reader.read()) != -1) sb.append((char) ch); // print each character
} catch (IOException e) {
throw new RuntimeException("Error reading file " + filePath, e);
}
return sb.toString();
}
public static void write(String filePath, String content) {
try (FileWriter writer = new FileWriter(filePath)) {
writer.write(content);
} catch (IOException e) {
throw new RuntimeException("Error writing file " + filePath, e);
}
}
public static String read(String filePath) {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (IOException e) {
throw new RuntimeException("Error reading file: " + filePath, e);
}
}
public static void write(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write(content);
} catch (IOException e) {
throw new RuntimeException("Error writing file: " + filePath, e);
}
}Class here: FileReaderAndWriter.java, BufferReaderAndWriter.java
- Low-level class: FileInputStream
- reads one byte at a time
- High-level class (for efficiency): BufferedInputStream
- High-level class (other): ObjectInputStream
- Wrapping example:
- new ObjectInputStream(new FileInputStream("file.dat"));
- Example Here: ObjectIOStream.java
- Low-level class: FileReader
- High-level class (for efficiency): BufferedReader
- High-level class (other): InputStreamReader
- a bridge between byte streams and character streams
- Wrapping examples:
- new BufferedReader(new FileReader("in.txt"));
- new BufferedReader(new InputStreamReader(System.in));
public static void toUpperCaseFromConsole(){
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
if (line.equalsIgnoreCase("Exist")) {
break; // stop reading
}
System.out.println(line.toUpperCase());
}
} catch (IOException e) {
throw new RuntimeException("Error Writing file: " , e);
}
}
public static String read(String filePath) {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
return reader.lines().collect(Collectors.joining("\n"));
} catch (IOException e) {
throw new RuntimeException("Error reading file: " + filePath, e);
}
}Class here: BufferReaderAndWriter.java
- Low-level class: FileWriter
- High-level class (for efficiency): BufferedWriter
- High-level classes (other): OutputStreamWriter, PrintWriter
- a bridge between byte streams and character streams
- Wrapping examples:
- new BufferedWriter(new FileWriter("out.txt"));
- new BufferedWriter(new OutputStreamWriter(System.out));
public static void write(String filePath, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath))) {
writer.write(content);
} catch (IOException e) {
throw new RuntimeException("Error writing file: " + filePath, e);
}
}Class here: BufferReaderAndWriter.java
- class java.io.Console is designed for interacting with the user
- this class is a singleton
- using factory method we create one and only instance of this class
- the constructors of Console class are private
- i.e. created using factory methods, not with new keyword
Example:
import java.io.Console;
import java.util.Arrays;
public class MyConsoleExample {
//create a file and cd into folder and run
public static void main(String[] args) {
Console console = System.console();
if (console == null) {
System.out.println("No console available");
} else {
char[] password = console.readPassword("Enter your password: ");
char[] repeatPassword = "Alan123".toCharArray();
if (Arrays.equals(password, repeatPassword)) {
console.writer().println("-".repeat(30));
console.format("Hello %s!%n", "Alan");
} else {
console.writer().println("-".repeat(30));
console.writer().println("Wrong Password!");
console.writer().flush();
}
}
}
}If you run on intelliJ:
No console available
Run Console:
- javac .java //compile .java to .class
- java //run main file
D:\>javaC MyConsoleExample.java
D:\>java MyConsoleExampleD:\>java MyConsoleExample
Enter your password:
------------------------------
Hello Alan!
D:\>java MyConsoleExample
Enter your password:
------------------------------
Wrong Password!
- Serialization in Java is process of convert from Object to Byte Array to:
- Write to file (Ex:
.dat,ser) - Send through the network
- Store in memory (cache, session)
- Transmit among chanel (client to server)
- Write to file (Ex:
serializationisthe process of saving in-memoryJavaobjectin thephysical file- de-serialization is the opposite:
readingfrom file andcreatingJava object - to make a class
serializable:- it must implement the
marker interface Serializable(marker interface is an interface which has no methods) - when serializing the object,
only instance membersare serialized (not static)
- it must implement the
- a special field in serializable classes which is serialized even though it's static:
private static final long serialVersionUID = 1L;- this field serves as a
unique identifierforeach classin (de)serialization process - during
deserializationJVM checks if theserialVersionUIDof the loaded class is the same as theserialVersionUIDof the serialized object- if they
match, it means that thetwo versions of the class are compatible - if they
don't match, the JVMthrows an InvalidClassException
- if they
- if you
don't wantafieldto beserialized, you can mark it astransient, e.g.
private transient String myPassword;- when being
deserialized,transient fieldwillrevertto it'sdefaultJavavalue(null for String, 0 for int, false for boolean, etc.) - if you have
instance variablesin yourserializable class,make surethatthese objectsare alsomarkedasserializable, e.g. - if you want to
serialize classStudent which has aninstance variableof type Address, you have tomake Addressclassserializableas well - remember: only non-transient instance members will be serialized!
Student Class:
import lombok.Getter;
import java.io.Serializable;
import java.util.UUID;
@Getter
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
//don't want a field to be serialized
private transient String id;
private String name;
private int age;
public Student(String Name, int Age) {
this.id = UUID.randomUUID().toString();
this.name = Name;
this.age = Age;
}
@Override
public String toString() {
return "Student [ID=" + id + ", Name=" + name + ", Age=" + age + "]";
}
}Example 1:
public static void main(String[] args) {
Student alan = new Student("Alan", 25);
//covert from Java Object to Byte Array and id marked transient
byte[] serialize = SerializationUtils.serialize(alan);
System.out.println(SerializationUtils.deserialize(serialize));
}Student [ID=null, Name=Alan, Age=25]
Example 2:
public static void main(String[] args) {
Student alan = new Student("Alan", 25);
System.out.println("Initialize Student: " + alan);
serialize(alan, "src/resource/file/SerializationExample.dat");
Student deserialize = (Student) deserialize("src/resource/file/SerializationExample.dat");
System.out.println("Deserialize Student File: "+deserialize.toString());
}
public static void serialize(Object ob, String fileName){
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath))) {
oos.writeObject(ob);
} catch (IOException e) {
throw new RuntimeException("Error writing to file", e);
}
}
public static Object deserialize(String fileName){
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath))) {
return ois.readObject();
} catch (IOException | ClassNotFoundException e) {
throw new RuntimeException("Error reading to file", e);
}
}Initialize Student: Student [ID=5f6ef6d9-ccd7-4179-87b2-d2ba81606ab6, Name=Alan, Age=25]
Deserialize Student File: Student [ID=null, Name=Alan, Age=25]
Example Class: SerializationExample.java
- System.in refers to the standard input stream of a Java program. It is opened when the program is started.
- in is a variable of java.lang.System class.
public static final InputStream in- The "standard" input stream. This stream is already open and ready to supply input data. Typically this stream corresponds to keyboard input or another input source specified by the host environment or user.
- The
System.invariable cannot be reassigned to any other stream directly.- Although in is a final variable and so, it cannot be reassigned directly. However, System class has a public static void setIn(InputStream in) method that can be used to change in to refer to any other InputStream.
- You can close it by calling
System.in.close(); - The declared type of System.in is java.io.InputStream. It refers to an object of type java.io.BufferedInputStream.
- An InputStream is meant to read bytes. Whether these bytes are characters or not is irrelevant. A program could potentially interpret the bytes reads through this stream as characters.