什么是IO流 I : Input O : Output 通过IO可以完成硬盘文件的读和写。
IO流的分类 有多种分类方式:
一种方式是按照流的方向进行分类: 以内存作为参照物, 往内存中去,叫做输入(Input)。或者叫做读(Read)。 从内存中出来,叫做输出(Output)。或者叫做写(Write)。
另一种方式是按照读取数据方式不同进行分类: 有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制位。 这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频文件等…. 假设文件file1.txt,采用字节流的话是这样读的: a中国bc张三fe 第一次读:一个字节,正好读到’a’ 第二次读:一个字节,正好读到’中’字符的一半。 第三次读:一个字节,正好读到’中’字符的另外一半。
有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取 普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取。 假设文件file1.txt,采用字符流的话是这样读的: a中国bc张三fe 第一次读:’a’字符(’a’字符在windows系统中占用1个字节。) 第二次读:’中’字符(’中’字符在windows系统中占用2个字节。)
综上所述:流的分类输入流、输出流 字节流、字符流
IO流如何学习? Java中的IO流都已经写好了,我们程序员不需要关心,我们最主要还是掌握, 在java中已经提供了哪些流,每个流的特点是什么,每个流对象上的常用方法有 哪些???? java中所有的流都是在:java.io.*;下。
java中主要还是研究: 怎么new流对象。 调用流对象的哪个方法是读,哪个方法是写。
java IO流的四大家族 四大家族的首领:
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
四大家族的首领都是抽象类。(abstract class)
注意:在java中只要“类名”以Stream结尾的都是字节流。以“Reader/Writer”结尾的都是字符流。
所有的流都实现了: java.io.Closeable接口,都是可关闭的,都有close()方法。 流毕竟是一个管道,这个是内存和硬盘之间的通道,用完之后一定要关闭, 不然会耗费(占用)很多资源。养成好习惯,用完流一定要关闭。
所有的输出流都实现了: java.io.Flushable接口,都是可刷新的,都有flush()方法。 养成一个好习惯,输出流在最终输出之后,一定要记得flush() 刷新一下。这个刷新表示将通道/管道当中剩余未输出的数据 强行输出完(清空管道!)刷新的作用就是清空管道。 注意:如果没有flush()可能会导致丢失数据。
需要掌握的IO流 文件专属: java.io.FileInputStream(掌握) java.io.FileOutputStream(掌握) java.io.FileReader java.io.FileWriter
转换流:(将字节流转换成字符流) java.io.InputStreamReader java.io.OutputStreamWriter
缓冲流专属: java.io.BufferedReader java.io.BufferedWriter java.io.BufferedInputStream java.io.BufferedOutputStream
数据流专属: java.io.DataInputStream java.io.DataOutputStream
标准输出流: java.io.PrintWriter java.io.PrintStream(掌握)
对象专属流: java.io.ObjectInputStream(掌握) java.io.ObjectOutputStream(掌握)
1、文件字节输入流,万能的,任何类型的文件都可以采用这个流来读。 2、字节的方式,完成输入的操作,完成读的操作(硬盘—> 内存)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class FileInputStreamTest01 { public static void main (String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream ("D:/course/JavaProjects/02-JavaSE/temp" ); int readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); readData = fis.read(); System.out.println(readData); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
改进版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class FileInputStreamTest02 { public static void main (String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream ("D:\\course\\JavaProjects\\02-JavaSE\\temp" ); int readData = 0 ; while ((readData = fis.read()) != -1 ){ System.out.println(readData); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
int read(byte[] data) 一次最多读取 b.length 个字节。 减少硬盘和内存的交互,提高程序的执行效率。 往byte[]数组当中读。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class FileInputStreamTest03 { public static void main (String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream ("chapter23/src/com/bjpowernode/java/io/tempfile4" ); byte [] bytes = new byte [4 ]; int readCount = fis.read(bytes); System.out.println(readCount); System.out.println(new String (bytes,0 , readCount)); readCount = fis.read(bytes); System.out.println(readCount); System.out.println(new String (bytes,0 , readCount)); readCount = fis.read(bytes); System.out.println(readCount); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
最终版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.io.FileInputStream;import java.io.IOException;public class FileInputStreamTest04 { public static void main (String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream ("chapter23/src/tempfile3" ); byte [] bytes = new byte [4 ]; int readCount; while ((readCount = fis.read(bytes)) != -1 ) { System.out.print(new String (bytes, 0 , readCount)); } } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
其他方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;public class FileInputStreamTest05 { public static void main (String[] args) { FileInputStream fis = null ; try { fis = new FileInputStream ("tempfile" ); System.out.println("总字节数量:" + fis.available()); fis.skip(3 ); System.out.println(fis.read()); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
java.io.FileOutputStream 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class FileOutputStreamTest01 { public static void main (String[] args) { FileOutputStream fos = null ; try { fos = new FileOutputStream ("chapter23/src/tempfile3" , true ); byte [] bytes = {97 , 98 , 99 , 100 }; fos.write(bytes); fos.write(bytes, 0 , 2 ); String s = "我是一个中国人,我骄傲!!!" ; byte [] bs = s.getBytes(); fos.write(bs); fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null ) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
文件的复制原理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;public class Copy01 { public static void main (String[] args) { FileInputStream fis = null ; FileOutputStream fos = null ; try { fis = new FileInputStream ("D:\\course\\02-JavaSE\\video\\chapter01\\动力节点-JavaSE-杜聚宾-001-文件扩展名的显示.avi" ); fos = new FileOutputStream ("C:\\动力节点-JavaSE-杜聚宾-001-文件扩展名的显示.avi" ); byte [] bytes = new byte [1024 * 1024 ]; int readCount = 0 ; while ((readCount = fis.read(bytes)) != -1 ) { fos.write(bytes, 0 , readCount); } fos.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (fos != null ) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null ) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
java.io.FileReader 文件字符输入流,只能读取普通文本。 读取文本内容时,比较方便,快捷。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;public class FileReaderTest { public static void main (String[] args) { FileReader reader = null ; try { reader = new FileReader ("tempfile" ); char [] chars = new char [4 ]; reader.read(chars); for (char c : chars) { System.out.println(c); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null ) { try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
java.io.FileWriter 文件字符输出流。写。 只能输出普通文本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import java.io.FileWriter;import java.io.IOException;public class FileWriterTest { public static void main (String[] args) { FileWriter out = null ; try { out = new FileWriter ("file" , true ); char [] chars = {'我' ,'是' ,'中' ,'国' ,'人' }; out.write(chars); out.write(chars, 2 , 3 ); out.write("我是一名java软件工程师!" ); out.write("\n" ); out.write("hello world!" ); out.flush(); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null ) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 import java.io.FileNotFoundException;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;public class Copy02 { public static void main (String[] args) { FileReader in = null ; FileWriter out = null ; try { in = new FileReader ("chapter23/src/com/bjpowernode/java/io/Copy02.java" ); out = new FileWriter ("Copy02.java" ); char [] chars = new char [1024 * 512 ]; int readCount = 0 ; while ((readCount = in.read(chars)) != -1 ){ out.write(chars, 0 , readCount); } out.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (in != null ) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null ) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
java.io.BufferedReader 带有缓冲区的字符输入流。 使用这个流的时候不需要自定义char数组,或者说不需要自定义byte数组。自带缓冲。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 import java.io.BufferedReader;import java.io.FileReader;public class BufferedReaderTest01 { public static void main (String[] args) throws Exception{ FileReader reader = new FileReader ("Copy02.java" ); BufferedReader br = new BufferedReader (reader); String s = null ; while ((s = br.readLine()) != null ){ System.out.print(s); } br.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 import java.io.BufferedReader;import java.io.FileInputStream;import java.io.InputStream;import java.io.InputStreamReader;public class BufferedReaderTest02 { public static void main (String[] args) throws Exception{ BufferedReader br = new BufferedReader (new InputStreamReader (new FileInputStream ("Copy02.java" ))); String line = null ; while ((line = br.readLine()) != null ){ System.out.println(line); } br.close(); } }
java.io.BufferedWriter 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import java.io.BufferedWriter;import java.io.FileOutputStream;import java.io.FileWriter;import java.io.OutputStreamWriter;public class BufferedWriterTest { public static void main (String[] args) throws Exception{ BufferedWriter out = new BufferedWriter (new OutputStreamWriter (new FileOutputStream ("copy" , true ))); out.write("hello world!" ); out.write("\n" ); out.write("hello kitty!" ); out.flush(); out.close(); } }
java.io.DataOutputStream java.io.DataOutputStream:数据专属的流。 这个流可以将数据连同数据的类型一并写入文件。 注意:这个文件不是普通文本文档。(这个文件使用记事本打不开。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.io.DataOutputStream;import java.io.FileOutputStream;public class DataOutputStreamTest { public static void main (String[] args) throws Exception{ DataOutputStream dos = new DataOutputStream (new FileOutputStream ("data" )); byte b = 100 ; short s = 200 ; int i = 300 ; long l = 400L ; float f = 3.0F ; double d = 3.14 ; boolean sex = false ; char c = 'a' ; dos.writeByte(b); dos.writeShort(s); dos.writeInt(i); dos.writeLong(l); dos.writeFloat(f); dos.writeDouble(d); dos.writeBoolean(sex); dos.writeChar(c); dos.flush(); dos.close(); } }
DataInputStream:数据字节输入流。 DataOutputStream写的文件,只能使用DataInputStream去读。并且读的时候你需要提前知道写入的顺序。 读的顺序需要和写的顺序一致。才可以正常取出数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 import java.io.DataInputStream;import java.io.FileInputStream;public class DataInputStreamTest01 { public static void main (String[] args) throws Exception{ DataInputStream dis = new DataInputStream (new FileInputStream ("data" )); byte b = dis.readByte(); short s = dis.readShort(); int i = dis.readInt(); long l = dis.readLong(); float f = dis.readFloat(); double d = dis.readDouble(); boolean sex = dis.readBoolean(); char c = dis.readChar(); System.out.println(b); System.out.println(s); System.out.println(i + 1000 ); System.out.println(l); System.out.println(f); System.out.println(d); System.out.println(sex); System.out.println(c); dis.close(); } }
java.io.PrintStream java.io.PrintStream:标准的字节输出流。默认输出到控制台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.io.FileOutputStream;import java.io.PrintStream;public class PrintStreamTest { public static void main (String[] args) throws Exception{ System.out.println("hello world!" ); PrintStream ps = System.out; ps.println("hello zhangsan" ); ps.println("hello lisi" ); ps.println("hello wangwu" ); PrintStream printStream = new PrintStream (new FileOutputStream ("log" )); System.setOut(printStream); System.out.println("hello world" ); System.out.println("hello kitty" ); System.out.println("hello zhangsan" ); } }
利用标准输出流编写日志工具: Logger.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.PrintStream;import java.text.SimpleDateFormat;import java.util.Date;public class Logger { public static void log (String msg) { try { PrintStream out = new PrintStream (new FileOutputStream ("log.txt" , true )); System.setOut(out); Date nowTime = new Date (); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss SSS" ); String strTime = sdf.format(nowTime); System.out.println(strTime + ": " + msg); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
LogTest.java:
1 2 3 4 5 6 7 8 9 public class LogTest { public static void main (String[] args) { Logger.log("调用了System类的gc()方法,建议启动垃圾回收" ); Logger.log("调用了UserService的doSome()方法" ); Logger.log("用户尝试进行登录,验证失败" ); Logger.log("我非常喜欢这个记录日志的工具哦!" ); } }
File类 1、File类和四大家族没有关系,所以File类不能完成文件的读和写。 2、File对象代表什么? 文件和目录路径名的抽象表示形式。 C:\Drivers 这是一个File对象 C:\Drivers\Lan\Realtek\Readme.txt 也是File对象。 一个File对象有可能对应的是目录,也可能是文件。 File只是一个路径名的抽象表示形式。 3、需要掌握File类中常用的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 import java.io.File;public class FileTest01 { public static void main (String[] args) throws Exception { File f1 = new File ("D:\\file" ); System.out.println(f1.exists()); File f2 = new File ("D:/a/b/c/d/e/f" ); File f3 = new File ("D:\\course\\01-开课\\学习方法.txt" ); String parentPath = f3.getParent(); System.out.println(parentPath); File parentFile = f3.getParentFile(); System.out.println("获取绝对路径:" + parentFile.getAbsolutePath()); File f4 = new File ("copy" ); System.out.println("绝对路径:" + f4.getAbsolutePath()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;public class FileTest02 { public static void main (String[] args) { File f1 = new File ("D:\\course\\01-开课\\开学典礼.ppt" ); System.out.println("文件名:" + f1.getName()); System.out.println(f1.isDirectory()); System.out.println(f1.isFile()); long haoMiao = f1.lastModified(); Date time = new Date (haoMiao); SimpleDateFormat sdf = new SimpleDateFormat ("yyyy-MM-dd HH:mm:ss SSS" ); String strTime = sdf.format(time); System.out.println(strTime); System.out.println(f1.length()); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.io.File;public class FileTest03 { public static void main (String[] args) { File f = new File ("D:\\course\\01-开课" ); File[] files = f.listFiles(); for (File file : files){ System.out.println(file.getName()); } } }
拷贝目录 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 import java.io.*;public class CopyAll { public static void main (String[] args) { File srcFile = new File ("D:\\course\\02-JavaSE\\document" ); File destFile = new File ("C:\\a\\b\\c" ); copyDir(srcFile, destFile); } private static void copyDir (File srcFile, File destFile) { if (srcFile.isFile()) { FileInputStream in = null ; FileOutputStream out = null ; try { in = new FileInputStream (srcFile); String path = (destFile.getAbsolutePath().endsWith("\\" ) ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\" ) + srcFile.getAbsolutePath().substring(3 ); out = new FileOutputStream (path); byte [] bytes = new byte [1024 * 1024 ]; int readCount = 0 ; while ((readCount = in.read(bytes)) != -1 ){ out.write(bytes, 0 , readCount); } out.flush(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (out != null ) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if (in != null ) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return ; } File[] files = srcFile.listFiles(); for (File file : files){ if (file.isDirectory()){ String srcDir = file.getAbsolutePath(); String destDir = (destFile.getAbsolutePath().endsWith("\\" ) ? destFile.getAbsolutePath() : destFile.getAbsolutePath() + "\\" ) + srcDir.substring(3 ); File newFile = new File (destDir); if (!newFile.exists()){ newFile.mkdirs(); } } copyDir(file, destFile); } } }
序列化与反序列化
序列化 1、java.io.NotSerializableException: Student对象不支持序列化!!!!
2、参与序列化和反序列化的对象,必须实现Serializable接口。
3、注意:通过源代码发现,Serializable接口只是一个标志接口 : public interface Serializable { } 这个接口当中什么代码都没有。 那么它起到一个什么作用呢? 起到标识的作用,标志的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。 Serializable这个标志接口是给java虚拟机参考的,java虚拟机看到这个接口之后,会为该类自动生成 一个序列化版本号。
4、序列化版本号有什么用呢? java.io.InvalidClassException: com.bjpowernode.java.bean.Student; local class incompatible: stream classdesc serialVersionUID = -684255398724514298(十年后), local class serialVersionUID = -3463447116624555755(十年前)
java语言中是采用什么机制来区分类的? 第一:首先通过类名进行比对,如果类名不一样,肯定不是同一个类。 第二:如果类名一样,再怎么进行类的区别?靠序列化版本号进行区分。
小鹏编写了一个类:com.bjpowernode.java.bean.Student implements Serializable 胡浪编写了一个类:com.bjpowernode.java.bean.Student implements Serializable 不同的人编写了同一个类,但“这两个类确实不是同一个类”。这个时候序列化版本就起上作用了。 对于java虚拟机来说,java虚拟机是可以区分开这两个类的,因为这两个类都实现了Serializable接口, 都有默认的序列化版本号,他们的序列化版本号不一样。所以区分开了。(这是自动生成序列化版本号的好处)
请思考? 这种自动生成序列化版本号有什么缺陷? 这种自动生成的序列化版本号缺点是:一旦代码确定之后,不能进行后续的修改, 因为只要修改,必然会重新编译,此时会生成全新的序列化版本号,这个时候java 虚拟机会认为这是一个全新的类。(这样就不好了!)
最终结论: 凡是一个类实现了Serializable接口,建议给该类提供一个固定不变的序列化版本号。 这样,以后这个类即使代码修改了,但是版本号不变,java虚拟机会认为是同一个类。
重点:参与序列化的类型必须实现java.io.Serializable接口。 并且建议将序列化版本号手动的写出来。 private static final long serialVersionUID = 1L;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import java.io.Serializable;public class Student implements Serializable { private static final long serialVersionUID = 1L ; private int no; private int age; private String email; private String address; public Student () { } public Student (int no, String name) { this .no = no; } public int getNo () { return no; } public void setNo (int no) { this .no = no; } @Override public String toString () { return "Student{" + "no=" + no + ", age=" + age + ", email='" + email + '\'' + ", address='" + address + '\'' + '}' ; } }
反序列化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import java.io.FileInputStream;import java.io.ObjectInputStream;public class ObjectInputStreamTest01 { public static void main (String[] args) throws Exception{ ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("students" )); Object obj = ois.readObject(); System.out.println(obj); ois.close(); } }
一次性序列化与反序列化多个对象 transient关键字表示游离的,不参与序列化。
User.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import java.io.Serializable;public class User implements Serializable { private int no; private transient String name; public User () { } public User (int no, String name) { this .no = no; this .name = name; } @Override public String toString () { return "User{" + "no=" + no + ", name='" + name + '\'' + '}' ; } public int getNo () { return no; } public void setNo (int no) { this .no = no; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
ObjectOutputStreamTest02.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.util.ArrayList;import java.util.List;public class ObjectOutputStreamTest02 { public static void main (String[] args) throws Exception{ List<User> userList = new ArrayList <>(); userList.add(new User (1 ,"zhangsan" )); userList.add(new User (2 , "lisi" )); userList.add(new User (3 , "wangwu" )); ObjectOutputStream oos = new ObjectOutputStream (new FileOutputStream ("users" )); oos.writeObject(userList); oos.flush(); oos.close(); } }
ObjectInputStreamTest02.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.io.FileInputStream;import java.io.ObjectInputStream;import java.util.List;public class ObjectInputStreamTest02 { public static void main (String[] args) throws Exception{ ObjectInputStream ois = new ObjectInputStream (new FileInputStream ("users" )); List<User> userList = (List<User>)ois.readObject(); for (User user : userList){ System.out.println(user); } ois.close(); } }
IO+Properties的联合应用 IO流:文件的读和写。 Properties:是一个Map集合,key和value都是String类型。
非常好的一个设计理念: 以后经常改变的数据,可以单独写到一个文件中,使用程序动态读取。 将来只需要修改这个文件的内容,java代码不需要改动,不需要重新编译,服务器也不需要重启。就可以拿到动态的信息。
类似于以上机制的这种文件被称为配置文件。 并且当配置文件中的内容格式是: key1=value key2=value 的时候,我们把这种配置文件叫做属性配置文件。
java规范中有要求:属性配置文件建议以.properties结尾,但这不是必须的。 这种以.properties结尾的文件在java中被称为:属性配置文件。 其中Properties是专门存放属性配置文件内容的一个类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import java.io.FileReader;import java.util.Properties;public class IoPropertiesTest01 { public static void main (String[] args) throws Exception{ FileReader reader = new FileReader ("chapter23/userinfo.properties" ); Properties pro = new Properties (); pro.load(reader); String username = pro.getProperty("username" ); System.out.println(username); String password = pro.getProperty("password" ); System.out.println(password); String data = pro.getProperty("data" ); System.out.println(data); String usernamex = pro.getProperty("usernamex" ); System.out.println(usernamex); } }
在属性配置文件中#是注释 属性配置文件的key重复的话,value会自动覆盖! 最好不要有空格! 建议key和value之间使用=的方式 不建议使用: =左边是key,=右边是value