飞道的博客

IO流的总结

170人阅读  评论(0)

 

 

1:IO流的原理

  • IO是Input/Output的缩写,用于处理设备之间的数据传输,如读写文件、网络通讯
  • Java程序中,对于数据的输入/输出操作以“流”的方式进行
  • java.io包下提供了各种流的接口和类,通过标准的方法输入或输出数据

2:流的分类

2.1:节点流和处理流的区别

处理流需要包装在节点流上

2.2:IO的体系

2.3:InputStream & Reader 的介绍

2.3.1:InputStream的方法

2.3.2:Reader的方法

2.4:OutputStream & Writer的介绍

2.4.1:OutputStream的常用方法

2.4.2:Writer的常用方法

2.5:举例说明


   
  1. 1:
  2. File file = new File("hello.txt");// F:\javaSenior\hello.txt 相较于当前工程,不是想当于module下面
  3. System.out.println(file.getAbsolutePath());
  4. File file1 = new File("day09\\hello.txt");//F:\javaSenior\day09\hello.txt
  5. System.out.println(file1.getAbsolutePath());

在IDEA中,在main()方法里面创建的文件的路径是相对于工程下面的,不是相对于module,在Test测试方法里面是相对于module

2:将day09下的hello.txt文件内容读入程序中,并输出到控制台   hello.txt里面写的是abc123中国人

说明点: 1. read()的理解:返回读入的一个字符。如果达到文件末尾,返回-1

2. 异常的处理:为了保证流资源一定可以执行关闭操作。需要使用try-catch-finally处理

3. 读入的文件一定要存在,否则就会报FileNotFoundException。


   
  1. //1:实例化File类的对象,指明要操作的文件
  2. File file=new File( "hello.txt"); //相对于当前module下的
  3. //2:提供具体的流
  4. FileReader fr=new FileReader(file);
  5. //3:数据的读入
  6. read():返回读入的一个字符,如果达到文件的末尾,返回- 1
  7. //方式一:
  8. int data=fr.read();
  9. while( data!=- 1)
  10. {
  11. System. out.println((char) data);
  12. data=fr.read();
  13. }
  14. //方式二:
  15. int data;
  16. while(( data = fr.read()) != - 1){
  17. System. out.print((char) data);
  18. }

通过read()方法


   
  1. //1:实例化File类的对象,指明要操作的文件
  2. File file= new File( "hello.txt"); //相对于当前module下的
  3. //2:提供具体的流
  4. FileReader fr= new FileReader(file);
  5. //3.读入的操作
  6. //read(char[] cbuf):返回每次读入cbuf数组中的字符的个数。如果达到文件末尾,返回-1
  7. char[] cbuf = new char[ 6];
  8. int len;
  9. while((len = fr.read(cbuf)) != -1){
  10. //方式一:
  11. //错误的写法
  12. for( int i = 0;i < cbuf.length;i++){
  13. System. out.print(cbuf[i]); //txt文件是abc123中国人,数组的长度是5,每次要读入五个字符,第一次读出abc123,第二次读的时候用中国人去覆盖上一次的abc,123仍然还在,所以第二次读出的是中国人123,结果输出的是abc123中国人123
  14. }
  15. //正确的写法
  16. // for(int i = 0;i < len;i++){
  17. // System.out.print(cbuf[i]);//每次读出字符实际的长度
  18. // }
  19. //方式二:
  20. //错误的写法,对应着方式一的错误的写法
  21. // String str = new String(cbuf);
  22. // System.out.print(str);
  23. //正确的写法
  24. // String str = new String(cbuf,0,len);
  25. // System.out.print(str);

总结:read(char[])方法在读取数据的时候,用下次去取出的字符去替代上一次所读出的字符(从下标0开始),所以读出的时候我们应该去取读出的实际长度。

3:从内存中写出数据到硬盘的文件里。输出操作


   
  1. 1. 输出操作,对应的File可以不存在的。并不会报异常
  2. 2.
  3. File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。
  4. File对应的硬盘中的文件如果存在:
  5. 如果流使用的构造器是:FileWriter(file,false) / FileWriter(file):对原有文件的覆盖
  6. 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有文件基础上追加内容
  7. */
  8. @Test
  9. public void testFileWriter() {
  10. FileWriter fw = null;
  11. try {
  12. //1.提供File类的对象,指明写出到的文件
  13. File file = new File("hello4.txt");
  14. //2.提供FileWriter的对象,用于数据的写出
  15. fw = new FileWriter(file,false);
  16. //3.写出的操作
  17. fw.write("I have a dream!\n");
  18. fw.write("you need to have a dream!");
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally {
  22. //4.流资源的关闭
  23. if(fw != null){
  24. try {
  25. fw.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }

4:将一个文件复制到另外一个文件


   
  1. @Test
  2. public void testFileReaderFileWriter() {
  3. FileReader fr = null;
  4. FileWriter fw = null;
  5. try {
  6. //1.创建File类的对象,指明读入和写出的文件
  7. File srcFile = new File( "hello.txt");
  8. File destFile = new File( "hello2.txt");
  9. //不能使用字符流来处理图片等字节数据
  10. // File srcFile = new File("爱情与友情.jpg");
  11. // File destFile = new File("爱情与友情1.jpg");
  12. //2.创建输入流和输出流的对象
  13. fr = new FileReader(srcFile);
  14. fw = new FileWriter(destFile);
  15. //3.数据的读入和写出操作
  16. char[] cbuf = new char[ 5];
  17. int len; //记录每次读入到cbuf数组中的字符的个数
  18. while((len = fr.read(cbuf)) != - 1){
  19. //每次写出len个字符
  20. fw.write(cbuf, 0,len);
  21. }
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. } finally

 

3:FileInputStream/FileInputStream说明

      3.1:文件的输出


  
  1. FileInputStream fis = null;
  2. try {
  3. //1. 造文件
  4. File file = new File( "hello.txt");
  5. //2.造流
  6. fis = new FileInputStream(file);
  7. int size = fis.available(); //这个方法可以预估字节流文件里面预估的流,一次读完
  8. //3.读数据
  9. byte[] buffer = new byte[size];
  10. int len; //记录每次读取的字节的个数
  11. while((len = fis.read(buffer)) != -1){
  12. String str = new String(buffer, 0,size);
  13. System. out.println(str);
  14. System. out.println( "************"); //总共只执行了一次
  15. }
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. } finally {
  19. if(fis != null){
  20. //4.关闭资源
  21. try {
  22. fis.close();
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. }
  26. }
  27. }
  28. }
使用字节流FileInputStream处理文本文件,可能出现乱码。

//1:造文件

File file = new File("hello.txt");
//2.造流
FileInputStream fis = new FileInputStream(file);
//3.读数据
byte[] buffer = new byte[2];
int len;//记录每次读取的字节的个数
while((len = fis.read(buffer)) != -1){

    String str = new String(buffer,0,size);
    System.out.println(str);

}

假设:"hello.txt"里面有“a中国”三个字符,由于buffer数组每次读两个字节流,那么第一个字节流给a,另外一个字节流给“中”字,由于UTF-8一个汉字三个字节流,那么它另外两个字节流需要占用下一次读取的,会造成乱码,

解决方法:用字节流、或者给数组开辟的空间足够大,一次可以读取所有的字符

3.2:实现对图片的复制


  
  1. /*
  2. 实现对图片的复制操作
  3. */
  4. @Test
  5. public void testFileInputOutputStream() {
  6. FileInputStream fis = null;
  7. FileOutputStream fos = null;
  8. try {
  9. //
  10. File srcFile = new File( "爱情与友情.jpg");
  11. File destFile = new File( "爱情与友情2.jpg");
  12. //
  13. fis = new FileInputStream(srcFile);
  14. fos = new FileOutputStream(destFile);
  15. //复制的过程
  16. byte[] buffer = new byte[ 5];
  17. int len;
  18. while((len = fis.read(buffer)) != - 1){
  19. fos.write(buffer, 0,len);
  20. }
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. } finally {
  24. if(fos != null){
  25. //
  26. try {
  27. fos.close();
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }
  31. }
  32. if(fis != null){
  33. try {
  34. fis.close();
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. }
  40. }

4:节点流(或文件流):注意点

5:缓冲流

5.1:图片复制的案例


  
  1. @Test
  2. public void BufferedStreamTest() throws FileNotFoundException {
  3. BufferedInputStream bis = null;
  4. BufferedOutputStream bos = null;
  5. try {
  6. //1.造文件
  7. File srcFile = new File( "爱情与友情.jpg");
  8. File destFile = new File( "爱情与友情3.jpg");
  9. //2.造流
  10. //2.1 造节点流
  11. FileInputStream fis = new FileInputStream((srcFile));
  12. FileOutputStream fos = new FileOutputStream(destFile);
  13. //2.2 造缓冲流
  14. bis = new BufferedInputStream(fis);
  15. bos = new BufferedOutputStream(fos);
  16. //3.复制的细节:读取、写入
  17. byte[] buffer = new byte[ 10];
  18. int len;
  19. while((len = bis.read(buffer)) != - 1){
  20. bos.write(buffer, 0,len);
  21. // bos.flush();//刷新缓冲区
  22. }
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. //4.资源关闭
  27. //要求:先关闭外层的流,再关闭内层的流
  28. if(bos != null){
  29. try {
  30. bos.close();
  31. } catch (IOException e) {
  32. e.printStackTrace();
  33. }
  34. }
  35. if(bis != null){
  36. try {
  37. bis.close();
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. }
  41. }
  42. //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
  43. // fos.close();
  44. // fis.close();
  45. }

5.2:文件复制的案例


  
  1. @Test
  2. public void testBufferedReaderBufferedWriter(){
  3. BufferedReader br = null;
  4. BufferedWriter bw = null;
  5. try {
  6. //创建文件和相应的流
  7. br = new BufferedReader( new FileReader( new File( "dbcp.txt")));
  8. bw = new BufferedWriter( new FileWriter( new File( "dbcp1.txt")));
  9. //读写操作
  10. //方式一:使用char[]数组
  11. // char[] cbuf = new char[1024];
  12. // int len;
  13. // while((len = br.read(cbuf)) != -1){
  14. // bw.write(cbuf,0,len);
  15. // // bw.flush();
  16. // }
  17. //方式二:使用String
  18. String data;
  19. while((data = br.readLine()) != null){
  20. //方法一:
  21. // bw.write(data + "\n");//data中不包含换行符
  22. //方法二:
  23. bw.write(data); //data中不包含换行符
  24. bw.newLine(); //提供换行的操作
  25. }
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. } finally {
  29. //关闭资源
  30. if(bw != null){
  31. try {
  32. bw.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. if(br != null){
  38. try {
  39. br.close();
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }
BufferedReader提供了readLine()方法来读取一行行的字符

BufferWriter提供了newLine()方法提供换行的操作

5.3:缓冲流的课后习题

5.3.1:图片的加密


  
  1. //图片的加密
  2. @Test
  3. public void test1() {
  4. FileInputStream fis = null;
  5. FileOutputStream fos = null;
  6. try {
  7. fis = new FileInputStream( "爱情与友情.jpg");
  8. fos = new FileOutputStream( "爱情与友情secret.jpg");
  9. byte[] buffer = new byte[ 20];
  10. int len;
  11. while ((len = fis.read(buffer)) != - 1) {
  12. //字节数组进行修改
  13. //错误的
  14. // for(byte b : buffer){
  15. // b = (byte) (b ^ 5);
  16. // }
  17. //正确的
  18. for ( int i = 0; i < len; i++) {
  19. buffer[i] = ( byte) (buffer[i] ^ 5);
  20. }
  21. fos.write(buffer, 0, len);
  22. }
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. if (fos != null) {
  27. try {
  28. fos.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. if (fis != null) {
  34. try {
  35. fis.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }
  42. //图片的解密
  43. @Test
  44. public void test2() {
  45. FileInputStream fis = null;
  46. FileOutputStream fos = null;
  47. try {
  48. fis = new FileInputStream( "爱情与友情secret.jpg");
  49. fos = new FileOutputStream( "爱情与友情4.jpg");
  50. byte[] buffer = new byte[ 20];
  51. int len;
  52. while ((len = fis.read(buffer)) != - 1) {
  53. //字节数组进行修改
  54. //错误的
  55. // for(byte b : buffer){
  56. // b = (byte) (b ^ 5);
  57. // }
  58. //正确的
  59. for ( int i = 0; i < len; i++) {
  60. buffer[i] = ( byte) (buffer[i] ^ 5);
  61. }
  62. fos.write(buffer, 0, len);
  63. }
  64. } catch (IOException e) {
  65. e.printStackTrace();
  66. } finally {
  67. if (fos != null) {
  68. try {
  69. fos.close();
  70. } catch (IOException e) {
  71. e.printStackTrace();
  72. }
  73. }
  74. if (fis != null) {
  75. try {
  76. fis.close();
  77. } catch (IOException e) {
  78. e.printStackTrace();
  79. }
  80. }
  81. }
  82. 两次与的操作数据不变

5.3.2:获取文本上每个字符出现的次数


  
  1. public class WordCount {
  2. /*
  3. 说明:如果使用单元测试,文件相对路径为当前module
  4. 如果使用main()测试,文件相对路径为当前工程
  5. */
  6. @Test
  7. public void testWordCount() {
  8. FileReader fr = null;
  9. BufferedWriter bw = null;
  10. try {
  11. //1.创建Map集合
  12. Map<Character, Integer> map = new HashMap<Character, Integer>();
  13. //2.遍历每一个字符,每一个字符出现的次数放到map中
  14. fr = new FileReader( "dbcp.txt");
  15. int c = 0;
  16. while ((c = fr.read()) != -1) {
  17. //int 还原 char
  18. char ch = ( char) c;
  19. // 判断char是否在map中第一次出现
  20. if (map. get(ch) == null) {
  21. map.put(ch, 1);
  22. } else {
  23. map.put(ch, map. get(ch) + 1);
  24. }
  25. }
  26. //3.把map中数据存在文件count.txt
  27. //3.1 创建Writer
  28. bw = new BufferedWriter( new FileWriter( "wordcount.txt"));
  29. //3.2 遍历map,再写入数据
  30. Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
  31. for (Map.Entry<Character, Integer> entry : entrySet) {
  32. switch (entry.getKey()) {
  33. case ' ':
  34. bw.write( "空格=" + entry.getValue());
  35. break;
  36. case '\t': //\t表示tab 键字符
  37. bw.write( "tab键=" + entry.getValue());
  38. break;
  39. case '\r': //
  40. bw.write( "回车=" + entry.getValue());
  41. break;
  42. case '\n': //
  43. bw.write( "换行=" + entry.getValue());
  44. break;
  45. default:
  46. bw.write(entry.getKey() + "=" + entry.getValue());
  47. break;
  48. }
  49. bw.newLine();
  50. }
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. } finally {
  54. //4.关流
  55. if (fr != null) {
  56. try {
  57. fr.close();
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. }
  61. }
  62. if (bw != null) {
  63. try {
  64. bw.close();
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. }
  68. }
  69. }
  70. }
  71. }

六:转换流

转换流提供了在字节流和字符流之间的转换
Java API 提供了两个转换流:
 
InputStreamReader :将 InputStream 转换为 Reader
 
OutputStreamWriter :将 Writer 转换为 OutputStream
 
字节流中的数据都是字符时,转成字符流操作更高效。
 
很多时候我们使用转换流来处理文件乱码问题。实现编码和
解码的功能。
 
 
 
 
 
* 处理流之二:转换流的使用
* 1.转换流:属于字符流
*   InputStreamReader:将一个字节的输入流转换为字符的输入流
*   OutputStreamWriter:将一个字符的输出流转换为字节的输出流
*
* 2.作用:提供字节流与字符流之间的转换
*
* 3. 解码:字节、字节数组  --->字符数组、字符串
*    编码:字符数组、字符串 ---> 字节、字节数组
*
*
* 4.字符集
*ASCII:美国标准信息交换码。
   用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表
   用一个字节的8位表示。
GB2312:中国的中文编码表。最多两个字节编码所有字符
GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。

6.1:转换流的案例


  
  1. ublic class InputStreamReaderTest {
  2. /*
  3. 此时处理异常的话,仍然应该使用try-catch-finally
  4. InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
  5. */
  6. @Test
  7. public void test1() throws IOException {
  8. FileInputStream fis = new FileInputStream( "dbcp.txt");
  9. // InputStreamReader isr = new InputStreamReader(fis);//使用系统默认的字符集
  10. //参数2指明了字符集,具体使用哪个字符集,取决于文件dbcp.txt保存时使用的字符集
  11. InputStreamReader isr = new InputStreamReader(fis, "UTF-8"); //使用系统默认的字符集
  12. char[] cbuf = new char[ 20];
  13. int len;
  14. while((len = isr.read(cbuf)) != - 1){
  15. String str = new String(cbuf, 0,len);
  16. System.out.print(str);
  17. }
  18. isr.close();
  19. }
  20. /*
  21. 此时处理异常的话,仍然应该使用try-catch-finally
  22. 综合使用InputStreamReader和OutputStreamWriter
  23. */
  24. @Test
  25. public void test2() throws Exception {
  26. //1.造文件、造流
  27. File file1 = new File( "dbcp.txt");
  28. File file2 = new File( "dbcp_gbk.txt");
  29. FileInputStream fis = new FileInputStream(file1);
  30. FileOutputStream fos = new FileOutputStream(file2);
  31. InputStreamReader isr = new InputStreamReader(fis, "utf-8");
  32. OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");
  33. //2.读写过程
  34. char[] cbuf = new char[ 20];
  35. int len;
  36. while((len = isr.read(cbuf)) != - 1){
  37. osw.write(cbuf, 0,len);
  38. }
  39. //3.关闭资源
  40. isr.close();
  41. osw.close();
  42. }
 

七:标准输入、输出流

1.标准的输入、输出流
1.1
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出
1.2
System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流。

1.3练习:
从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,
直至当输入“e”或者“exit”时,退出程序。

方法一:使用Scanner实现,调用next()返回一个字符串
方法二:使用System.in实现。System.in  --->  转换流 ---> BufferedReader的readLine()

    
  1. public static void main(String[] args) {
  2. BufferedReader br = null;
  3. try {
  4. InputStreamReader isr = new InputStreamReader(System. in);
  5. br = new BufferedReader(isr);
  6. while ( true) {
  7. System. out.println( "请输入字符串:");
  8. String data = br.readLine();
  9. if ( "e".equalsIgnoreCase( data) || "exit".equalsIgnoreCase( data)) {
  10. System. out.println( "程序结束");
  11. break;
  12. }
  13. String upperCase = data.toUpperCase();
  14. System. out.println(upperCase);
  15. }
  16. } catch (IOException e) {
  17. e.printStackTrace();
  18. } finally {
  19. if (br != null) {
  20. try {
  21. br.close();
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }

7.1:小练习

Create a program named MyInput.java: Contain the methods for reading int,
double, float, boolean, short, byte and String values from the keyboard.

     
  1. import java.io.*;
  2. public class MyInput {
  3. // Read a string from the keyboard
  4. public static String readString() {
  5. BufferedReader br = new BufferedReader( new InputStreamReader(System.in));
  6. // Declare and initialize the string
  7. String string = "";
  8. // Get the string from the keyboard
  9. try {
  10. string = br.readLine();
  11. } catch (IOException ex) {
  12. System.out.println(ex);
  13. }
  14. // Return the string obtained from the keyboard
  15. return string;
  16. }
  17. // Read an int value from the keyboard
  18. public static int readInt() {
  19. return Integer.parseInt(readString());
  20. }
  21. // Read a double value from the keyboard
  22. public static double readDouble() {
  23. return Double.parseDouble(readString());
  24. }
  25. // Read a byte value from the keyboard
  26. public static double readByte() {
  27. return Byte.parseByte(readString());
  28. }
  29. // Read a short value from the keyboard
  30. public static double readShort() {
  31. return Short.parseShort(readString());
  32. }
  33. // Read a long value from the keyboard
  34. public static double readLong() {
  35. return Long.parseLong(readString());
  36. }
  37. // Read a float value from the keyboard
  38. public static double readFloat() {
  39. return Float.parseFloat(readString());
  40. }
  41. }
 

八:打印流以及数据流8及

一打8

打印流: PrintStream PrintWriter
提供了一系列重载的 print() println() 方法,用于多种数据类型的输出
PrintStream PrintWriter 的输出不会抛出 IOException 异常
  PrintStream PrintWriter 有自动 flush 功能
  PrintStream 打印的所有字符都使用平台的默认字符编码转换为字节。
在需要写入字符而不是写入字节的情况下,应该使用 PrintWriter 类。
System.out 返回的是 PrintStream 的实例
 

   
  1. PrintStream ps = null;
  2. try {
  3. FileOutputStream fos = new FileOutputStream( new File( "a.txt"));
  4. // 创建打印输出流,设置为自动刷新模式(写入换行符或字节 '\n' 时都会刷新输出缓冲区)
  5. ps = new PrintStream(fos, true);
  6. if (ps != null) { // 把标准输出流(控制台输出)改成文件
  7. System.setOut(ps);
  8. }
  9. for ( int i = 0; i <= 255; i++) { // 输出ASCII字符
  10. System. out.print( i); //输出在a.txt的文件上
  11. if (i % 50 == 0) { // 每50个数据一行
  12. System. out.println(); // 换行
  13. }
  14. }
  15. } catch (FileNotFoundException e) {
  16. e.printStackTrace();
  17. } finally {
  18. if (ps != null) {
  19. ps.close();
  20. }
  21. }

数据流


    
  1. 3. 数据流
  2. 3.1 DataInputStream 和 DataOutputStream
  3. 3.2 作用:用于读取或写出基本数据类型的变量或字符串
  4. 练习:将内存中的字符串、基本数据类型的变量写出到文件中。
  5. 注意:处理异常的话,仍然应该使用 try- catch- finally.
  6. */
  7. @Test
  8. public void test3() throws IOException {
  9. //1.
  10. DataOutputStream dos = new DataOutputStream( new FileOutputStream( "data.txt"));
  11. //2.
  12. dos.writeUTF( "刘建辰");
  13. dos.flush(); //刷新操作,将内存中的数据写入文件
  14. dos.writeInt( 23);
  15. dos.flush();
  16. dos.writeBoolean( true);
  17. dos.flush();
  18. //3.
  19. dos.close();
  20. }
  21. /*
  22. 将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
  23. 注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
  24. */
  25. @Test
  26. public void test4() throws IOException {
  27. //1.
  28. DataInputStream dis = new DataInputStream( new FileInputStream( "data.txt"));
  29. //2.
  30. String name = dis.readUTF();
  31. int age = dis.readInt();
  32. boolean isMale = dis.readBoolean();
  33. System.out.println( "name = " + name);
  34. System.out.println( "age = " + age);
  35. System.out.println( "isMale = " + isMale);
  36. //3.
  37. dis.close();
  38. }

 

九:对象流

 

 

 

 
印流流
 
凡是实现 Serializable 接口的类都有一个表示序列化版本标识符的静态变量:
private static final long serialVersionUID;
serialVersionUID 用来表明类的不同版本间的兼容性。 简言之,其目的是以序列化对象
进行版本控制,有关各版本反序列化时是否兼容。
如果类没有显示定义这个静态常量,它的值是 Java 运行时环境根据类的内部细节自
动生成的。 若类的实例变量做了修改, serialVersionUID 可能发生变化。 故建议,
显式声明。
简单来说, Java 的序列化机制是通过在运行时判断类的 serialVersionUID 来验
证版本一致性的。在进行反序列化时, JVM 会把传来的字节流中的
serialVersionUID 与本地相应实体类的 serialVersionUID 进行比较,如果相同
就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异
常。 (InvalidCastException)
 
 

9.1:案例


  
  1. * 对象流的使用
  2. * 1.ObjectInputStream 和 ObjectOutputStream
  3. * 2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
  4. *
  5. * 3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java
  6. *
  7. * 4.序列化机制:
  8. * 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种
  9. * 二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。
  10. * 当其它程序获取了这种二进制流,就可以恢复成原来的Java对象。
  11. *
  12. * @author shkstart
  13. * @create 2019 上午 10: 27
  14. */
  15. public class ObjectInputOutputStreamTest {
  16. /*
  17. 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
  18. 使用ObjectOutputStream实现
  19. */
  20. @Test
  21. public void testObjectOutputStream() throws IOException {
  22. ObjectOutputStream oos= null;
  23. try {
  24. oos = new ObjectOutputStream( new FileOutputStream( "object.dat"));
  25. //2.
  26. oos.writeObject( new String( "我爱北京天安门"));
  27. oos.flush(); //刷新操作
  28. oos.writeObject( new Person( "王铭", 23));
  29. oos.flush();
  30. oos.writeObject( new Person( "张学良", 23, 1001, new Account( 5000)));
  31. oos.flush();
  32. System.out.println( "传输完成");
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. } finally {
  36. if(oos != null){
  37. //3.
  38. try {
  39. oos.close();
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. }
  44. }
  45. }
  46. }
  47. /*
  48. 反序列化:将磁盘文件中的对象还原为内存中的一个java对象
  49. 使用ObjectInputStream来实现
  50. */
  51. @Test
  52. public void testObjectInputStream () throws IOException, ClassNotFoundException {
  53. ObjectInputStream ois = null;
  54. try {
  55. ois = new ObjectInputStream( new FileInputStream( "object.dat"));
  56. Object obj = ois.readObject();
  57. String str = (String) obj;
  58. Person p = (Person) ois.readObject();
  59. Person p1 = (Person) ois.readObject();
  60. System.out.println(str);
  61. System.out.println(p);
  62. System.out.println(p1);
  63. } catch (IOException e) {
  64. e.printStackTrace();
  65. } catch (ClassNotFoundException e) {
  66. e.printStackTrace();
  67. } finally {
  68. if (ois != null) {
  69. try {
  70. ois.close();
  71. } catch (IOException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. }
序列化和反序列化里面的内容一一对应,

十:随机存取文件流

* RandomAccessFile的使用
* 1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
* 2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
*
* 3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
*   如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
*
* 4. 可以通过相关的操作,实现RandomAccessFile“插入”数据的效果

   
  1. @Test
  2. public void test1() {
  3. RandomAccessFile raf1 = null;
  4. RandomAccessFile raf2 = null;
  5. try {
  6. //1.
  7. raf1 = new RandomAccessFile( new File( "爱情与友情.jpg"), "r");
  8. raf2 = new RandomAccessFile( new File( "爱情与友情1.jpg"), "rw");
  9. //2.
  10. byte[] buffer = new byte[ 1024];
  11. int len;
  12. while((len = raf1.read(buffer)) != - 1){
  13. raf2.write(buffer, 0,len);
  14. }
  15. } catch (IOException e) {
  16. e.printStackTrace();
  17. } finally {
  18. //3.
  19. if(raf1 != null){
  20. try {
  21. raf1.close();
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. if(raf2 != null){
  27. try {
  28. raf2.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. }
  34. }
  35. @Test
  36. public void test2() throws IOException {
  37. RandomAccessFile raf1 = new RandomAccessFile( "hello.txt", "rw"); //abcxxxdef
  38. raf1.seek( 3); //将指针调到角标为3的位置
  39. raf1.write( "xyz".getBytes()); //abcxyzdef //从指定的位置开始覆盖,默认从头部开始
  40. raf1.close();
  41. }

10.1  案例   

将hello.txt里面的内容:"abcdef",插入"xyz",变成abcxyzdef


   
  1. public void test3() throws IOException {
  2. RandomAccessFile raf1 = new RandomAccessFile( "hello.txt", "rw");
  3. raf1.seek( 3); //将指针调到角标为3的位置
  4. //保存指针3后面的所有数据到StringBuilder中
  5. StringBuilder builder = new StringBuilder(( int) new File( "hello.txt").length());
  6. byte[] buffer = new byte[ 20];
  7. int len;
  8. while(( len = raf1.read(buffer)) != -1){
  9. builder. append( new String(buffer, 0, len)) ;
  10. }
  11. //调回指针,写入“xyz”
  12. raf1.seek( 3);
  13. raf1.write( "xyz".getBytes());
  14. //将StringBuilder中的数据写入到文件中
  15. raf1.write(builder.toString().getBytes());
  16. raf1. close();

 

十一:Java NIO

10.1:常用方法

 


转载:https://blog.csdn.net/weixin_46443325/article/details/115475880
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场