2026/3/26 11:46:25
网站建设
项目流程
已经有域名如何做网站,中国科技成就作文素材排比句,廊坊网站建设多少钱,哈尔滨 建设网站 科技文章目录
Java进阶——IO 流 1、File 类的使用 1.1、File 常用构造器1.2、路径分隔符1.3、File 的常用方法 2、IO流原理及流的分类 2.1、IO流原理2.2、流的分类 3、IO流的体系结构4、节点流 4.1、FileReader 读入数据的操作4.2、FileWriter 写出数据的操作4.3、FileReader 和 …文章目录Java进阶——IO 流1、File 类的使用1.1、File 常用构造器1.2、路径分隔符1.3、File 的常用方法2、IO流原理及流的分类2.1、IO流原理2.2、流的分类3、IO流的体系结构4、节点流4.1、FileReader 读入数据的操作4.2、FileWriter 写出数据的操作4.3、FileReader 和 FileWriter 实现文本文件的复制4.4、FileInputStream 和 FileOutputStream 实现非文本文件的复制5、缓存流5.1、BufferedInputStream 和 BufferedOutputStream 实现非文本文件复制5.2、BufferedReader 和 BufferedWriter 实现文本文件复制5.3、练习统计文本中各个字符出现的次数6、转换流6.1、转换流概述6.2、InputStreamReader 的使用6.3、转换流实现文本文件编码转换7、常见的字符编码8、标准输入、输出流9、打印流10、数据流11、对象流11.1、对象流概述11.2、对象流序列化和反序列化字符串11.3、自定义类实现序列化和反序列化12、随机存取文件流12.1、随机存取文件流概述12.2、RandomAccessFile 实现非文本文件的读写复制12.3、RandomAccessFile 实现数据的读写12.4、RandomAccessFile 实现数据的插入Java进阶——IO 流1、File 类的使用java.io.File类:文件和文件目录路径的抽象表示形式与平台无关。File能新建、删除、重命名文件和目录但 File 不能访问文件内容本身。如果需要访问文件内容本身则需要使用输入/输出流。想要在Java程序中表示一个真实存在的文件或目录那么必须有一个File对象但是Java程序中的一个File对象可能没有一个真实存在的文件或目录。File对象可以作为参数传递给流的构造器。1.1、File 常用构造器1、public File(String pathname)以pathname为路径创建File对象可以是绝对路径或者相对路径如果pathname是相对路径则默认的当前路径在系统属性user.dir中存储。绝对路径:是一个固定的路径,从盘符开始相对路径:是相对于某个位置开始代码实例//实例化 File file new File(hello.txt);//相对路径 // 使用\是避免在java中认为是转义字符 File file1 new File(E:\JavaSE\Commonly used常用类\src\io\hi.txt);//绝对路径 //此时File仅仅是内存层面的对象在硬盘中并没有一个真实存在的文件或目录。 System.out.println(file);//hello.txt System.out.println(file1);//E:JavaSECommonly used常用类srciohi.txt2、public File(String parent,String child)以parent为父路径child为子路径创建File对象。代码实例//在E:\JavaSE\Commonly used常用类目录下实例化一个名为Commonly的文件目录 File file2 new File(E:\JavaSE\Commonly used常用类,Commonly); System.out.println(file2);//E:JavaSECommonly used常用类Commonly3、public File(File parent,String child)根据一个父File对象和子文件路径创建File对象代码实例//在E:JavaSECommonly used常用类Commonly目录下实例化一个名为hello.txt的文件 File file4 new File(file2,hello.txt); //在E:JavaSECommonly used常用类Commonly目录下实例化一个名为hello的文件目录 File file5 new File(file2,hello); System.out.println(file4);//E:JavaSECommonly used常用类Commonlyhello.txt System.out.println(file5);//E:JavaSECommonly used常用类Commonlyhello1.2、路径分隔符路径中的每级目录之间用一个路径分隔符隔开。路径分隔符和系统有关:windows和DOS系统默认使用 “” 来表示UNIX和URL使用 “/” 来表示Java程序支持跨平台运行因此路径分隔符要慎用。使用\是避免在java中被认为是转义字符。为了解决这个隐患File类提供了一个常量public static final String separator。根据操作系统动态的提供分隔符。举例File file2 new File(d: File.separator hello” File.separator info.txt);1.3、File 的常用方法File类的获取功能public String getAbsolutePath()获取绝对路径public String getPath()获取路径public String getName()获取名称public String getParent()获取上层文件目录路径。若无返回nullpublic long length()获取文件长度(即:字节数。不能获取目录的长度public long lastModified()获取最后一次的修改时间毫秒值测试代码File file1 new File(hello.md); File file2 new File(D:\io\hi.md); System.out.println(file1.getAbsoluteFile());//获取绝对路径 System.out.println(file1.getPath());//获取路径 System.out.println(file1.getName());//获取名称 System.out.println(file1.getParent());//获取上层文件目录路径。若无返回null System.out.println(file1.length());//获取文件长度(即:字节数。不能获取目录的长度 System.out.println(file1.lastModified());//获取最后一次的修改时间毫秒值 System.out.println(); System.out.println(file2.getAbsoluteFile());//获取绝对路径 System.out.println(file2.getPath());//获取路径 System.out.println(file2.getName());//获取名称 System.out.println(file2.getParent());//获取上层文件目录路径。若无返回null System.out.println(file2.length());//获取文件长度(即:字节数。不能获取目录的长度 System.out.println(file2.lastModified());//获取最后一次的修改时间毫秒值public String[]list()获取指定目录下的所有文件或者文件目录的名称数组public File[] listFiles()获取指定目录下的所有文件或者文件目录的File数组测试代码//该文件目录要存在 File file new File(E:\Redis); String[] list file.list();//获取指定目录下的所有文件或者文件目录的名称数组 for (String s : list){ System.out.println(s); } System.out.println(); File[] files file.listFiles();//获取指定目录下的所有文件或者文件目录的File数组 for (File f : files){ System.out.println(f); }File类的重命名功能public boolean renameTo(File dest)把文件重命名为指定的文件路径测试代码File file new File(hello.md); File file1 new File(D:\io\hello1.md); //要求file在硬盘中存在file1在硬盘中不存在renameTo后原file文件就转移到file1路径下了 boolean b file.renameTo(file1);//把文件重命名为指定的文件路径 System.out.println(b);File类的判断功能public boolean isDirectory()判断是否是文件目录public boolean isFile()判断是否是文件public boolean exists() 判断是否存在public boolean canRead()判断是否可读public boolean canWrite()判断是否可写public boolean isHidden()判断是否隐藏测试代码File file new File(hello.md); File file1 new File(D:\io); System.out.println(file.isDirectory());//判断是否是文件目录 false System.out.println(file1.isDirectory());//判断是否是文件目录 true System.out.println(file.isFile());//判断是否是文件目录 true System.out.println(file1.isFile());//判断是否是文件目录 false System.out.println(file.exists());//判断是否存在 true System.out.println(file1.exists());//判断是否存在 true System.out.println(file.canRead());//判断是否可读 true System.out.println(file.canWrite());//判断是否可写 true System.out.println(file.isHidden());//判断是否隐藏 falseFile类的创建功能与删除public boolean createNewFile()创建文件。若文件存在则不创建返回falsepublic boolean mkdir() 创建文件目录。如果此文件目录存在就不创建了。如果此文件目录的上层目录不存在也不创建public boolean mkdirs()创建文件目录。如果上层文件目录不存在一并创建注意事项如果你创建文件或者文件目录没有写盘符路径那么默认在项目路径下public boolean delete()删除文件或者文件夹删除注意事项Java中的删除不走回收站。要删除一个文件目录请注意该文件目录内不能包含文件或者文件目录。测试代码//文件的创建与删除 File file new File(hello.txt); if (!file.exists()){ file.createNewFile(); System.out.println(创建成功); }else { file.delete(); System.out.println(删除成功); } //文件目录的创建与删除 File file1 new File(D:\io\io1); boolean mkdir file1.mkdir(); if (mkdir){ System.out.println(创建成功1); }else { file1.delete(); System.out.println(删除成功1); } File file2 new File(D:\io2\io3); boolean mkdir2 file2.mkdirs(); if (mkdir2){ System.out.println(创建成功2); }else { file2.delete(); System.out.println(删除成功2); }2、IO流原理及流的分类2.1、IO流原理I/O是Input/Output的缩写I/O技术是非常实用的技术用于处理设备之间的数据传输。如读/写文件网络通讯等。输入input:读取外部数据磁盘、光盘等存储设备的数据到程序内存中。输出output:将程序内存)数据输出到磁盘、光盘等存储设备中。Java程序中对于数据的输入/输出操作以“流(stream)”的方式进行。java.io包下提供了各种“流”类和接口用以获取不同种类的数据并通过标准的方法输入或输出数据。2.2、流的分类按操作数据单位不同分为:字节流(8 bit)字符流(16 bit)按数据流的流向不同分为:输入流输出流按流的角色的不同分为:节点流处理流3、IO流的体系结构1、Java的IO流共涉及40多个类实际上非常规则都是从如下4个抽象基类派生的。抽象基类字节流非文本文件如视频、音乐…字符流文本文件输入流InputStreamReader输出流OutputStreamWriter2、由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。IO流体系4、节点流4.1、FileReader 读入数据的操作把文件中的内容读入到程序中并在控制台输出。使用read()方法Test public void test1(){ FileReader reader null; try { //实例化File对象指明要操作的文件 File file new File(hello.txt); //创建具体的流 reader new FileReader(file); //数据的读入。read()返回读入的一个字符如果读到文件最后就返回-1 int i; while ((i reader.read()) ! -1){ System.out.print((char)i);//helloworld } } catch (IOException e) { e.printStackTrace(); } finally { //关闭流 try { if (reader ! null) reader.close(); } catch (IOException e) { e.printStackTrace(); } } }使用read()的重载方法read(char[] cbuf)Test public void test2() { FileReader fileReader null; try { //实例化File对象指明要操作的文件 File file new File(hello.txt); //创建具体的流 fileReader new FileReader(file); char[] chars new char[5]; int len; //数据的读入,read(char[] cbuf)每次读取cbuf.length个字符到cbuf数组里面返回每次读取的字符的个数读到文件最后返回-1 while ((len fileReader.read(chars)) ! -1){ //方式一 // for (int i 0; i len; i) { // System.out.print(i); // } //方式二 String str new String(chars,0,len); System.out.print(str); } } catch (IOException e) { e.printStackTrace(); } finally { if (fileReader ! null) { try { //关闭资源 fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }4.2、FileWriter 写出数据的操作Test public void test3(){ FileWriter fileWriter null; try { //1.实例化File对象指明要写出到的文件 File file new File(hello1.txt); //2.创建具体的流 fileWriter new FileWriter(file); //3.写出操作 fileWriter.write(I have a dream ); fileWriter.write(you need to have a dream); } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileWriter ! null) //4.关闭资源 fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }说明写出操作对应的文件可以不存在不会报错。File对应的文件在硬盘中如果不存在在写出过程中会自动创建。File对应的文件在硬盘中如果已经存在如果流使用的构造器是 FileWriter(file) 或 FileWriter(file,false)会对原有的文件进行覆盖如果流使用的构造器是 FileWriter(file,true)不会对原有的文件进行覆盖而是在原有文件内容上进行内容追加。4.3、FileReader 和 FileWriter 实现文本文件的复制原理把一个文本文件的内容读入到程序内存中再把内容写出到另一个文本文件中这样就实现了文本文件的复制。Test public void test4() { FileReader fileReader null; FileWriter fileWriter null; try { //1.实例化File对象指明要读入和写出的文件 File oldFile new File(hello.txt); File newFile new File(hello1.txt); //2.创建输入流和输出流 fileReader new FileReader(oldFile); fileWriter new FileWriter(newFile); char[] cbuf new char[5]; int len 0; while((len fileReader.read(cbuf)) ! -1){ fileWriter.write(cbuf,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileWriter ! null) fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fileReader ! null) fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } }4.4、FileInputStream 和 FileOutputStream 实现非文本文件的复制FileInputStream 和 FileOutputStream 属于字节流如果用字节流来读入或写出文本文件可能会出现乱码。Test public void test() { FileInputStream fileInputStream null; FileOutputStream fileOutputStream null; try { //指明要读入和写出的非文本文件 File srcFile new File(1.jpg); File destFile new File(2.jpg); //创建流 fileInputStream new FileInputStream(srcFile); fileOutputStream new FileOutputStream(destFile); byte[] bytes new byte[1024]; int len ; //复制操作 while((len fileInputStream.read(bytes)) ! -1){ fileOutputStream.write(bytes,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭资源 if (fileInputStream ! null) fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fileOutputStream ! null) fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }5、缓存流缓冲流属于处理流的一种。缓存流可以有效提高读取和写入操作的效率。5.1、BufferedInputStream 和 BufferedOutputStream 实现非文本文件复制Test public void test1() { BufferedInputStream bis null; BufferedOutputStream bos null; try { //创建文件对象 File srcFile new File(1.jpg); File destFile new File(3.jpg); //先造节点流 FileInputStream fis new FileInputStream(srcFile); FileOutputStream fos new FileOutputStream(destFile); //再造缓冲流 bis new BufferedInputStream(fis); bos new BufferedOutputStream(fos); //复制操作 byte[] buffer new byte[1024]; int len; while((len bis.read(buffer)) ! -1){ bos.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭资源 说明1.先关闭外层流再关闭内层流 2.在关闭外层流处理流时内层流节点流会自动关闭 try { if (bos ! null) bos.close(); } catch (IOException e) { e.printStackTrace(); } try { if (bis ! null) bis.close(); } catch (IOException e) { e.printStackTrace(); } } }5.2、BufferedReader 和 BufferedWriter 实现文本文件复制Test public void test2() { FileReader fr null; FileWriter fw null; try { //创建文件对象 File srcFile new File(hello.txt); File destFile new File(hello2.txt); //先造节点流 fr new FileReader(srcFile); fw new FileWriter(destFile); //再造缓冲流 BufferedReader br new BufferedReader(fr); BufferedWriter bw new BufferedWriter(fw); //复制操作 //方式一 // char[] buffer new char[1024]; // int len; // while((len br.read(buffer)) ! -1){ // bw.write(buffer,0,len); // } //方式二readLine() 每次读取一行 String data; while ((data br.readLine()) ! null){ bw.write(data);//data中不包含换行符 bw.newLine();//提供换行操作 } } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭资源 if (fw ! null) fw.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fr ! null) fr.close(); } catch (IOException e) { e.printStackTrace(); } } }5.3、练习统计文本中各个字符出现的次数Test public void test3() { FileReader fr null; FileWriter fw null; BufferedWriter bw null; try { //创建HashMapkey为字符value为字符出现的次数 HashMapCharacter, Integer map new HashMap(); fr new FileReader(new File(hello.txt)); int c 0; //读入文件到map中 while ((c fr.read()) ! -1){ //把每次读入的字符转换为char类型 char ch (char) c; //如果该字符在map中不存在 if ((map.get(ch)) null){ //就把该字符作为key添加到map中value为1因为是第一次添加 map.put(ch,1); }else { //如果该字符在map中已经存在就在原有的value上1 map.put(ch,map.get(ch) 1); } } //把map中的数据写出到count.txt fw new FileWriter(new File(count.txt)); //使用缓存流写出数据 bw new BufferedWriter(fw); //遍历map SetMap.EntryCharacter, Integer entrySet map.entrySet(); for (Map.EntryCharacter, Integer entry : entrySet){ switch (entry.getKey()){ case : bw.write(空格 entry.getValue()); break; case : bw.write(tab键 entry.getValue()); break; case : bw.write(回车 entry.getValue()); break; case : bw.write(换行 entry.getValue()); break; default: bw.write(entry.getKey() entry.getValue()); } //换行 bw.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭资源 if (bw ! null) bw.close(); } catch (IOException e) { e.printStackTrace(); } try { if (fr ! null) fr.close(); } catch (IOException e) { e.printStackTrace(); } } }6、转换流6.1、转换流概述转换流也是处理流的一种。转换流提供了在字节流和字符流之间的转换。JavaAPI提供了两个转换流lnputStreamReader将 InputStream 转换为 Reader字节输入流转换成字符输入流OutputStreamWriter将 Writer 转换为 OutputStream字符输出流转换成字节输出流字节流中的数据都是字符时转成字符流操作更高效。很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能。6.2、InputStreamReader 的使用lnputStreamReader将InputStream转换为Reader字节输入流转换成字符输入流Test public void test1(){ InputStreamReader isr null; try { //创建字节输入流 FileInputStream fis new FileInputStream(hello.txt); //转换流第二个参数指明字符集使用的字符集依据文件原本保存时使用的字符集如不指定就使用系统默认的字符集 isr new InputStreamReader(fis,utf-8); char[] cbuf new char[1024]; int len; while ((len isr.read(cbuf)) ! -1){ String str new String(cbuf,0,len); System.out.println(str); } } catch (IOException e) { e.printStackTrace(); } finally { try { //关闭资源 if (isr ! null) isr.close(); } catch (IOException e) { e.printStackTrace(); } } }6.3、转换流实现文本文件编码转换Test public void test2(){ InputStreamReader isr null; OutputStreamWriter osw null; try { //原文本文件File对象 File file new File(hello.txt); //转换后的gbk编码的文件File对象 File file1 new File(hello_gbk.txt); //创建节点流 FileInputStream fis new FileInputStream(file); FileOutputStream fos new FileOutputStream(file1); //创建转换流并指明字符集编码 isr new InputStreamReader(fis,utf-8); osw new OutputStreamWriter(fos,gbk); char[] cbuf new char[1024]; int len; while ((len isr.read(cbuf)) ! -1) { osw.write(cbuf,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (osw ! null) osw.close(); } catch (IOException e) { e.printStackTrace(); } try { if (isr ! null) isr.close(); } catch (IOException e) { e.printStackTrace(); } } }查看原文本文件运行后查看转换后的gbk格式的文本文件7、常见的字符编码编码表的由来计算机只能识别二进制数据早期由来是电信号。为了方便应用计算机让它可以识别各个国家的文字。就将各个国家的文字用数字来表示并一一对应形成一张表。这就是编码表。常见的编码表ASCIIl美国标准信息交换码。用一个字节的7位可以表示。ISO8859-1;拉丁码表。欧洲码表。用一个字节的8位表示。GB2312中国的中文编码表。最多两个字节编码所有字竹GBK中国的中文编码表升级融合了更多的中文文字符号。最多两个字节编码Unicode国际标准码融合了目前人类使用的所有字符。为每个字符分配唯一的字竹码。所有的文字都用两个字节来表示。UTF-8变长的编码方式可用1-4个字节来表示一个字符。Unicode不完美这里就有三个问题一个是我们已经知道英文字母只用一个字节表示就够了第二个问题是如何才能区别Unicode和ASCII计算机怎么知道两个字节表示一个符号而不是分别表示两个符号呢第三个如果和GBK等双字节编码方式一样用最高位是1或O表示两个字节和一个字节就少了很多值无法用于表示字符不够表示所有字符。Unicode在很长一段时间内无法推广直到互联网的出现。面向传输的众多 UTFUCS Transfer Format标准出现了顾名思义UTF-8就是每次8个位传输数据而UTF-16就是每次16个位。这是为传输而设计的编码并使编码无国界这样就可以显示全世界上所有文化的字符了。Unicode只是定义了一个庞大的、全球通用的字符集许为每个字符规定了唯一确定的编号具体存储成什么样的字节流取决于字符编码方案。推荐的Unicode编码是UTF-8利IUTF-16。8、标准输入、输出流标准输入、输出流的概述标准输入、输出流也是处理流的一种。Systejn.in和System.out分别代表了系统标准的输入和输出设备。默认输入设备是键盘输出设备是显示器System.in的类型是InputStream输入节点流System.out的类型是PrintStream打印流其是OutputStream的子类FilterOutputStream的子类重定向:通过System类的setlnsetOut方法对默认设备进行改变。public static void setln(InputStream in)public static void setOut(PrintStream out)标准输入、输出流的使用从键盘输入字符串要求将读取到的整行字符串转成大写输出。然后继续进行输入操作直至当输入“e”或者“exit”时退出程序。public class OtherStreamTest { public static void main(String[] args) { BufferedReader br null; try { //使用转换流把System.in转换成字符流 InputStreamReader isr new InputStreamReader(System.in); //创建输入字符缓存流 br new BufferedReader(isr); while (true){ System.out.println(请输入); String data br.readLine(); if (data.equalsIgnoreCase(e) || exit.equalsIgnoreCase(data)){ System.out.println(程序退出); break; } System.out.println(data.toUpperCase()); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br ! null) br.close(); } catch (IOException e) { e.printStackTrace(); } } } }运行结果9、打印流打印流概述打印流也是处理流的一种。实现将基本数据类型的数据格式转化为字符串输出。打印流PrintStreamFPrintWriter提供了一系列重载的print()和println()方法用于多种数据类型的输出PrintStream和PrintWriter的输出不会抛出IOException异常PrintStream和PrintWriter有自动flush功能PrintStream打印的所有字符都使用平台的默认字符编码转换为字节。在需要写入字符而不是写入字节的情况下应该使用PrintWriter类。System.out返回的是PrintStream的实例打印流使用打印ASCL字符到指定文件中Test public void test1(){ PrintStream ps null; try { File file new File(D:\io\ascll.txt); FileOutputStream fos new FileOutputStream(file); //创建打印输出流 ps new PrintStream(fos,true);//自动刷新模式写入换行符或字节“ ”时都会刷新输出缓存区 if (ps ! null){ //对输出设备改变指定输出到文件中不再输出到控制台中 System.setOut(ps); } for (int i 0; i 255; i) {//输出ASCLL字符 System.out.print((char)i); if (i % 50 0){//50个换行 System.out.println(); } } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { try { if (ps ! null) ps.close(); } catch (Exception e) { e.printStackTrace(); } } }查看ascll.txt文件10、数据流数据流的概述数据流也是处理流的一种。为了方便地读取或写出Java语言的基本数据类型和String的数据可以使用数据流。数据流有两个类 DatalnputStream 和 DataOutputStream(用于读取和写出基本数据类型、String类的数据)。分别“套接”在 InputStream 和 OutputStream子类的流上DatalnputStream中的方法double readDouble()byte readByte()char readChar()float readFloat()double readDouble()short readShort()long readLong()int readInt()String readUTF()void readFully(byte[] b)DataOutputStream中的方法将上述的方法的read改为相应的write即可。数据流的使用将内存中的数据写入到硬盘文件中Test public void test2(){ DataOutputStream dos null; try { //创建节点流 FileOutputStream fos new FileOutputStream(data.txt); dos new DataOutputStream(fos); //将数据写出到文件中 dos.writeUTF(万里顾一程); dos.flush(); dos.writeInt(18); dos.flush(); dos.writeBoolean(true); dos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dos ! null) dos.close(); } catch (IOException e) { e.printStackTrace(); } } }将硬盘文件中的数据读取出来并输出到控制台Test public void test3(){ DataInputStream dis null; try { FileInputStream fis new FileInputStream(data.txt); dis new DataInputStream(fis); //数据读取的顺序要和数据写入时的顺序一样 String name dis.readUTF(); int age dis.readInt(); boolean isMan dis.readBoolean(); System.out.println(name); System.out.println(age); System.out.println(isMan); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dis ! null) dis.close(); } catch (IOException e) { e.printStackTrace(); } } }查看控制台输出11、对象流11.1、对象流概述对象流是处理流的一种。对象流有两个类ObjectInputStream 和 OjbectOutputSteam用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中也能把对象从数据源中还原回来。序列化用 ObjectOutputStream 类保存基本类型数据或对象的机制反序列化用 ObjectInputStream 类读取基本类型数据或对象的机制ObjectOutputStream 和ObjectlnputStream 不能序列化 static 和 ltransient不可序列化 修饰的成员变量对象的序列化机制对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流从而允许把这种二进制流持久地保存在磁盘上或通过网络将这种二进制流传输到另一个网络节点序列化当其它程序获取了这种二进制流就可以恢复成原来的Java对象反序列化。序列化的好处在于可将任何实现了 Serializable 接口的对象转化为字节数据使其在保存和传输时可被还原。序列化是RMI (Remote Method Invoke-远程方法调用过程的参数和返回值都必须实现的机制而RMI是 JavaEE的基础。因此序列化机制是JavaEE平台的基础。如果需要让某个对象支持序列化机制则必须让对象所属的类及其属性是可序列化的为了让某个类是可序列化的该类必须实现如下两个接口之一。否则会抛出NotSerializableException异常。SerializableExternalizable11.2、对象流序列化和反序列化字符串序列化Test public void test(){ ObjectOutputStream oos null; try { //创建对象流进行序列化操作 oos new ObjectOutputStream(new FileOutputStream(object.data)); //序列化字符串对象 oos.writeObject(new String(万里顾一程)); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (oos ! null) oos.close(); } catch (IOException e) { e.printStackTrace(); } } }反序列化Test public void test1(){ ObjectInputStream ois null; try { //创建对象流进行反序列化操作 ois new ObjectInputStream(new FileInputStream(object.data)); //读取对象数据并打印 Object str ois.readObject(); System.out.println((String) str); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { if (ois ! null) ois.close(); } catch (IOException e) { e.printStackTrace(); } } }11.3、自定义类实现序列化和反序列化自定义类package io; import java.io.Serializable; //1.实现Serializable 接口 public class Person implements Serializable { //2.添加序列化版本号 private static final long serialVersionUID 434543632352672L; //3.所有属性也必须是可序列化的 private int id; private String name; public Person() { } public Person(int id, String name) { this.id id; this.name name; } public int getId() { return id; } public void setId(int id) { this.id id; } public String getName() { return name; } public void setName(String name) { this.name name; } Override public String toString() { return Person{ id id , name name }; } }序列化版本号介绍凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态常量private static final long serialVersionUID。serialVersionUID用来表明类的不同版本间的兼容性。简言之其目的是以序列化对象进行版本控制有关各版本反序亚化时是否兼容。如果类没有显示定义这个静态常量它的值是Java运行时环境根据类的内部细节自动生成的。若类的实例变量做了修改serialVersionUID可能发生变化。故建议显式声明。简单来说Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较如果相同就认为是一致的可以进行反序列化否则就会出现序列化版本不一致的异常(InvalidCastException)。序列化Test public void test(){ ObjectOutputStream oos null; try { //创建对象流进行序列化操作 oos new ObjectOutputStream(new FileOutputStream(object.data)); //序列化字对象 oos.writeObject(new Person(1,万里顾一程)); oos.flush(); oos.writeObject(new Person(2,神明)); oos.flush(); oos.writeObject(new Person(3,桃仙)); oos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (oos ! null) oos.close(); } catch (IOException e) { e.printStackTrace(); } } }反序列化Test public void test1(){ ObjectInputStream ois null; try { //创建对象流进行反序列化操作 ois new ObjectInputStream(new FileInputStream(object.data)); Object str ois.readObject(); Object str1 ois.readObject(); Object str2 ois.readObject(); System.out.println((Person) str); System.out.println((Person) str1); System.out.println((Person) str2); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } finally { try { if (ois ! null) ois.close(); } catch (IOException e) { e.printStackTrace(); } } }12、随机存取文件流12.1、随机存取文件流概述随机存取文件流也是处理流的一种。随机存取文件流的类是 RandomAccessFile。RandomAccessFile既可以作为输入流也可以作为输出流。RandomAccessFile声明在java.io包下但直接继承于java.lang.Object类。并且它实现了Datalnput、DataOutput这两个接口也就意味着这个类既可以读也可以写。RandomAccessFile类支持“随机访问”的方式程序可以直接跳到文件的任意地方来读、写文件支持只访问文件的部分内容也支持向已存在的文件后追加内容RandomAccessFile对象包含一个记录指针用以标示当前读写处的位置。RandomAccessFile类对象可以自由移动记录指针long getFilePointer()获取文件记录指针的当前位置void seek(long pos)将文件记录指针定位到pos位置构造器public RandomAccessFile(File file,String mode)public RandomAccessFile(String name, String mode)创建RandomAccessFile类实例需要指定一个mode参数该参数指定 RandomAccessFile 的访问模式r:以只读方式打开rw:打开以便读取和写入rwd:打开以便读取和写入;同步文件内容的更新rws:打开以便读取和写入;同步文件内容和元数据的更新如果模式为只读r。则不会创建文件而是会去读取一个已经存在的文件如果读取的文件不存在则会出现异常。如果模式为rw读写如果文件不存在则会去创建文件如果存在则不会创建。12.2、RandomAccessFile 实现非文本文件的读写复制Test public void test3(){ RandomAccessFile raf null; RandomAccessFile raf1 null; try { //创建RandomAccessFile对象访问模式为以只读的方式打开文件 raf new RandomAccessFile(1.jpg,r); //创建RandomAccessFile对象访问模式为以读和写的方式打开文件 raf1 new RandomAccessFile(4.jpg,rw); byte[] buffer new byte[1024]; int len; while ((len raf.read(buffer)) ! -1){ raf1.write(buffer,0,len); } } catch (IOException e) { e.printStackTrace(); } finally { if (raf1 ! null) { try { raf1.close(); } catch (IOException e) { e.printStackTrace(); } } if (raf ! null){ try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } } }12.3、RandomAccessFile 实现数据的读写如果 RandomAccessFile 作为输出流写出到的文件如果不存在则会创建该文件如果写出到的文件已存在则会从头开始覆盖原文件的内容。Test public void test4(){ RandomAccessFile raf null; try { //创建RandomAccessFile对象访问模式为以读和写的方式打开文件 raf new RandomAccessFile(hello1.txt,rw); raf.write(abcdefg.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (raf ! null){ try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } } }12.4、RandomAccessFile 实现数据的插入Test public void test5(){ RandomAccessFile raf null; try { raf new RandomAccessFile(hello3.txt,rw); //将文件记录指针定位到角标为3的位置从0开始就是插入位置 raf.seek(3); //创建 StringBuilder 存储插入位置后面的字符串 StringBuilder sb new StringBuilder((int) new File(hello1.txt).length()); int len ; byte[] buffer new byte[1024]; while ((len raf.read(buffer)) ! -1){ sb.append(new String(buffer,0,len)); } //将角标调回为3的位置 raf.seek(3); raf.write(xxx.getBytes()); //将StringBuilder中的字符串写回 raf.write(sb.toString().getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { if (raf ! null){ try { raf.close(); } catch (IOException e) { e.printStackTrace(); } } } }插入前插入后