十四、IO
一、概述:
1.流的分类:
按照流向的不同分为:输入流 输出流
按照处理数据单位的不通分为:字节流 字符流(处理的文本文件)
按照角色的不通分为 节点流(直接作用于文件的)处理流
关于处理流的说明:(处理流作用在节点流上)
2.IO的体系:
抽象基类 | 节点流(文件流) | 缓冲流 |
InputStream(字节流) | FileInputStream | BufferedInputStream |
OutputStream(字节流) | FileOutputStream | BufferedOutputStream |
Reader(字符流) | FileReader | BufferedReader |
Writer(字符流) | FileWriter | BufferedWriter |
3.如何使用
- 对于文本文件(.txt,.java,.c,.cpp)使用字符流处理
- 对于非文本文件,使用字节流处理
二、字节流
1、FileReaderd
1.1步骤:
- 创建File类对象,指明要操作的文件;
- 提供具体的流
- 数据的处理
- 关闭应用的流
demo1:从硬盘存在的一个文件中,读取其内容到程序中,使用FileInputStream,显示在控制台上
1 @Test 2 3 public void testStream1() { 4 5 // 2.提供具体的流 6 FileReader fileReader = null; 7 try { 8 9 // 1.创建一个File类的对象,指明要操作的文件 10 11 File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下 12 fileReader = new FileReader(file1); 13 // 3.数据的读入 14 // read() 返回读入的一个字符,文件达到末尾,则返回-1 15 int data = fileReader.read(); 16 while (data != -1) { 17 System.out.print((char) data); 18 data = fileReader.read(); 19 } 20 } catch (FileNotFoundException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } catch (IOException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } finally { 27 // 4.关闭相应的流 28 if (fileReader != null) { 29 try { 30 fileReader.close(); 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 } 35 36 } 37 38 }
注意:要读取的文件一定要存在,否则空指针异常
说明:
- read()的理解:返回读入的一直字符,如果到底文件末尾则返回-1;
- 关于异常的处理,为了保证保证流资源的关闭,这里使用了try catch finally 来处理,这里看到了顺序没有从上到下来,是因为最后做了异常处理导致的;
1.2.关于read方法的详细说明
1.2.1read()方法错误版(只为说明用)
1 / 2 reader 方法升级版(错误版) 3 4 @Description 5 @author lixiuming 6 @date 2021年5月5日上午11:22:37 7 @throws IOException 8 9 / 10 @Test 11 public void testReaderUpgrade2() throws IOException { 12 // 1.File 类的实例化 13 File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下 14 // 2.流的实例化 15 FileReader fileReader = new FileReader(file1); 16 // 3.流的写出 17 char[] charArr = new char[5];// 一次读入多个数据来提高效率 18 int len = fileReader.read(charArr);// 一次读入多个数据,返回每次读入的charArr数组中字符的个数,如果达到文件末尾,返回-1 19 while (len != -1) { 20 for (int i = 0; i < charArr.length; i++) { 21 System.out.print((char) charArr[i]); 22 } 23 len = fileReader.read(charArr); 24 } 25 // 4.流的操作 26 fileReader.close(); 27 28 }
这里的charArr.length;有问题,在文件中,如果hello.txt中的内容是:hello word!! hello lixiuming!!123,那么此时的输出结果就是 hello word!! hello lixiuming!!123!!,多了两个“!!”;
若最后取的数组长度不足5,那么前一个的数组是:
i | n | g | ! | ! |
最后一组数组则是:
1 | 3 | 2 | ! | ! |
没有覆盖掉原来的数据;
1.2.2read()的升级版本正确写法:
1 / 2 reader 方法的升级版(正确版) 3 4 @Description 5 @author lixiuming 6 @throws IOException 7 @date 2021年5月5日上午10:55:53 8 9 / 10 @Test 11 public void testReaderUpgrade() throws IOException { 12 // 1.File 类的实例化 13 File file1 = new File("hello.txt");// 文件位置为当前工程下面,不是当前类下 14 // 2.流的实例化 15 FileReader fileReader = new FileReader(file1); 16 // 3.流的写出 17 char[] charArr = new char[5];// 一次读入多个数据来提高效率 18 int len = fileReader.read(charArr);// 一次读入多个数据,返回每次读入的charArr数组中字符的个数,如果达到文件末尾,返回-1 19 while (len != -1) { 20 for (int i = 0; i < len; i++) { 21 System.out.print((char) charArr[i]); 22 23 } 24 len = fileReader.read(charArr); 25 } 26 // 4.流的操作 27 fileReader.close(); 28 29 }
2.FileWrite
步骤:
- 创建File类对象,指明要操作的文件;
- 提供具体的流
- 数据的处理
- 关闭应用的流
demo:从内存中写出数据到硬盘的文件里的简单说明
1 @Test 2 public void testFileWirter() throws IOException { 3 // 1、提供File类的对象,指明写出到的文件 4 File file = new File("hello2.txt"); 5 // 2.提供FileWrite的对象,用于数据的写出 6 FileWriter fw = new FileWriter(file); 7 // 3.写出的具体操作 8 9 fw.write("I have a dream!"); 10 fw.write("You need have a dream!"); 11 // 4.关闭流 12 fw.close(); 13 14 }
说明:
输出操作,对应File可以不存在,并不会报异常;
如不存在,在输出过程中自动穿件文件
如果存在, a.如果流构造器使用的是FileWriter(file,false)/FileWriter(file),对象会对原有的文件进行覆盖;
b.如果流构造器使用的是FileWriter(file,true) 不会对原有的文件覆盖,而是在原有的文件内追加;
3.文件的复制(FileReader和FileWriter同时使用)
3.1JUNIT测试版:
1 / 2 文件的复制 3 4 @Description 5 @author lixiuming 6 @throws IOException 7 @date 2021年5月5日上午10:19:44 8 9 / 10 @Test 11 public void testFileCopy() { 12 // 2.创建输入和出入流的对象 13 FileReader fr = null; 14 FileWriter fw = null; 15 try { 16 // 1.创建File 类的对象,指明读入和写出的文件 17 File copy = new File("hello.txt"); 18 File copyTo = new File("hello2.txt"); 19 fr = new FileReader(copy); 20 fw = new FileWriter(copyTo); 21 // 3.数据的读入和写出 22 char[] charArr = new char[5]; 23 int len = fr.read(charArr); 24 while (len != -1) { 25 for (int i = 0; i < len; i++) { 26 char data = (char) charArr[i]; 27 fw.write(data); 28 } 29 len = fr.read(charArr); 30 } 31 } catch (Exception e) { 32 } finally { 33 // 4.关闭流资源 34 try { 35 if (fw != null) { 36 fw.close(); 37 } 38 39 } catch (IOException e) { 40 e.printStackTrace(); 41 } finally { 42 if (fr != null) { 43 try { 44 fr.close(); 45 } catch (IOException e) { 46 e.printStackTrace(); 47 } 48 } 49 } 50 51 } 52 53 }
4、FileInputStream/FileOutputStream
4.1步骤:
- 创建File类对象,指明要操作的文件;
- 提供具体的流
- 数据的处理
- 关闭应用的流
说明:用字节流 读取文本文件(中文 数字 英文):控制台中文会有乱码,如果单纯的复制文件没有问题;
使用demo:用字节流读取文本文件
1 @Test 2 public void testFileInputString() { 3 // 2.造流 4 FileInputStream fo = null; 5 try { 6 // 1.造文件 7 File file = new File("hello.txt"); 8 fo = new FileInputStream(file); 9 // 3.文件读出 10 byte[] arr = new byte[5]; 11 int len = fo.read(arr); 12 while (len != -1) { 13 System.out.print(new String(arr, 0, len)); 14 len = fo.read(arr); 15 } 16 } catch (Exception e) { 17 // TODO: handle exception 18 } finally { 19 // 4、流关闭 20 try { 21 if (fo != null) 22 fo.close(); 23 } catch (IOException e) { 24 // TODO Auto-generated catch block 25 e.printStackTrace(); 26 } 27 } 28 29 }
4.2实现图片的复制
1 @Test 2 public void testCopyImg() { 3 // 2.造流 4 FileInputStream fi = null; 5 FileOutputStream fo = null; 6 try { 7 // 1.造文件 8 File copyFile = new File("WX20210407-100610.png"); 9 File copytoFile = new File("collection.png"); 10 fi = new FileInputStream(copyFile); 11 fo = new FileOutputStream(copytoFile); 12 // 3.文件读出 13 byte[] arr = new byte[5]; 14 int len = fi.read(arr); 15 while (len != -1) { 16 for (int i = 0; i < len; i++) { 17 fo.write(arr[i]); 18 } 19 len = fi.read(arr); 20 21 } 22 } catch (Exception e) { 23 // TODO: handle exception 24 } finally { 25 // 4、流关闭 26 try { 27 if (fo != null) 28 fo.close(); 29 } catch (IOException e) { 30 // TODO Auto-generated catch block 31 e.printStackTrace(); 32 } 33 try { 34 if (fi != null) 35 fi.close(); 36 } catch (IOException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 42 }
4.3对文件复制的通用方法:
说明:不能使用字符流复制照片,但是 字节流可以复制文本文件,但是,如果在复制的过程中,想在控制台查看文件,可能会有中文乱码;
1 / 2 复制文件通用方法 3 4 @Description 5 @author lixiuming 6 @date 2021年5月5日下午2:34:36 7 @param srcStr 复制文件地址(文件名) 8 @param destStr 复制到文件的地址(文件名) 9 10 / 11 public void testCopFile(String srcStr, String destStr) { 12 // 2.造流 13 FileInputStream fi = null; 14 FileOutputStream fo = null; 15 try { 16 // 1.造文件 17 File copyFile = new File(srcStr); 18 File copytoFile = new File(destStr); 19 fi = new FileInputStream(copyFile); 20 fo = new FileOutputStream(copytoFile); 21 // 3.文件读出 22 byte[] arr = new byte[1024];// 一般使用1024 23 int len = fi.read(arr); 24 while (len != -1) { 25 for (int i = 0; i < len; i++) { 26 fo.write(arr[i]); 27 } 28 len = fi.read(arr); 29 30 } 31 } catch (Exception e) { 32 // TODO: handle exception 33 } finally { 34 // 4、流关闭 35 try { 36 if (fo != null) 37 fo.close(); 38 } catch (IOException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 try { 43 if (fi != null) 44 fi.close(); 45 } catch (IOException e) { 46 // TODO Auto-generated catch block 47 e.printStackTrace(); 48 } 49 } 50 51 }
三、缓冲流
1.1缓冲流的作用:可以提供效率
1.2使用和步骤
- 创建File类对象,指明要操作的文件;
- 提供具体的流:节点流和缓冲流;
- 数据的处理
- 关闭应用的流
demo:使用缓冲流实现文件的复制:(BufferedInputStream/BufferedOutputStream)
1 / 2 缓冲流实现的文件复制 3 4 @Description 5 @author lixiuming 6 @date 2021年5月5日下午2:58:38 7 8 / 9 @Test 10 public void testCopyFileByBuffer() { 11 BufferedInputStream bi = null; 12 BufferedOutputStream bo = null; 13 // 3.复制 14 byte[] arr; 15 int len; 16 try { 17 // 1.造文件 18 File copy = new File("hello.txt"); 19 File copyTo = new File("hello3.txt"); 20 // 2.造流 21 FileInputStream fi = new FileInputStream(copy); 22 FileOutputStream fo = new FileOutputStream(copyTo); 23 bi = new BufferedInputStream(fi); 24 bo = new BufferedOutputStream(fo); 25 arr = new byte[1024]; 26 len = bi.read(arr); 27 while (len != -1) { 28 for (int i = 0; i < len; i++) { 29 bo.write(arr[i]); 30 } 31 len = bi.read(arr); 32 } 33 } catch (Exception e) { 34 } finally { 35 // 4.关闭资源 36 try { 37 if (bo != null) { 38 bo.close(); 39 } 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 try { 44 if (bi != null) { 45 bi.close(); 46 } 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 } 51 52 }
说明,这里的造流除了 节点流还有缓冲流,因为缓冲流作用在节点流之上;
1.3 缓冲流复制文件的通用方法
1 public void testCopyFileByBuffer(String srcStr, String destStr) { 2 BufferedInputStream bi = null; 3 BufferedOutputStream bo = null; 4 // 3.复制 5 byte[] arr; 6 int len; 7 try { 8 // 1.造文件 9 File copy = new File(srcStr); 10 File copyTo = new File(destStr); 11 // 2.造流 12 // 2.1造节点流 13 FileInputStream fi = new FileInputStream(copy); 14 FileOutputStream fo = new FileOutputStream(copyTo); 15 // 2.2造缓冲流 16 bi = new BufferedInputStream(fi); 17 bo = new BufferedOutputStream(fo); 18 arr = new byte[1024]; 19 len = bi.read(arr); 20 while (len != -1) { 21 for (int i = 0; i < len; i++) { 22 bo.write(arr[i]); 23 } 24 len = bi.read(arr); 25 } 26 } catch (Exception e) { 27 } finally { 28 // 4.关闭资源 29 // 说明,关闭外层流,内层流自动关闭;所以 file的节点流在此处自动关闭 30 try { 31 if (bo != null) { 32 bo.close(); 33 } 34 } catch (IOException e) { 35 e.printStackTrace(); 36 } 37 try { 38 if (bi != null) { 39 bi.close(); 40 } 41 } catch (IOException e) { 42 e.printStackTrace(); 43 } 44 } 45 46 }
1.4BufferReader BufferedWriter 实现文本文件的复制
junit测试版
1 /** 2 * BufferReader BufferedWriter 实现文本文件的复制 3 * 4 * @Description 5 * @author lixiuming 6 * @throws IOException 7 * @date 2021年5月5日下午3:12:32 8 * 9 */ 10 @Test 11 public void testBufferReaderWriter() { 12 BufferedReader bi = null; 13 BufferedWriter bo = null; 14 try { 15 // 1造文件 16 File file = new File("hello.txt"); 17 File copyto = new File("hello4.txt"); 18 // 2.造流 19 FileReader fi = new FileReader(file); 20 FileWriter fo = new FileWriter(copyto); 21 bi = new BufferedReader(fi); 22 bo = new BufferedWriter(fo); 23 // 3.复制的处理过程 24 char[] arr = new char[1024]; 25 int len = bi.read(arr); 26 while (len != -1) { 27 for (int i = 0; i < len; i++) { 28 bo.write(arr[i]); 29 } 30 len = bi.read(arr); 31 } 32 } catch (Exception e) { 33 // TODO: handle exception 34 } finally { 35 // 4.关闭流 36 try { 37 if (bi != null) { 38 bi.close(); 39 } 40 } catch (IOException e) { 41 // TODO Auto-generated catch block 42 e.printStackTrace(); 43 } 44 try { 45 if (bo != null) { 46 bo.close(); 47 } 48 } catch (IOException e) { 49 e.printStackTrace(); 50 } 51 } 52 }
封装版:
1 /** 2 * BufferReader BufferedWriter 实现文本文件的复制 3 * 4 * @Description 5 * @author lixiuming 6 * @throws IOException 7 * @date 2021年5月5日下午3:12:32 8 * 9 */ 10 public void testBufferReaderWriterCopy(String srcStr, String destStr) { 11 BufferedReader bi = null; 12 BufferedWriter bo = null; 13 try { 14 // 1造文件 15 File file = new File(srcStr); 16 File copyto = new File(destStr); 17 // 2.造流 18 FileReader fi = new FileReader(file); 19 FileWriter fo = new FileWriter(copyto); 20 bi = new BufferedReader(fi); 21 bo = new BufferedWriter(fo); 22 // 3.复制的处理过程 23 char[] arr = new char[1024]; 24 int len = bi.read(arr); 25 while (len != -1) { 26 for (int i = 0; i < len; i++) { 27 bo.write(arr[i]); 28 } 29 len = bi.read(arr); 30 } 31 } catch (Exception e) { 32 // TODO: handle exception 33 } finally { 34 // 4.关闭流 35 try { 36 if (bi != null) { 37 bi.close(); 38 } 39 } catch (IOException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 } 43 try { 44 if (bo != null) { 45 bo.close(); 46 } 47 } catch (IOException e) { 48 e.printStackTrace(); 49 } 50 } 51 }
四、其他流
1.转换流(属于字符流 ):
- InputStreamReader:将字节的输入流 转 字符的输入流;
- OutputStreamWriter; 将字符的输出流,转字节的输出流
作用:提供字节流和字符流的转换;
通途:可以编码 和 解码;
demo:使用utf-8读取文件,使用gbk写文件;
1 @Test 2 public void testReaderWriter() { 3 InputStreamReader isr = null; 4 OutputStreamWriter osw = null; 5 try { 6 //1.造文件 7 File strFile = new File("hello.txt"); 8 File destFile = new File("hello_gbk.txt"); 9 //2.造流 10 FileInputStream fi = new FileInputStream(strFile); 11 FileOutputStream fo = new FileOutputStream(destFile); 12 isr = new InputStreamReader(fi, "utf-8"); 13 osw = new OutputStreamWriter(fo, "gbk"); 14 //3.处理 15 char[] arr = new char[1024]; 16 int len = isr.read(arr); 17 while (len != -1) { 18 for (int i = 0; i < len; i++) { 19 osw.write(arr[i]); 20 } 21 len = isr.read(arr); 22 } 23 } catch (Exception e) { 24 // TODO: handle exception 25 }finally { 26 //4.关闭流 27 try { 28 if(isr!=null) { 29 isr.close(); 30 } 31 } catch (IOException e) { 32 // TODO Auto-generated catch block 33 e.printStackTrace(); 34 } 35 try { 36 if(osw!=null) { 37 osw.close(); 38 } 39 } catch (IOException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 } 43 } 44 45 }
2.数据流:处理基本数据类型和String数据;
DataInputStream / DataOutputStream
用于读取或写出基本数据类型的变量或者字符串
readBoolean()
readChar()
readLone()
String readUTF()
readByte()
readFloat()
readShort()
readInt()
void readFully(byte[] b)
demo1:将基本类型数据写出到文件
1 @Test 2 public void testData(){ 3 FileOutputStream fos=null; 4 DataOutputStream dos = null; 5 try { 6 fos = new FileOutputStream("data.txt"); 7 dos = new DataOutputStream(fos); 8 dos.writeUTF("ksdflskdfhslkdf"); 9 dos.writeBoolean(true); 10 dos.writeLong(123123); 11 } catch (Exception e) { 12 // TODO: handle exception 13 }finally { 14 try { 15 if(dos!=null) { 16 dos.close(); 17 } 18 } catch (IOException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 } 23 24 }
demo2:将文件 读入到内存
1 //将基本类型和字符串从文件中读入到内存中,读入的顺序需要和写入时的顺序一致 2 @Test 3 public void testReadData(){ 4 DataInputStream dos = null; 5 try { 6 File file = new File("data.txt"); 7 FileInputStream fos = new FileInputStream(file); 8 dos = new DataInputStream(fos); 9 byte[] arr = new byte[1024]; 10 String str = dos.readUTF(); 11 Boolean bo = dos.readBoolean(); 12 long lo =dos.readLong(); 13 System.out.println(str+"||"+bo+"||"+bo); 14 } catch (Exception e) { 15 // TODO: handle exception 16 }finally { 17 try { 18 if(dos!=null) { 19 dos.close(); 20 } 21 } catch (IOException e) { 22 // TODO Auto-generated catch block 23 e.printStackTrace(); 24 } 25 } 26 }
注意:读入内存过程中,读入的顺序需要和写入时的顺序一致
3.打印流:
字节流:PrintStream
字符流:printWriter
提供了一系列重载的print() 和println()
改变输出位置
1 2 @Test 3 4 public void printSrtreamWriter() { 5 // 设置打印位置 6 PrintStream ps = null; 7 try { 8 File file = new File("hello.txt"); 9 FileOutputStream fos = new FileOutputStream(file); 10 ps = new PrintStream(fos, true); 11 System.setOut(ps); 12 for (int i = 0; i < 255; i++) { 13 System.out.print((char) i); 14 if (i % 50 == 0) { 15 System.out.println();// 换行 16 } 17 } 18 } catch (Exception e) { 19 // TODO: handle exception 20 } finally { 21 if (ps != null) { 22 ps.close(); 23 } 24 } 25 }
4. 标准的输入,输出流
- System.in 标准的输入流,默认键盘输入
- System.out 标准的输出流,默认从控制台输出
- System.setIn()/System.setOut()可以冲洗指定输入和输出;
demo:把输入内容转化成大写,输出,当直接输入“e”或者“exit”时,退出程序
1 @Test 2 public void testSystemIn() { 3 InputStream is = null; 4 5 InputStreamReader isr = null; 6 BufferedReader br = null; 7 8 try { 9 is = System.in; 10 isr = new InputStreamReader(is); 11 br = new BufferedReader(isr); 12 String str = null; 13 while (true) { 14 15 System.out.print("请输入字符串:"); 16 17 str = br.readLine(); 18 19 if (str.equalsIgnoreCase("e") || str.equalsIgnoreCase("exit")) { 20 21 break; 22 23 } else { 24 25 String str1 = str.toUpperCase(); 26 27 System.out.println(str1); 28 29 } 30 31 } 32 } catch (Exception e) { 33 // TODO: handle exception 34 }finally { 35 if(br!=null) 36 try { 37 br.close(); 38 } catch (IOException e) { 39 // TODO Auto-generated catch block 40 e.printStackTrace(); 41 } 42 } 43 44 }
5.对象流
①作用:用于存储和读取基本数据类型数据或者对象的处理流;
序列化:用ObjectOutputStream 类保存基本类型数据或对象的机制
反序列化:用ObjectInputStream 类读取基本类型数据或对象
②对象的序列化机制:允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久的保存到磁盘上,
或者通过网络将这种二进制流传输到另一个网络节点,当其他程序获取了这种二进制流,就可以恢复成原来的java对象;
③序列化的好处:可以将任意实现了Serializable接口的对象转换为字节数据,使其在保存和传输时可被还原;
序列化是RMI过程的传输和返回值都必须实现的机制,而RMI是java EE的基础,因此序列化是javaEE平台的基础
④注意:
如果需要让某个对象支持序列化机制:则必须让对象所属的类及其属性是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一 否则会抛出
NoSerializableException的异常
- Sericalizable
- Externalizable
ObjectInputStream 和 ObjectOutputStream 不能序列化static和transient修饰的成员;
⑤demo示例(只是为了展示基本使用步骤)
1 /** 2 * 对象的序列号(简单版) 3 * 4 * @Description 5 * @author lixiuming 6 * @throws IOException 7 * @date 2021年5月15日下午2:47:12 8 * 9 */ 10 @Test 11 public void testObjectStream() throws IOException { 12 File file = new File("object.dat"); 13 FileOutputStream fi = new FileOutputStream(file); 14 ObjectOutputStream bos = new ObjectOutputStream(fi); 15 bos.writeObject(new String("我爱北京天安门")); 16 bos.close(); 17 } 18 19 /** 20 * 反向过程 21 * 22 * @Description 23 * @author lixiuming 24 * @date 2021年5月15日下午3:01:59 25 * 26 */ 27 @Test 28 public void testInput() { 29 ObjectInputStream bis = null; 30 try { 31 File file = new File("object.dat"); 32 FileInputStream fi = new FileInputStream(file); 33 bis = new ObjectInputStream(fi); 34 byte[] arr = new byte[1024]; 35 String str = (String) bis.readObject(); 36 System.out.println(str); 37 } catch (Exception e) { 38 // TODO: handle exception 39 } finally { 40 try { 41 if (bis != null) { 42 bis.close(); 43 } 44 } catch (IOException e) { 45 // TODO Auto-generated catch block 46 e.printStackTrace(); 47 } 48 } 49 50 }
升级版:
1 / 2 自定义类的序列化 3 4 @Description 5 @author lixiuming 6 @date 2021年5月15日下午3:23:28 7 8 / 9 @Test 10 public void test1() { 11 ObjectOutputStream obs = null; 12 try { 13 File file = new File("Person.dat"); 14 FileOutputStream fo = new FileOutputStream(file); 15 obs = new ObjectOutputStream(fo); 16 Persion persion = new Persion(); 17 persion.setAge(11); 18 persion.setName("李秀明"); 19 obs.writeObject(persion); 20 } catch (Exception e) { 21 // TODO: handle exception 22 } finally { 23 try { 24 if (obs != null) { 25 26 obs.close(); 27 } 28 } catch (IOException e) { 29 // TODO Auto-generated catch block 30 e.printStackTrace(); 31 } 32 } 33 } 34 35 / 36 自定义饭序列化 37 38 @Description 39 @author lixiuming 40 @date 2021年5月15日下午3:44:38 41 42 / 43 @Test 44 public void test2() { 45 ObjectInputStream bis = null; 46 try { 47 File file = new File("Person.dat"); 48 FileInputStream fi = new FileInputStream(file); 49 bis = new ObjectInputStream(fi); 50 Persion persion = (Persion) bis.readObject(); 51 System.out.println(persion.toString()); 52 } catch (Exception e) { 53 // TODO: handle exception 54 } finally { 55 try { 56 if (bis != null) { 57 bis.close(); 58 } 59 } catch (IOException e) { 60 // TODO Auto-generated catch block 61 e.printStackTrace(); 62 } 63 } 64 65 }
涉及到的类:
注意:对类的要求:
- 需要实现接口:serializable
- 当前类提供一个全局常量:serializableUID
- 除了当前类需要实现serializable接口外,还必须保证其内部所有属性也必须是可序列话的 默认情况下,基本数据类型是可序列化的;
补充:ObjectOutputStream 和 ObjectInputStream不能序列化static和transient修饰的成员
1 public class Persion implements Serializable { 2 3 /** 4 * 5 */ 6 private static final long serialVersionUID = -5081496688118179383L; 7 private String name; 8 private int age; 9 private Account account;//必须实现Serializable接口 10 11 public String getName() { 12 return name; 13 } 14 15 public void setName(String name) { 16 this.name = name; 17 } 18 19 public int getAge() { 20 return age; 21 } 22 23 public void setAge(int age) { 24 this.age = age; 25 } 26 27 public Account getAccount() { 28 return account; 29 } 30 31 public void setAccount(Account account) { 32 this.account = account; 33 } 34 35 } 36 37 class Account implements Serializable { 38 /** 39 * 40 */ 41 private static final long serialVersionUID = -3229470228130872968L; 42 private double banlence; 43 44 public double getBanlence() { 45 return banlence; 46 } 47 48 public void setBanlence(double banlence) { 49 this.banlence = banlence; 50 } 51 52 }
6.RandomAccessFile
说明:
1.RdomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
2.RandomAccessFile既可以作为输入流,又可以作为输出流
RandomAccessFile的访问模式:
- r:以只读的方式打开
- rw:打开以后可以读取和写入
- rwd:打开以后可以读取和写入,同步文件内容的更新
- rws:打开以后可以读取和写入,同步文件内容和元数据的更新;
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建,如果存在,则会对原有文件进行覆盖(默认情况下从头覆盖);
4.可以通过相关操作,可以实现对文件的“插入”数据的效果;
(应用场景,文件断点续传)
demo1以照片赋值为例
1 @Test 2 public void testAccessFileStream() { 3 RandomAccessFile af = null; 4 RandomAccessFile af2 = null; 5 try { 6 File file = new File("collection.png"); 7 File file2 = new File("collection22.png"); 8 af = new RandomAccessFile(file, "r"); 9 af2 = new RandomAccessFile(file2, "rw"); 10 byte[] arr = new byte[1024]; 11 int len = af.read(arr); 12 while (len != -1) { 13 for (int i = 0; i < len; i++) { 14 af2.write(arr[i]); 15 } 16 17 len = af.read(arr); 18 } 19 } catch (Exception e) { 20 // TODO: handle exception 21 } finally { 22 try { 23 if (af != null) { 24 af.close(); 25 } 26 } catch (IOException e) { 27 // TODO Auto-generated catch block 28 e.printStackTrace(); 29 } 30 try { 31 if (af2 != null) { 32 33 af2.close(); 34 } 35 } catch (IOException e) { 36 // TODO Auto-generated catch block 37 e.printStackTrace(); 38 } 39 } 40 41 }
demo2关于文件操作
1 //对文件的操作 2 @Test 3 public void testAccessFileStream2() { 4 RandomAccessFile af2 = null; 5 try { 6 File file2 = new File("accessfile.txt"); 7 af2 = new RandomAccessFile(file2, "rw"); 8 af2.seek(12);//指定写入位置(从该位置进行覆盖) 9 af2.write("1234567890".getBytes());//默认情况:文件不存在,则创建,存在,则覆盖(默认从头开始覆盖) 10 11 } catch (Exception e) { 12 // TODO: handle exception 13 } finally { 14 try { 15 if (af2 != null) { 16 17 af2.close(); 18 } 19 } catch (IOException e) { 20 // TODO Auto-generated catch block 21 e.printStackTrace(); 22 } 23 } 24 25 }
五、使用第三方jar包实现数据读写