看到b站韩顺平老师发了IO,自己也没系统总结过IO,写篇文章记录一下吧
文件在程序中以流形式来操作 流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:(往程序输入的流)数据从数据源(文件)到程序(内存)的路径 输出流:(程序往外输出的流)数据从程序(内存)到数据源(文件)的路径
I/O(Input/Output),I/O技术,处理数据传输,例如读写文件,网络通讯 java中数据的输入/输出以“流(stream)”的方式进行 java.io包下提供"流"类和接口,用以获取不同种类的数据,通过方法输入或输出数据
按操作数据单位不同:字节流(8bit二进制位,无损);字符流(按字符操作):记住,二进制文件例如图片、音频、视频等用字节流,不要用字符流。避免不必要的错误发生。
数据流流向不同:输入流、输出流 按流的角色不同:节点流、处理流/包装流
节点流可以从一个特定的数据源读写数据
,如FileReader、FileWriter[源码] 处理流(包装流),连接已存在的流(节点流或处理流)之上
,为程序提供更为强大的读写功能,如BufferedReader、BufferedWriter[源码],他们可以提供内部缓冲区数组
性能提高:以增加缓冲的方式提高输入输出效率 操作便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便 处理流只需要关闭外层流即可(关处理流,会自动将它作用的节点流一起关掉)
假设我们想让Dog dog = new Dog(“黄狗蛋”,3)这个对象持久化到磁盘,并能从文件中恢复对象,就需要用到对象流(ObjectInputStream/ObjectOutputStream)和序列化/反序列化操作 序列化就是保存数据时,保存数据的值和数据类型
反序列化就是恢复数据时,恢复数据的值和数据类型 类想要可序列化,需要让其支持序列化,实现Serializable接口(空接口,标记作用,标记对象可被序列化)或Externalizable(继承Serializable,并声明了两个方法(读和写),一般不用) 实现Serializable接口,最好要生成一个serialVersionUID。是序列化前后的唯一标识符,相当于密钥,序列化时,会根据这个ID序列化,否则会自动生成,一旦修改,后期恢复,因为ID不同,会反序列化失败
一、文件与目录
1. 创建文件
类图:basics_of_java_io/uml/File.puml
new File ( String pathname)
new File ( File parent, String child)
new File ( String parent, String child)
createNewFile ( ) 方法 创建新文件
测试:basics_of_java_io/file/FileCreateTest.java
import java. io. File ;
import java. io. IOException ;
public class FileCreateTest {
public static void main ( String [ ] args) {
FileCreateTest fileCreateTest = new FileCreateTest ( ) ;
fileCreateTest. createByPathName ( "E:\\news1.txt" ) ;
fileCreateTest. createByParentChild ( ) ;
fileCreateTest. createByParentChildPath ( ) ;
}
public void createByPathName ( String pathname) {
File file = new File ( pathname) ;
try {
boolean newFile = file. createNewFile ( ) ;
System . out. println ( pathname+ "文件创建完成" ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void createByParentChild ( ) {
File file = new File ( new File ( "E:\\" ) , "news2.txt" ) ;
try {
boolean newFile = file. createNewFile ( ) ;
System . out. println ( file. getAbsolutePath ( ) + "文件创建完成" ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void createByParentChildPath ( ) {
File file = new File ( "E:\\" , "news3.txt" ) ;
try {
boolean newFile = file. createNewFile ( ) ;
System . out. println ( file. getAbsolutePath ( ) + "文件创建完成" ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
}
2. 获取文件信息
描述(🍅:不常用/🏆:常用) API 🏆获取文件名 String getName() 🏆获取文件绝对路径 String getAbsolutePath() 🏆获取当前file的父路径 String getParent() 🏆获取file长度 Long length() 🏆文件是否存在 boolean exists() 🏆是否是文件 boolean isFile() 🏆是否为目录 boolean isDirectory()
测试:basics_of_java_io/file/FileInformation.java
import java. io. File ;
public class FileInformation {
public static void main ( String [ ] args) {
File file = new File ( "E:/news1.txt" ) ;
System . out. println ( "\uD83C\uDFC6获取文件名:" + file. getName ( ) ) ;
System . out. println ( "\uD83C\uDFC6获取文件绝对路径:" + file. getAbsolutePath ( ) ) ;
System . out. println ( "\uD83C\uDFC6获取当前file的父路径:" + file. getParent ( ) ) ;
System . out. println ( "\uD83C\uDFC6获取file长度:" + file. length ( ) ) ;
System . out. println ( "\uD83C\uDFC6文件是否存在:" + file. exists ( ) ) ;
System . out. println ( "\uD83C\uDFC6是否是文件:" + file. isFile ( ) ) ;
System . out. println ( "\uD83C\uDFC6是否为目录:" + file. isDirectory ( ) ) ;
}
}
3. 操作目录
java中目录也被当做文件
描述(🍅:不常用/🏆:常用) API 🏆创建一级目录 boolean mkdir() 🏆创建多级目录 boolean mkdirs() 🏆删除空目录或指定file boolean delete()
测试:basics_of_java_io/file/DirectoryOperationTest.java
import java. io. File ;
public class DirectoryOperationTest {
public static void main ( String [ ] args) {
File file = new File ( "E:/testDirectory/news1.txt" ) ;
if ( ! file. exists ( ) ) {
file. mkdirs ( ) ;
System . out. println ( "\uD83C\uDFC6mkdirs()创建成功:" + file. getAbsolutePath ( ) ) ;
}
System . out. println ( "\uD83C\uDFC6delete()删除指定文件:" + file. delete ( ) ) ;
}
}
二、字节输入流
1. FileInputStream文件输入流
描述(🍅:构造方法/🏆:普通方法) API 🍅通过打开一个到实际文件的连接创建一个FileInputStream,该文件通过文件系统中的File对象file指定 FileInputStream(File file) 🍅通过使用文件描述符fdObj创建一个FileInputStream,该文件描述符表示到文件系统中某个实际文件的现有连接 FileInputStream(FileDescriptor fdObj) 🍅通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径名name指定 FileInputStream(String name) 🏆返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。 int available() 🏆关闭此文件输入流并释放与此流有关的所有系统资源 void close() 🏆确保在不再引用文件输入流时调用其close方法 protected void finalize() 🏆返回与此文件输入流有关的唯一FileChannel对象 FileChannel get Channel() 🏆返回表示到文件系统中实际文件的连接的FileDescriptor对象,该文件系统正被此FileInputStream使用 FileDescriptor getFD() 🏆从此输入流中读取一个数据字节 int read() 🏆从此输入流中将最多b.length个字节的数据读入一个byte数组中 int read(byte[] b) 🏆从此输入流中将最多len个字节的数据读入一个byte数组中 int read(byte[] b,int off,int len) 🏆从输入流中跳过并丢弃n个字节的数据 long skip(long n)
for example(举例),news1.txt文件内容读取:basics_of_java_io/io_stream/input_stream/FileInputStreamTest.java
import java. io. FileInputStream ;
import java. io. IOException ;
public class FileInputStreamTest {
public static void main ( String [ ] args) {
FileInputStreamTest fileInputStreamTest = new FileInputStreamTest ( ) ;
try {
System . out. println ( "============================使用read()方法读==============================" ) ;
fileInputStreamTest. readTest ( ) ;
System . out. println ( "============================使用read(byte)方法读==============================" ) ;
fileInputStreamTest. readByByteTest ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void readTest ( ) throws IOException {
String filePath = "E:/news1.txt" ;
FileInputStream fileInputStream = new FileInputStream ( filePath) ;
int readData = 0 ;
while ( ( readData = fileInputStream. read ( ) ) != - 1 ) {
System . out. print ( ( char ) readData) ;
}
System . out. println ( ) ;
fileInputStream. close ( ) ;
}
public void readByByteTest ( ) throws IOException {
String filePath = "E:/news1.txt" ;
FileInputStream fileInputStream = new FileInputStream ( filePath) ;
int byteCount = 0 ;
byte [ ] bytes = new byte [ 1024 ] ;
while ( ( byteCount= fileInputStream. read ( bytes) ) != - 1 ) {
System . out. println ( "当前数组实际读出的字节数:" + byteCount) ;
System . out. print ( new String ( bytes) ) ;
}
System . out. println ( ) ;
fileInputStream. close ( ) ;
}
}
2. BufferedInputStream缓冲字节输入流
字节处理流:底层拥有缓冲数组,提高效率;用缓冲流获取news2.txt文本数据(会乱码,不推荐处理文本文件):basics_of_java_io/io_stream/input_stream/BufferedInputStreamTest.java
import java. io. BufferedInputStream ;
import java. io. FileInputStream ;
import java. io. IOException ;
public class BufferedInputStreamTest {
public static void main ( String [ ] args) {
BufferedInputStreamTest bufferedInputStreamTest = new BufferedInputStreamTest ( ) ;
try {
bufferedInputStreamTest. test ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test ( ) throws IOException {
BufferedInputStream bufferedInputStream = new BufferedInputStream ( new FileInputStream ( "E:/news2.txt" ) ) ;
int dataCount = 0 ;
byte [ ] bytes = new byte [ 10 ] ;
while ( ( dataCount = bufferedInputStream. read ( bytes) ) != - 1 ) {
System . out. print ( new String ( bytes, 0 , dataCount) ) ;
}
}
}
三、字节输出流
1. FileOutputStream文件输出流
描述(🍅:构造方法/🏆:普通方法) API 🍅创建向指定file,写入数据的文件输出流 FileOutputStream(File file) 🍅创建向指定file写入数据的文件输出流,并可以指定是否采用追加方式(输出内容到文件末尾追加) FileOutputStream(File file,boolean append) 🍅创建向指定文件描述符处写入数据的文件输出流 FileOutputStream(FileDescriptor fdObj) 🍅创建一个向指定名称文件中写入数据的文件输出流 FileOutputStream(String name) 🍅创建一个向指定名称文件中写入数据的文件输出流,可选追加 FileOutputStream(String name,boolean append) 🏆关闭此文件输出流并释放与此流有关的所有系统资源 void close() 🏆清理文件的连接,确保不再引用此文件输出流时调用此流的close方法 protected void finalize() 🏆返回与此文件输出流有关的唯一FileChannel对象 FileChannel getChannel() 🏆返回与此流有关的文件描述符 FileDescriptor getFD() 🏆将b.length个字节从指定byte数组写入此文件输出流中 void write(byte[] b) 🏆将指定byte数组中从偏移量off开始的len个字节写入此文件输出流 void write(byte[] b,int off,int len) 🏆将指定字节写入此文件输出流 void write(int b)
for example(举例),输出news1.txt内容到news2.txt文件,将文件复制到testDirectory文件夹(注意文件不存在会自动创建,但必须确保目录存在):basics_of_java_io/io_stream/input_stream/FileInputStreamTest.java
import java. io. FileInputStream ;
import java. io. FileOutputStream ;
import java. io. IOException ;
public class FileOutputStreamTest {
public static void main ( String [ ] args) {
FileOutputStreamTest fileOutputStreamTest = new FileOutputStreamTest ( ) ;
try {
fileOutputStreamTest. test3 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test ( ) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream ( "E:/news2.txt" ) ;
FileInputStream fileInputStream = new FileInputStream ( "E:/news1.txt" ) ;
byte [ ] bytes = new byte [ 1024 ] ;
System . out. println ( "从news1.txt文件读取内容:" ) ;
while ( fileInputStream. read ( bytes) != - 1 ) {
System . out. print ( new String ( bytes) ) ;
fileOutputStream. write ( bytes) ;
}
System . out. println ( "写入完成" ) ;
fileInputStream. close ( ) ;
fileOutputStream. close ( ) ;
}
public void test2 ( ) throws IOException {
FileOutputStream fileOutputStream = new FileOutputStream ( "E:/news2.txt" , true ) ;
FileInputStream fileInputStream = new FileInputStream ( "E:/news1.txt" ) ;
byte [ ] bytes = new byte [ 1024 ] ;
System . out. println ( "从news1.txt文件读取内容:" ) ;
while ( fileInputStream. read ( bytes) != - 1 ) {
System . out. print ( new String ( bytes) ) ;
fileOutputStream. write ( bytes) ;
}
System . out. println ( "追加完成" ) ;
fileInputStream. close ( ) ;
fileOutputStream. close ( ) ;
}
public void test3 ( ) throws IOException {
FileInputStream fileInputStream = new FileInputStream ( "E:/su.jfif" ) ;
FileOutputStream fileOutputStream = new FileOutputStream ( "E:/testDirectory/su.jfif" ) ;
int byteCount = 0 ;
byte [ ] bytes = new byte [ 1024 ] ;
while ( ( byteCount = fileInputStream. read ( bytes) ) != - 1 ) {
fileOutputStream. write ( bytes, 0 , byteCount) ;
}
System . out. println ( "复制E:/su.jfif文件到E:/testDirectory/su.jfif成功" ) ;
if ( fileInputStream != null ) {
fileInputStream. close ( ) ;
}
if ( fileOutputStream != null ) {
fileOutputStream. close ( ) ;
}
}
}
2. BufferedOutputStream缓冲字节输出流
字节处理流:将多个字节写入底层输出流中,不必对每次字节写入,都调用底层系统:复制jins.jpg文件
import java. io. * ;
public class BufferedOutputStreamTest {
public static void main ( String [ ] args) {
BufferedOutputStreamTest bufferedOutputStreamTest = new BufferedOutputStreamTest ( ) ;
try {
bufferedOutputStreamTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
BufferedInputStream bufferedInputStream = new BufferedInputStream ( new FileInputStream ( "E:/jins.jpg" ) ) ;
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream ( new FileOutputStream ( "E:/copy.jpg" ) ) ;
System . out. println ( "将E:/jins.jpg复制到E:/copy.jpg" ) ;
int dataCount = 0 ;
byte [ ] bytes = new byte [ 1024 ] ;
while ( ( dataCount = bufferedInputStream. read ( bytes) ) != - 1 ) {
bufferedOutputStream. write ( bytes, 0 , dataCount) ;
}
bufferedOutputStream. close ( ) ;
bufferedInputStream. close ( ) ;
}
}
四、字符输入流
1. FileReader文件字符输入流
描述(🍅:构造方法/🏆:普通方法) API 🍅创建指定file的文件字符输入流 FileReader(File file) 🍅创建指定路径的文件字符输入流 FileReader(String name) 🏆读取单个字符,返回字符int值(char可以自动转换int),到文件末尾返回-1 int read() 🏆批量读取多个字符到数组,返回读取到的字符数,到文件末尾,返回-1 int read(char[])
描述(🍅:构造方法/🏆:普通方法) API 🏆将char[]转换成String new String(char[]) 🏆将char[]的指定部分转换成String new String(char[],off,len)
for example(举例),将如下news3.txt中内容,读取:basics_of_java_io/io_stream/reader/FileReaderTest.java
import java. io. FileReader ;
import java. io. IOException ;
public class FileReaderTest {
public static void main ( String [ ] args) {
try {
FileReaderTest fileReaderTest = new FileReaderTest ( ) ;
fileReaderTest. test2 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
FileReader fileReader = new FileReader ( "E:/news3.txt" ) ;
int data = 0 ;
while ( ( data = fileReader. read ( ) ) != - 1 ) {
System . out. print ( ( char ) data) ;
}
}
public void test2 ( ) throws IOException {
FileReader fileReader = new FileReader ( "E:/news3.txt" ) ;
int dataCount = 0 ;
char [ ] bytes = new char [ 10 ] ;
while ( ( dataCount = fileReader. read ( bytes) ) != - 1 ) {
System . out. print ( new String ( bytes, 0 , dataCount) ) ;
}
}
}
2. BufferedReader缓冲字符输入流
BufferedReader处理流,连接已存在的流(节点流或处理流)之上,关闭时,会自动将作用的节点流关掉:basics_of_java_io/io_stream/reader/BufferedReaderTest.java
import java. io. BufferedReader ;
import java. io. FileReader ;
import java. io. IOException ;
public class BufferedReaderTest {
public static void main ( String [ ] args) {
BufferedReaderTest bufferedReaderTest = new BufferedReaderTest ( ) ;
try {
bufferedReaderTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
System . out. println ( "=====>>>\uD83C\uDFC6BufferedReader处理流封装FileReader节点流,read()方法读取news4中文本,每次读一个字符\uD83C\uDFC6<<<======" ) ;
BufferedReader bufferedReader = new BufferedReader ( new FileReader ( "E:/news3.txt" ) ) ;
int data = 0 ;
while ( ( data = bufferedReader. read ( ) ) != - 1 ) {
System . out. print ( ( ( char ) data) ) ;
}
bufferedReader. close ( ) ;
System . out. println ( "=====>>>\uD83C\uDFC6BufferedReader处理流封装FileReader节点流,read(char[],int,int)方法读取news4中文本,每次读一个字符\uD83C\uDFC6<<<======" ) ;
BufferedReader bufferedReader2 = new BufferedReader ( new FileReader ( "E:/news3.txt" ) ) ;
char [ ] chars = new char [ 10 ] ;
int dataCount = 0 ;
while ( ( dataCount = bufferedReader2. read ( chars) ) != - 1 ) {
System . out. print ( new String ( chars, 0 , dataCount) ) ;
}
bufferedReader2. close ( ) ;
System . out. println ( "==高效===>>>\uD83C\uDFC6readLine()方法读取,每次读一行,遇到换行符就认为一行读完,但是换行符不会读取\uD83C\uDFC6<<<======" ) ;
BufferedReader bufferedReader3 = new BufferedReader ( new FileReader ( "E:/news3.txt" ) ) ;
String readLine = "" ;
while ( ( readLine = bufferedReader3. readLine ( ) ) != null ) {
System . out. println ( readLine) ;
}
bufferedReader3. close ( ) ;
}
}
五、字符输出流
1. FileWriter文件字符输出流
描述(🍅:构造方法/🏆:普通方法) API 🍅创建指定file的文件字符输出流,覆盖模式,每次写入都从文件的开头位置写 FileWriter(File file) 🍅创建指定路径的文件字符输出流,覆盖模式,每次写入都从文件的开头位置写 FileWriter(String name) 🍅创建指定file的文件字符输出流,追加模式,每次写入都从文件末尾写 FileWriter(File file,boolean) 🍅创建指定路径的文件字符输出流,追加模式,每次写入都从文件末尾写 FileWriter(String name,boolean) 🏆写入单个字符 write(int) 🏆写入指定数组 write(char[]) 🏆写入指定数组的指定部分 write(char[],off,len) 🏆写入整个字符串 write(string) 🏆写入字符串的指定部分 write(string,off,len)
描述(🍅:构造方法/🏆:普通方法) API 🏆将String转换成char[] toCharArray()
FileWriter使用后,需要关闭close或刷新flush 否则写入不到指定文件(实际底层写入文件的逻辑,再flush()和close()中调用)
for example(举例),向news4.txt文件写入"打扫宿舍!2!3asdf":basics_of_java_io/io_stream/writer/FileWriterTest.java
import java. io. FileWriter ;
import java. io. IOException ;
public class FileWriterTest {
public static void main ( String [ ] args) {
FileWriterTest fileWriterTest = new FileWriterTest ( ) ;
try {
fileWriterTest. test1 ( ) ;
fileWriterTest. test2 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
FileWriter fileWriter = new FileWriter ( "E:/news4.txt" ) ;
String str = "打扫宿舍!2!3asdf" ;
char [ ] chars = str. toCharArray ( ) ;
for ( char c : chars) {
fileWriter. write ( c) ;
}
System . out. println ( "打扫宿舍!2!3asdf=====>>>已写入到E:/news4.txt" ) ;
fileWriter. flush ( ) ;
fileWriter. close ( ) ;
}
public void test2 ( ) throws IOException {
FileWriter fileWriter = new FileWriter ( "E:/news4.txt" , true ) ;
String str = "打扫宿舍!2!3asdf" ;
char [ ] chars = str. toCharArray ( ) ;
fileWriter. write ( chars) ;
System . out. println ( "打扫宿舍!2!3asdf=====>>>已写入到E:/news4.txt" ) ;
fileWriter. flush ( ) ;
fileWriter. close ( ) ;
}
}
2. BufferedWriter缓冲字符输入流
import java. io. * ;
public class BufferedWriterTest {
public static void main ( String [ ] args) {
BufferedWriterTest bufferedWriterTest = new BufferedWriterTest ( ) ;
try {
bufferedWriterTest. test ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test ( ) throws IOException {
System . out. println ( "===>>>>write(chars),将字符串:BufferedWriter缓冲字符输出流 输到E:/news4.txt<<<====" ) ;
BufferedWriter bufferedWriter = new BufferedWriter ( new FileWriter ( "E:/news4.txt" ) ) ;
String data = "BufferedWriter缓冲字符输入流" ;
char [ ] chars = data. toCharArray ( ) ;
bufferedWriter. write ( chars) ;
bufferedWriter. close ( ) ;
System . out. println ( "===>>>>write(chars),将news1.txt文件中内容,输出到E:/news4.txt,newLine()方法换行<<<====" ) ;
BufferedReader bufferedReader = new BufferedReader ( new FileReader ( "E:/news1.txt" ) ) ;
BufferedWriter bufferedWriter2 = new BufferedWriter ( new FileWriter ( "E:/news4.txt" , true ) ) ;
bufferedWriter2. newLine ( ) ;
int charCount = 0 ;
char [ ] chars1 = new char [ 5 ] ;
while ( ( charCount= bufferedReader. read ( chars1) ) != - 1 ) {
bufferedWriter2. write ( chars1, 0 , charCount) ;
}
bufferedWriter2. close ( ) ;
}
}
六、对象流
系列化和反序列化顺序一直 序列化对象要实现Serializable接口,并最好添加SerialVersionUID,提高版本兼容性 序列化对象时,不会序列化用static和transient修饰的成员,static是类的东西,我们序列化的是实例对象,所以不实例化static,transient是专门标识字段不能序列化的关键字 序列化对象,里面的属性类型也需要实现序列化接口 序列化拥有可继承性,父类实现Serializable接口,子类都会默认实现
1. ObjectInputStream对象字节输入流
将Student对象序列化到student.dat文件:basics_of_java_io/io_stream/objectStream/SerializableTest.java
新建Student实体类(记住重写toString()) 编写序列化代码
import java. io. FileOutputStream ;
import java. io. IOException ;
import java. io. ObjectOutputStream ;
public class SerializableTest {
public static void main ( String [ ] args) {
SerializableTest serializableTest = new SerializableTest ( ) ;
try {
serializableTest. testObjectOutputStream ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void testObjectOutputStream ( ) throws IOException {
Student student = new Student ( ) ;
student. setUsername ( "张三" ) ;
student. setAge ( 15 ) ;
String filePath = "E:/Student.dat" ;
ObjectOutputStream oos = new ObjectOutputStream ( new FileOutputStream ( filePath) ) ;
oos. writeInt ( 10 ) ;
oos. writeBoolean ( true ) ;
oos. writeChar ( 'a' ) ;
oos. writeUTF ( "字符串" ) ;
oos. writeObject ( student) ;
oos. close ( ) ;
System . out. println ( "序列化完成!!!!!!!!!!!!!!!!!!!!!!" ) ;
}
}
2. ObjectOutputStream对象字节输出流
将student.bat文件,反序列化成java对象:basics_of_java_io/io_stream/objectStream/SerializableTest.java
public void testObjectInputStream ( ) throws IOException {
String filePath = "E:/Student.dat" ;
ObjectInputStream ois = new ObjectInputStream ( new FileInputStream ( filePath) ) ;
int read = ois. readInt ( ) ;
boolean b = ois. readBoolean ( ) ;
char c = ois. readChar ( ) ;
String s = ois. readUTF ( ) ;
Student student = null ;
try {
student = ( Student ) ois. readObject ( ) ;
} catch ( ClassNotFoundException e) {
e. printStackTrace ( ) ;
}
ois. close ( ) ;
System . out. println ( "反序列化完毕:==>>" + read+ "==>>" + b+ "==>>" + c+ "==>>" + s+ "==>>" + student+ "==>>" ) ;
}
如果你将toString方法删除(或者随便改点类结构,非变量),只要加了ID依然可以反序列成功
因为ID是我们写死的,但是如果不规定ID,它会根据类结构随机生成,所以我们反序列化的时候,因为去掉了toString方法,导致ID不一致,无法反序列化成功 以下是,不指定UID的情况,我们删除了toString,导致随机生成ID不一致,报错 所以我们只要实现Serializable接口,就尽量生成一个UID
七、标准输入输出流
流 类型 默认设备 System.in InputStream 键盘 System.out PrintStream 显示器
public class ImputAndOutput {
public static void main ( String [ ] args) {
System . out. println ( "System.in 运行类型为 :" + System . in. getClass ( ) ) ;
System . out. println ( "System.out 运行类型为 :" + System . out. getClass ( ) ) ;
}
}
八、转换流
常用于解决乱码问题 处理纯文本数据时,字符流效率更高,可以有效解决中文乱码,建议将字节流转换成字符流 可以指定编码格式,for example(例如):utf-8、gbk、gb2312、ISO8859-1等等
1. InputStreamReader字节输入转换流
Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
通过转换流,使用utf-8编码读取news3.txt文件:basics_of_java_io/io_stream/transformation/InputStreamReaderTest.java
import java. io. BufferedReader ;
import java. io. FileInputStream ;
import java. io. IOException ;
import java. io. InputStreamReader ;
public class InputStreamReaderTest {
public static void main ( String [ ] args) {
InputStreamReaderTest inputStreamReaderTest = new InputStreamReaderTest ( ) ;
try {
inputStreamReaderTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
InputStreamReader isr = new InputStreamReader ( new FileInputStream ( "E:/news3.txt" ) , "UTF-8" ) ;
BufferedReader br = new BufferedReader ( isr) ;
int dataCount = 0 ;
char [ ] chars = new char [ 10 ] ;
while ( ( dataCount = br. read ( chars) ) != - 1 ) {
System . out. print ( new String ( chars, 0 , dataCount) ) ;
}
br. close ( ) ;
}
}
2. OutputStreamWriter字节输出转换流
Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
通过转换流,使用utf-8编码读取news3.txt文件,然后用utf-8编码写入news4.txt:basics_of_java_io/io_stream/transformation/OutputStreamWriterTest.java
import java. io. * ;
public class OutputStreamWriterTest {
public static void main ( String [ ] args) {
OutputStreamWriterTest outputStreamWriterTest = new OutputStreamWriterTest ( ) ;
try {
outputStreamWriterTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
InputStreamReader isr = new InputStreamReader ( new FileInputStream ( "E:/news3.txt" ) , "UTF-8" ) ;
OutputStreamWriter osw = new OutputStreamWriter ( new FileOutputStream ( "E:/news4.txt" ) , "utf-8" ) ;
BufferedWriter bw = new BufferedWriter ( osw) ;
BufferedReader br = new BufferedReader ( isr) ;
int dataCount = 0 ;
char [ ] chars = new char [ 10 ] ;
while ( ( dataCount = br. read ( chars) ) != - 1 ) {
System . out. print ( new String ( chars, 0 , dataCount) ) ;
bw. write ( chars, 0 , dataCount) ;
}
br. close ( ) ;
bw. close ( ) ;
System . out. println ( "用utf-8编码写入完成" ) ;
}
}
九、打印流
专门用来打印的流(到控制台或文件中),只有输出流,没由输入流。可以用来做自己的日志系统
1. PrintStream字节打印流
将System.out.println("");语句的打印位置换成new5.txt文件,不是控制台:basics_of_java_io/io_stream/print/PrintStreamTest.java
import java. io. IOException ;
import java. io. PrintStream ;
import java. nio. charset. StandardCharsets ;
public class PrintStreamTest {
public static void main ( String [ ] args) {
PrintStreamTest printStreamTest = new PrintStreamTest ( ) ;
try {
printStreamTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
PrintStream out = System . out;
out. println ( "通过PrintStream输出信息到控制台" ) ;
out. write ( "println底层调用write完成功能,所以调用write()效果一样" . getBytes ( StandardCharsets . UTF_8) ) ;
System . setOut ( new PrintStream ( "E:/new5.txt" ) ) ;
System . out. println ( "System.setOut(new PrintStream(\"E:/new5.txt\"));将打印位置设置为new5.txt" ) ;
out. flush ( ) ;
out. close ( ) ;
}
}
2. PrintWriter字符打印流
打印字符效率更高,依然可以使用它打印到控制台,或者文件:basics_of_java_io/io_stream/print/PrintWriterTest.java
import java. io. FileWriter ;
import java. io. IOException ;
import java. io. PrintWriter ;
public class PrintWriterTest {
public static void main ( String [ ] args) {
PrintWriterTest printWriterTest = new PrintWriterTest ( ) ;
try {
printWriterTest. test1 ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void test1 ( ) throws IOException {
PrintWriter systemOut = new PrintWriter ( System . out) ;
systemOut. print ( "指定输出流为标准输出流System.out,输出" ) ;
PrintWriter pw = new PrintWriter ( new FileWriter ( "E:/new5.txt" , true ) ) ;
pw. println ( "指定输出流为文件输出流new FileWriter,输出" ) ;
systemOut. close ( ) ;
pw. close ( ) ;
}
}
十、实践
1. 有一个mysql.properties配置文件,读取其中配置
有一个mysql.properties,读取其中配置
import java. io. BufferedReader ;
import java. io. IOException ;
import java. io. InputStream ;
import java. io. InputStreamReader ;
public class ReadProperties {
public static void main ( String [ ] args) {
ReadProperties readProperties = new ReadProperties ( ) ;
try {
readProperties. readTradtion ( ) ;
} catch ( IOException e) {
e. printStackTrace ( ) ;
}
}
public void readTradtion ( ) throws IOException {
InputStream is = ReadProperties . class . getClassLoader ( ) . getResourceAsStream ( "mysql.properties" ) ;
InputStreamReader isr = new InputStreamReader ( is) ;
BufferedReader br = new BufferedReader ( isr) ;
String line = "" ;
while ( ( line = br. readLine ( ) ) != null ) {
String [ ] split = line. split ( "=" ) ;
System . out. println ( split[ 0 ] + "========================>>>>>>" + split[ 1 ] ) ;
}
br. close ( ) ;
}
}
专门用于读写配置文件的集合类(配置文件格式:键=值) 键值对不需要有空格,值不需要用引号,默认String类型
public void readProperties ( ) throws IOException {
URL resource = ReadProperties . class . getClassLoader ( ) . getResource ( "mysql.properties" ) ;
FileReader fileReader = new FileReader ( resource. getFile ( ) ) ;
Properties properties = new Properties ( ) ;
properties. load ( fileReader) ;
String ip = properties. getProperty ( "ip" ) ;
System . out. println ( "通过Properties类读取ip==================>>>>" + ip) ;
fileReader. close ( ) ;
}