IO is input / output. The Java IO class library constructs a set of I/O system based on the abstract basic classes InputStream and OutputStream, which mainly solves the problems of reading data from the data source and writing data to the destination. We put The data source and destination can be understood as both ends of the IO stream. Of course, usually, these two ends may be files or network connections.
Let's use the following diagram to deepen our understanding:
Read data from a data source into program memory through an InputStream stream object
Of course, we reverse the flow of the above figure, which is the schematic diagram of OutputStream.
In fact, in addition to the InputStream/OutputStream system for byte stream, the Java IO class library also provides a Reader/Writer system for character stream. The Reader/Writer inheritance structure is mainly for internationalization because it can better handle 16 bit Unicode characters.
In learning, these two sets of IO stream processing systems can be compared with reference to learning, because there are many similarities.
1. Understand the overall design
At the beginning of writing IO code, I was always confused by various IO stream classes. When can I remember so many IO related classes and methods.
In fact, as long as we master the overall design idea of IO class library and understand its hierarchy, it will be very clear. It's good to know when to use which stream objects to combine the desired functions. For API, you can check the manual.
First, the flow direction of a stream can be divided into input stream or Reader, output stream or Writer. Any class derived from InputStream or Reader has a read() basic method to read a single byte or byte array; Any class derived from OutputStream or Writer contains the basic method write(), which is used to write a single byte or an array of bytes.
From the perspective of operating bytes or characters, there are classes for byte stream, which basically end with XxxStream, and classes for character stream end with XxxReader or XxxWriter. Of course, these two types of streams can be transformed. There are two classes of transformed streams, which will be mentioned later.
Generally, when using IO streams, the following codes are similar:
FileInputStream inputStream = new FileInputStream(new File("a.txt")); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
This is actually the use of decorator mode. Decorator mode is used in IO stream system to package various function stream classes.
In the Java IO stream system, FilterInputStream/FilterOutStream and FilterReader/FilterWriter are the interface classes of decorator mode, and some function stream classes are wrapped down from this class. There are DataInputStream, BufferedInputStream, LineNumberInputStream, PushbackInputStream, etc. of course, there are also output function stream classes; Character oriented function flow class, etc.
The following figures describe the inheritance architecture of the entire IO flow
InputStream stream system
OutputStream stream system
Reader system
Writer system
2. File is actually a tool class
The File class actually represents not only a File, but also a group of files in a directory (representing a File path). Let's take a look at some of the most commonly used methods in the File class
1 File.delete() Delete a file or folder directory. 2 File.createNewFile() Create a new empty file. 3 File.mkdir() Create a new empty folder. 4 File.list() Gets the file and folder names in the specified directory. 5 File.listFiles() Gets the file and folder objects in the specified directory. 6 File.exists() Does the file or folder exist 7 8 String getAbsolutePath() // Get absolute path 9 long getFreeSpace() // Returns the number of unallocated bytes in the partition. 10 String getName() // Returns the name of the file or folder. 11 String getParent() // Returns the pathname string of the parent directory; null if no parent directory is specified. 12 File getParentFile() // Returns the parent directory File object 13 String getPath() // Returns a pathname string. 14 long getTotalSpace() // Returns the size of this file partition. 15 long getUsableSpace() //Returns the number of bytes occupied. 16 int hashCode() //File hash code. 17 long lastModified() // Returns the time when the file was last modified. 18 long length() // Gets the length in bytes. 19 boolean canRead() //Judge whether it is readable 20 boolean canWrite() //Determine whether it is writable 21 boolean isHidden() //Determine whether to hide 22 23 24 // Member function 25 static File[] listRoots() // Lists the available file system roots. 26 boolean renameTo(File dest) // rename 27 boolean setExecutable(boolean executable) // Set execution permissions. 28 boolean setExecutable(boolean executable, boolean ownerOnly) // Set execution permissions for all other users. 29 boolean setLastModified(long time) // Set the last modification time. 30 boolean setReadable(boolean readable) // Set read permissions. 31 boolean setReadable(boolean readable, boolean ownerOnly) // Set read permissions for all other users. 32 boolean setWritable(boolean writable) // Set write permissions. 33 boolean setWritable(boolean writable, boolean ownerOnly) // Set write permissions for all users.
It should be noted that the File path separator table is different in different systems, such as "\" in Windows and "/" in Linux. The File class provides us with an abstract representation of File Separator, which shields the differences in the system layer. Therefore, do not use a representative path such as "\" in the code, which may cause code execution errors on the Linux platform.
Here are some examples:
According to the incoming rules, the File object array composed of all the files in the directory is traversed
1 public class Directory { 2 public static File[] getLocalFiles(File dir, final String regex){ 3 return dir.listFiles(new FilenameFilter() { 4 private Pattern pattern = Pattern.compile(regex); 5 public boolean accept(File dir, String name) { 6 return pattern.matcher(new File(name).getName()).matches(); 7 } 8 }); 9 } 10 11 // Overloading methods 12 public static File[] getLocalFiles(String path, final String regex){ 13 return getLocalFiles(new File(path),regex); 14 } 15 16 public static void main(String[] args) { 17 String dir = "d:"; 18 File[] files = Directory.getLocalFiles(dir,".*\\.txt"); 19 for(File file : files){ 20 System.out.println(file.getAbsolutePath()); 21 } 22 } 23 }
Output results:
1d:\\1.txt 2d:\\New text document.txt
In the above code, dir Listfiles (filenamefilter) is an implementation of the policy pattern and uses anonymous inner classes.
The above examples are examples in Java programming ideas. Each code example in this book is very classic. Bruce Eckel's application of object-oriented ideas is perfect, which is very worth tasting.
3. InputStream and OutputStream
InputStream is an input stream. As mentioned earlier, it is a stream object used when reading data from a data source object into program content. By looking at the source code of InputStream, we know that it is an abstract class,
1 public abstract class InputStream extends Object implements Closeable
Some basic input flow methods are provided:
1 //Read a byte from the data and return it. When the end of the stream is encountered, return - 1 2 abstract int read() 3 4 //Read in a byte array, and return the actual number of bytes read in. Read in b.length bytes at most, and return - 1 when encountering the end of the stream 5 int read(byte[] b) 6 7 // Read in a byte array and return the actual number of bytes read in or - 1 when the end is encountered 8 //b: Represents the array of data read in, off: represents the offset in B of the position where the first read in byte should be placed, len: the maximum number of read in bytes 9 int read(byte[],int off,int len) 10 11 // Returns the current number of bytes that can be read. If it is read from a network connection, this method should be used with caution, 12 int available() 13 14 //Skip n bytes in the input stream and return the actual number of skipped bytes 15 long skip(long n) 16 17 //Mark the current position in the input stream 18 void mark(int readlimit) 19 20 //Judge whether the flow supports marking and returns true 21 boolean markSupported() 22 23 // The last tag is returned, and subsequent calls to read will reread these bytes. 24 void reset() 25 26 //It is very important to close the input stream. The stream must be closed after use 27 void close()
The streams inherited directly from InputStream basically correspond to each data source type.
class | function |
---|---|
ByteArrayInputStream | Use byte array as InputStream |
StringBufferInputStream | Convert String to InputStream |
FileInputStream | Read content from file |
PipedInputStream | Generates data for writing to the associated PipedOutputStream. Realize pipelining |
SequenceInputStream | Converts two or more InputStream objects to a single InputStream |
FilterInputStream | Abstract class is mainly used as the interface class of "decorator" to realize other function flows |
OutputStream is an abstraction of the output stream. It writes the data in the program memory to the destination (that is, the end receiving the data). See the signature of the following class:
1 public abstract class OutputStream implements Closeable, Flushable {}
It provides a basic method, which is much simpler than the input stream. The main methods are write (several overloaded methods), flush flush and close.
1 // Write out one byte of data 2 abstract void write(int n) 3 4 // Write bytes to data b 5 void write(byte[] b) 6 7 // Write out bytes to array b, off: represents the offset of the first write out byte in b, len: the maximum number of write out bytes 8 void write(byte[] b, int off, int len) 9 10 //Flush the output stream, that is, send all buffered data to the destination 11 void flush() 12 13 // Close output stream 14 void close()
Similarly, OutputStream also provides some basic stream implementations, which can also correspond to a specific destination (receiver), such as output to byte array or output to file / pipeline.
class | function |
---|---|
ByteArrayOutputStream | Create a buffer in memory where all data sent to the "stream" is placed |
FileOutputStream | Write data to file |
PipedOutputStream | Use with PipedInputStream. Realize pipelining |
FilterOutputStream | Abstract class is mainly used as the interface class of "decorator" to realize other function flows |
4. Flow packaged with decorator
The Java IO stream architecture uses the decorator pattern to add additional functionality to the underlying I / O streams. This additional function may be: the stream can be buffered to improve performance, the stream can read and write basic data types, etc.
These stream types that add functionality through the decorator pattern are extended from the FilterInputStream and FilterOutputStream abstract classes. You can go back to the diagrams mentioned at the beginning of the article to deepen your impression.
FilterInputStream type
class | function |
---|---|
DataInputStream | Used in conjunction with DataOutputStream, the stream can read basic data types such as int char long |
BufferedInputStream | Using buffers is mainly to improve performance |
LineNumberInputStream | To track the line number in the input stream, you can use getLineNumber and setLineNumber(int) |
PushbackInputStream | This enables the stream to pop up a "one byte buffer", which can fallback the last character read |
FilterOutStream type
class | function |
---|---|
DataOutputStream | Used in conjunction with DataInputStream, the stream can write basic data types such as int char long |
PrintStream | Used to produce formatted output |
BufferedOutputStream | Using the buffer, you can call flush() to empty the buffer |
In most cases, when we use streams, we use input streams and output streams together. The purpose is to transfer and store data. What's the use of separate read() for us? What can we do with reading a byte? Right. Therefore, we should understand that the use of streams is to combine or use function streams to transfer or store data.
5. Reader and Writer
Reader is the base class for all readers in Java IO. Reader is similar to InputStream, except that reader is based on characters rather than bytes.
Writer is the base class for all writers in Java IO. Similar to the relationship between Reader and InputStream, writer is based on characters rather than bytes. Writer is used to write text and OutputStream is used to write bytes.
The basic function classes of Reader and Writer can be learned by comparing InputStream and OutputStream.
Byte oriented | Character oriented |
---|---|
InputStream | Reader |
OutputStream | Writer |
FileInputStream | FileReader |
FileOutputStream | FileWriter |
ByteArrayInputStream | CharArrayReader |
ByteArrayOutputStream | CharArrayWriter |
PipedInputStream | PipedReader |
PipedOutputStream | PipedWriter |
StringBufferInputStream (deprecated) | StringReader |
No corresponding class | StringWriter |
There are two "adapter" stream types that can convert a byte stream into a byte stream. This means that InputStreamReader can convert InputStream into Reader and OutputStreamWriter can convert OutputStream into Writer.
Adapter class, byte stream, character stream
Of course, there is also a decorator implementation similar to byte stream, adding additional functions or behavior to character stream. These function character stream classes mainly include:
- BufferedReader
- BufferedWriter
- PrintWriter
- LineNumberReader
- PushbackReader
6. I/O flow in system class
Think about your first Java program? If I guess correctly, it should be hello world.
1 System.out.println("hello world")
Simple to outrageous, let's talk about standard input / output streams today.
In the standard IO model, Java provides system in,System.out and system error.
Start with system In, look at the source code
1 public final static InputStream in
Is a static field and an unwrapped InputStream. Usually, we will use BufferedReader to wrap and read the input line by line. Here we will use the adapter stream InputStreamReader mentioned earlier.
1 public class SystemInReader { 2 public static void main(String[] args) throws IOException { 3 BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); 4 String s; 5 while ((s = reader.readLine()) != null && s.length() != 0 ){ 6 System.out.println(s); 7 } 8 } 9 }
The program will wait for us to input, input what, and then output. Enter an empty string to end.
1 1 123 123
System.out is a PrintStream stream. System.out usually outputs the data you write to the console. System.out is usually used only on console programs like command line tools. System.out is also often used to print program debugging information (although it may not be the best way to get program debugging information).
System.err is a PrintStream stream. System.err and system Out works similarly, but it is more used to print error text.
You can redirect these system streams
Although system in, System. out,System. Err these three streams are Java The static members of the lang. system class, which have been initialized in advance when the JVM starts, can still be changed.
You can redirect using setIn(InputStream), setOut(PrintStream), setErr(PrintStream). For example, you can redirect the output of the console to a file.
1 OutputStream output = new FileOutputStream("d:/system.out.txt"); 2 PrintStream printOut = new PrintStream(output); 3 System.setOut(printOut);
7. Compression (ZIP document)
The Java IO class library supports reading and writing compressed data streams. We can compress one or a batch of files into a zip document. These compression related stream classes are processed by bytes. Let's take a look at the relevant stream classes designed for compression and decompression.
Compression class | function |
---|---|
CheckedInputStream | getCheckSum() can generate a checksum (not just decompression) for any InputStream |
CheckedOutputStream | getCheckSum() can generate a checksum (not just compression) for any OutputStream |
DeflaterOutputStream | Base class of compressed class |
ZipOutputStream | It inherits from deflatoroutputstream and compresses the data into Zip file format |
GZIPOutputStream | It inherits from deflatoroutputstream and compresses the data into GZIP file format |
InflaterInputStream | Base class of decompression class |
ZipInputStream | It inherits from the InflaterInputStream and decompresses the data in Zip file format |
GZIPInputStream | It inherits from the InflaterInputStream and decompresses the data in GZIP file format |
CheckedInputStream and CheckedOutputStream in the table are generally used together with Zip compression and decompression process, mainly to ensure the correctness of data packets in our compression and decompression process and obtain data that has not been tampered with in the middle.
Take checkdinputstream as an example. Its constructor needs to pass in a Checksum type:
1 public CheckedInputStream(InputStream in, Checksum cksum) { 2 super(in); 3 this.cksum = cksum; 4 }
Checksum is an interface. You can see that the policy mode is used here, and the specific verification algorithm can be selected. The Java class library provides me with two checksum algorithms: adler32 and CRC32. Adler32 may be better in performance, but CRC32 may be more accurate. Each has its own advantages and disadvantages.
OK, next, let's look at the specific use of compressed / decompressed streams.
7.1 compress multiple files into zip packages
1 public class ZipFileUtils { 2 public static void compressFiles(File[] files, String zipPath) throws IOException { 3 4 // Define the file output stream, indicating that it is to be compressed into a zip file 5 FileOutputStream f = new FileOutputStream(zipPath); 6 7 // Add verification function to output stream 8 CheckedOutputStream checkedOs = new CheckedOutputStream(f,new Adler32()); 9 10 // To define the output stream in zip format, you should understand that you have been using decorator mode to add functions to the stream 11 // ZipOutputStream is also inherited from FilterOutputStream 12 ZipOutputStream zipOut = new ZipOutputStream(checkedOs); 13 14 // Add buffer function to improve performance 15 BufferedOutputStream buffOut = new BufferedOutputStream(zipOut); 16 17 //For the compressed output stream, we can set a comment 18 zipOut.setComment("zip test"); 19 20 // The following is the process of reading a batch of Files from the Files [] array and writing them to the zip package 21 for (File file : files){ 22 23 // Create a buffer stream for reading files, also in decorator mode, using BufferedReader 24 // Wrapped FileReader 25 BufferedReader bfReadr = new BufferedReader(new FileReader(file)); 26 27 // A file object is represented by a ZipEntry in the zip stream and added to the zip stream using putNextEntry 28 zipOut.putNextEntry(new ZipEntry(file.getName())); 29 30 int c; 31 while ((c = bfReadr.read()) != -1){ 32 buffOut.write(c); 33 } 34 35 // Note that it should be closed here 36 bfReadr.close(); 37 buffOut.flush(); 38 } 39 buffOut.close(); 40 } 41 42 public static void main(String[] args) throws IOException { 43 String dir = "d:"; 44 String zipPath = "d:/test.zip"; 45 File[] files = Directory.getLocalFiles(dir,".*\\.txt"); 46 ZipFileUtils.compressFiles(files, zipPath); 47 } 48 }
In the main function, we use the Directory tool class in the chapter "File is actually a tool class" in this article.
7.2 unzip the zip package to the target folder
1 public static void unConpressZip(String zipPath, String destPath) throws IOException { 2 if(!destPath.endsWith(File.separator)){ 3 destPath = destPath + File.separator; 4 File file = new File(destPath); 5 if(!file.exists()){ 6 file.mkdirs(); 7 } 8 } 9 // Create a new file input stream class, 10 FileInputStream fis = new FileInputStream(zipPath); 11 12 // Add verification function to input stream 13 CheckedInputStream checkedIns = new CheckedInputStream(fis,new Adler32()); 14 15 // Create a new zip output stream because the file in ZIP format is read 16 ZipInputStream zipIn = new ZipInputStream(checkedIns); 17 18 // Add buffer stream function to improve performance 19 BufferedInputStream buffIn = new BufferedInputStream(zipIn); 20 21 // Read in each ZipEntry object from the zip input stream 22 ZipEntry zipEntry; 23 while ((zipEntry = zipIn.getNextEntry()) != null){ 24 System.out.println("Decompressing" + zipEntry); 25 26 // Write the extracted file to the destination folder 27 int size; 28 byte[] buffer = new byte[1024]; 29 FileOutputStream fos = new FileOutputStream(destPath + zipEntry.getName()); 30 BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length); 31 while ((size = buffIn.read(buffer, 0, buffer.length)) != -1) { 32 bos.write(buffer, 0, size); 33 } 34 bos.flush(); 35 bos.close(); 36 } 37 buffIn.close(); 38 39 // Output checksum 40 System.out.println("Checksum:" + checkedIns.getChecksum().getValue()); 41 } 42 43 // Called directly in the main function 44 public static void main(String[] args) throws IOException { 45 String dir = "d:"; 46 String zipPath = "d:/test.zip"; 47// File[] files = Directory.getLocalFiles(dir,".*\\.txt"); 48// ZipFileUtils.compressFiles(files, zipPath); 49 50 ZipFileUtils.unConpressZip(zipPath,"F:/ziptest"); 51 }
There is another easier way to unzip the zip package, using the ZipFile object. The entries() method of this object directly returns an enumeration of ZipEntry type. Look at the following code snippet:
1 ZipFile zipFile = new ZipFile("test.zip"); 2 Enumeration e = zipFile.entries(); 3 while (e.hasMoreElements()){ 4 ZipEntry zipEntry = (ZipEntry) e.nextElement(); 5 System.out.println("file:" + zipEntry); 6 }
8. Object serialization
8.1 what is serialization and deserialization?
Serialization is the process of converting an object into a byte sequence, and deserialization is the process of reconstituting a byte sequence into an object.
8.2 why is there an object serialization mechanism
The object in the program actually exists in memory. When we close the JVM, it will not continue to exist anyway. Is there a mechanism to make objects "persistent"? The serialization mechanism provides a way for you to input the byte stream of object serialization into a file and save it on disk.
Another meaning of serialization mechanism is that we can transfer objects through the network. For remote method call (RMI) in Java, the bottom layer needs the guarantee of serialization mechanism.
8.3 how to implement serialization and deserialization in Java
First, the object to be serialized must implement a Serializable interface (this is an identification interface and does not include any methods)
1 public interface Serializable { 2 }
The second is to use two object stream classes: ObjectInputStream and ObjectOutputStream. It mainly uses the readObject method of ObjectInputStream object to read in the object and the writeObject method of ObjectOutputStream to write the object to the stream
Next, we write a simple pojo object to the file through the serialization mechanism and read it into the program memory again.
1 public class User implements Serializable { 2 private String name; 3 private int age; 4 5 public User(String name, int age) { 6 this.name = name; 7 this.age = age; 8 } 9 10 @Override 11 public String toString() { 12 return "User{" + 13 "name='" + name + '\'' + 14 ", age='" + age + '\'' + 15 '}'; 16 } 17 18 public static void main(String[] args) throws IOException, ClassNotFoundException { 19 User user = new User("Second battalion commander",18); 20 ObjectOutputStream objectOps = new ObjectOutputStream(new FileOutputStream("f:/user.out")); 21 objectOps.writeObject(user); 22 objectOps.close(); 23 24 // Then take the object out of the file 25 ObjectInputStream objectIns = new ObjectInputStream(new FileInputStream("f:/user.out")); 26 27 // There's going to be a strong turn here 28 User user1 = (User) objectIns.readObject(); 29 System.out.println(user1); 30 objectIns.close(); 31 } 32 }
Program running results:
User{name='Second battalion commander', age='18'}
8.4 data that you do not want to serialize is masked using the transient keyword
If the user object above has a password field that belongs to sensitive information, it cannot be serialized, but the object that implements the Serializable interface will automatically serialize all data fields. What should we do? Just add the keyword transient to the password field.
1 private transient String password;
The serialization mechanism is briefly introduced here. This is Java's native serialization. There are many serialization protocols available on the market, such as Json, fastjason, Thrift, Hessian, protobuf, etc
9. Typical usage of I / O flow
There are many kinds of IO streams. I/O stream classes can be combined in different ways, but usually we use several combinations. The footwall counts the typical usage of several I/O streams by example.
9.1 buffered input file
1 public class BufferedInutFile { 2 public static String readFile(String fileName) throws IOException { 3 BufferedReader bf = new BufferedReader(new FileReader(fileName)); 4 String s; 5 6 // The contents read here exist in StringBuilder. Of course, other processing can also be done 7 StringBuilder sb = new StringBuilder(); 8 while ((s = bf.readLine()) != null){ 9 sb.append(s + "\n"); 10 } 11 bf.close(); 12 return sb.toString(); 13 } 14 15 public static void main(String[] args) throws IOException { 16 System.out.println(BufferedInutFile.readFile("d:/1.txt")); 17 } 18 }
9.2 formatted memory input
To read formatted data, you can use DataInputStream.
1 public class FormattedMemoryInput { 2 public static void main(String[] args) throws IOException { 3 try { 4 DataInputStream dataIns = new DataInputStream( 5 new ByteArrayInputStream(BufferedInutFile.readFile("f:/FormattedMemoryInput.java").getBytes())); 6 while (true){ 7 System.out.print((char) dataIns.readByte()); 8 } 9 } catch (EOFException e) { 10 System.err.println("End of stream"); 11 } 12 } 13 }
The above program will output all the code of the current class itself on the console and throw an EOFException exception. The reason why the exception is thrown is that it has reached the end of the reservation and is still reading data. Here you can use available() to determine how many characters are available.
1 package com.herp.pattern.strategy; 2 3 import java.io.ByteArrayInputStream; 4 import java.io.DataInputStream; 5 import java.io.IOException; 6 7 public class FormattedMemoryInput { 8 public static void main(String[] args) throws IOException { 9 DataInputStream dataIns = new DataInputStream( 10 new ByteArrayInputStream(BufferedInutFile.readFile("FormattedMemoryInput.java").getBytes())); 11 while (true){ 12 System.out.println((char) dataIns.readByte()); 13 } 14 } 15 }
9.3 basic file output
The FileWriter object can write data to a file. First, create a FileWriter associated with the specified file, and then wrap it with BufferedWriter to provide buffering function. In order to provide formatting mechanism, it is decorated as PrintWriter.
1 public class BasicFileOutput { 2 static String file = "BasicFileOutput.out"; 3 4 public static void main(String[] args) throws IOException { 5 BufferedReader in = new BufferedReader(new StringReader(BufferedInutFile.readFile("f:/BasicFileOutput.java"))); 6 PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); 7 8 int lineCount = 1; 9 String s; 10 while ((s = in.readLine()) != null){ 11 out.println(lineCount ++ + ": " + s); 12 } 13 out.close(); 14 in.close(); 15 } 16 }
Here is the basic file output Out file, you can see that we added the line number through the code byte
1: package com.herp.pattern.strategy; 2: 3: import java.io.*; 4: 5: public class BasicFileOutput { 6: static String file = "BasicFileOutput.out"; 7: 8: public static void main(String[] args) throws IOException { 9: BufferedReader in = new BufferedReader(new StringReader(BufferedInutFile.readFile("f:/BasicFileOutput"))); 10: PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file))); 11: 12: int lineCount = 1; 13: String s; 14: while ((s = in.readLine()) != null){ 15: out.println(lineCount ++ + ": " + s); 16: } 17: out.close(); 18: in.close(); 19: } 20: }
9.4 data storage and recovery
In order to output data that can be recovered by another "stream", we need to write data using DataOutputStream, and then recover data using DataInputStream. Of course, these streams can be in any form (the form here is actually the types at both ends of the stream we mentioned earlier), such as files.
1 public class StoringAndRecoveringData { 2 public static void main(String[] args) throws IOException { 3 DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("data.txt"))); 4 out.writeDouble(3.1415926); 5 out.writeUTF("Three company walk"); 6 out.writeInt(125); 7 out.writeUTF("Point praise and attention"); 8 out.close(); 9 10 DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("data.txt"))); 11 System.out.println(in.readDouble()); 12 System.out.println(in.readUTF()); 13 System.out.println(in.readInt()); 14 System.out.println(in.readUTF()); 15 in.close(); 16 } 17 }
Output results:
3.1415926 Three company walk 125 Point praise and attention
Note that we use writeUTF() and readUTF() to write and read strings.