Java学习-07 IO学习

I : 即input,代表读取。O:即output,代表输出。

1、File

主要字段:

示例:

System.out.println(File.pathSeparator);
System.out.println(File.pathSeparatorChar);
System.out.println(File.separator);
System.out.println(File.separatorChar);;

输出:

;
;
\
\

构造方法:

常用方法:
createNewFile, delete, exists(),getAbsolutePath(),getName(),getParent(),getPath(),isAbsolute(),isDirectory(),isFile(),length(),listFiles(),listFiles(FileFilter filter),listFiles(FilenameFilter filter),mkdir(),renameTo(File dest)
使用FileFilter 和匿名内部类案例:

File[] files2 = f.listFiles(new FileFilter() {@Overridepublic boolean accept(File pathname) {return pathname.getName().endsWith(".jpg");}
});if (files2 != null && files2.length > 0){for (File file :files2) {System.out.println("找到了一个jpg文件:" + file.getAbsolutePath());}
}

2、IO流

IO流概述:
可以将这种数据传输操作,看做一种数据的流动 , 按照流动的方向分为输入Input和输出Output

Java中的IO操作主要指的是 java.io包下的一些常用类的使用. 通过这些常用类对数据进行读取(输入Input) 和 写出(输出Output)

IO流的分类:

  • 按照流的方向来分,可以分为:输入流和输出流.
  • 按照流动的数据类型来分,可以分为:字节流和字符流

字节流:

  • 输入流 : InputStrea
  • 输出流 : OutputStream

字符流:

  • 输入流 : Reader
  • 输出流 : Writer

一切皆字节:
计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的.
在数据传输时 也都是以二进制的形式存储的.
后续学习的任何流 , 在传输时底层都是二进制.

2.1、FileOutputStream

OutputStream本身是输出流的抽象基类,所以使用它的实现类。
FileOutputStream的三种write方法:

一定要注意使用close方法释放资源。
案例练习:

package java03.com.app.core.section4;import java.io.FileOutputStream;
import java.io.IOException;public class OutputStreamDemo {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream(".\\a.txt");fos.write(65);fos.write(66);fos.write(67);byte[] bytes = {65,66,67};fos.write(bytes);byte[] bytes1 = "abc".getBytes();fos.write(bytes1);fos.write(bytes1, 1, 2);System.out.println("end");fos.close();}
}/*
输出结果:
ABCABCabcbc
*/

需要注意的是,第二次打开这个文档的时候,如果还是同样的命令,那么会先清空文档中的内容,再写入,如果不想清空,想在原来的内容后边追加,可以:
把new FileOutputStream(".\a.txt")写为:new FileOutputStream(".\a.txt",true);第二个参数就是表示是否追加。
注意,不能读取字符串,会导致乱码,因为对于UTF-8编码集,字符有的占两个字节,有的占三个字节。

2.2、FileInputStream

InputStream本身是输出流的抽象基类,所以使用它的实现类。
FileInputStream的三种read方法:

机翻存在一定问题,这里解释一下:

  • 第一种不传参数的是读取单个字节数据,然后返回读取的字节数据。
  • 第二种会读取最多b.length个字节,返回实际读取的字节数,注意是实际,比如你的b数组的长度为10,但是最后读取的字节不够10个,比如-还剩5个,那么会返回5,而不是10!
  • 第三种从输入流最多读取len个字节的数据,并放入字节数组b中,是从第二个参数off的位置开始读取, 同样返回的是实际读取的长度。

案例演示:
第一种读取方式:

package java03.com.app.core.section4;import java.io.FileInputStream;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 10:37* @Modified By:*/
public class InputStreamDemo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream(".\\a.txt");// a.txt : ABCABCabcbcchar r1 = (char) fis.read();int r2 = fis.read();byte r3 = (byte) fis.read();System.out.println(r1);System.out.println(r2);System.out.println(r3);}
}/*
输出:
A
66
67
*/

第二种读取方式:

package java03.com.app.core.section4;import java.io.FileInputStream;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 10:37* @Modified By:*/
public class InputStreamDemo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream(".\\a.txt");// a.txt : ABCABCabcbcbyte[] bytes = new byte[5];int len = fis.read(bytes);System.out.println("读取到的长度为:" + len + ", 字符为:" + new String(bytes,0,len));len = fis.read(bytes);System.out.println("读取到的长度为:" + len + ", 字符为:" + new String(bytes,0,len));len = fis.read(bytes);System.out.println("读取到的长度为:" + len + ", 字符为:" + new String(bytes,0,len));fis.close();}
}/*
读取到的长度为:5, 字符为:ABCAB
读取到的长度为:5, 字符为:Cabcb
读取到的长度为:1, 字符为:c
*/

第三种读取方式:

package java03.com.app.core.section4;import java.io.FileInputStream;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 10:37* @Modified By:*/
public class InputStreamDemo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream(".\\a.txt");// a.txt : ABCABCabcbcbyte[] bytes = new byte[5];int length = bytes.length;// 为了便于观察,把这里的bytes数组元素全部变为 *for (int i = 0; i < length; i++) {bytes[i] = '*';}System.out.println("读取前bytes中字符为:" + new String(bytes,0,length));int len = fis.read(bytes, 1, 3);System.out.println("读取到的长度为:" + len + ", bytes中字符为:" + new String(bytes,0,length));len = fis.read(bytes, 1, 3);System.out.println("读取到的长度为:" + len + ", bytes中字符为:" + new String(bytes,0,length));len = fis.read(bytes, 1, 3);System.out.println("读取到的长度为:" + len + ", bytes中字符为:" + new String(bytes,0,length));fis.close();}
}/*
读取前bytes中字符为:*****
读取到的长度为:3, bytes中字符为:*ABC*
读取到的长度为:3, bytes中字符为:*ABC*
读取到的长度为:3, bytes中字符为:*abc*
*/

可以看到,第三种方式读取的时候,读取的长度不再是bytes.length,而是第三个参数len,并且在存放的时候,会从第二个参数 off的位置开始往bytes数组中存放。
注意不能写字符串。

2.3、Writer

以下为它提供的write方法,可以看到,除了可以写字节,还可以直接写字符串。

用法和前面的字节流用法一样,所以就简单的举个栗子,然后主要说一说其他的方法。

abstract void flush() 刷新流。

先说说这个flush,这对应一个缓冲区,为什么要缓冲呢?因为计算机底层是二进制,传递的时候是一个字节一个字节的,但是对于UTF-8中的很多字符,它们都是占好几个字节,所以需要缓冲区先把它们拼起来,然后再放进去,这样就能避免乱码问题,所以你写入的东西,都是先保存在缓冲区的,直到调用flush方法,强制刷新缓冲区,才能把东西放进文档,close会自动调用。
比如如下代码:

package java03.com.app.core.section4;import java.io.FileWriter;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 11:21* @Modified By:*/
public class WriterDemo {public static void main(String[] args) throws IOException {FileWriter writer = new FileWriter("src/java03/com/app/core/section4/test.txt");writer.write("艳阳天那个风光好,");writer.write("红的花是绿的草,");writer.write("我乐乐呵呵向前跑,");writer.write("踏遍青山人未老。");// writer.close();}
}/*
会发现test.txt中什么也没有
*/

如果调用flush方法:

package java03.com.app.core.section4;import java.io.FileWriter;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 11:21* @Modified By:*/
public class WriterDemo {public static void main(String[] args) throws IOException {FileWriter writer = new FileWriter("src/java03/com/app/core/section4/test.txt");writer.write("艳阳天那个风光好,");writer.write("红的花是绿的草,");writer.write("我乐乐呵呵向前跑,");writer.write("踏遍青山人未老。");writer.flush();// writer.close();}
}/*
会看到test.txt中:
艳阳天那个风光好,红的花是绿的草,我乐乐呵呵向前跑,踏遍青山人未老。
*/

然后需要说说这个append方法,很有意思。

先上代码:

package java03.com.app.core.section4;import java.io.FileWriter;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 11:21* @Modified By:*/
public class WriterDemo {public static void main(String[] args) throws IOException {FileWriter writer = new FileWriter("src/java03/com/app/core/section4/test.txt");writer.append("艳阳天那个风光好,").append("红的花是绿的草.");writer.close();}
}/*
test.txt中:
艳阳天那个风光好,红的花是绿的草.
*/

可以看到,这次不用每次writer了,直接在后边.append就可以放入大量文字,因为它返回的是writer对象。
需要注意的是,这个append也只是在本次打开有效,下次再打开这个文件,用append写入的时候,可不是在原文件内容后边追加,是先清空源文件内容,再写入,控制在原内容后边追加的还是创建Writer时的第二个参数true,同上边的字节流。
那么append的第三种是什么意思呢?

package java03.com.app.core.section4;import java.io.FileWriter;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 11:21* @Modified By:*/
public class WriterDemo {public static void main(String[] args) throws IOException {FileWriter writer = new FileWriter("src/java03/com/app/core/section4/test.txt");writer.append("艳阳天那个风光好,").append("红的花是绿的草.").append("踏遍青山人未老。", 2,4);writer.close();}
}/*
test.txt中:
艳阳天那个风光好,红的花是绿的草.青山
*/

原来是把字符串按照start和end进行切片后,把切片得到的子字符串追加,注意是左闭右开的,即不包含右边索引对应的字符。

2.4 Reader

先说基本的Reader方法:三种read

可以看到,这三种和字节流的基本一样,只是把byte[] 换成了char[] ,所以用法都是一样的。
演示代码:

package java03.com.app.core.section4;import java.io.FileReader;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 12:05* @Modified By:*/
public class ReaderDemo {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("src/java03/com/app/core/section4/test.txt");// test.txt 内容:艳阳天那个风光好,红的花是绿的草,我乐乐呵呵向前跑,踏遍青山人未老。char[] chars = new char[9];int read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));fr.close();}
}/*
读取到9个字符,分别是:艳阳天那个风光好,
读取到9个字符,分别是:红的花是绿的草,我
读取到9个字符,分别是:乐乐呵呵向前跑,踏
读取到7个字符,分别是:遍青山人未老。,踏
*/

可以看到最后的输出怎么多了个,踏,这是啥?还记得缓冲区吗?这就是因为读取到的字符,是先保存在缓冲区的,而最后一次读取,要读取9个字符,但是只剩下7个字符了,那怎么办?从缓冲区哪里拿两个过来补上。见图:

第四次取的时候,只取到了7个字符,所以去上一行读取的拿了两个过来补上,对应黄色框框。

2.5、关于读入时的结束判断

不论是字节读取还是字符读取,读取到最后都会会返回-1, 所以可以根据这个判断是否读取到了最后。
还是拿上一节的代码,再读取一次,会看到最后输出变成了“读取到-1个字符,分别是:遍青山人未老。,踏”,返回了-1,表明没有读取到新的字符,所以没有修改chars数组,因此最后的输出文字和上一行的一样。

package java03.com.app.core.section4;import java.io.FileReader;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 12:05* @Modified By:*/
public class ReaderDemo {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("src/java03/com/app/core/section4/test.txt");// test.txt 内容:艳阳天那个风光好,红的花是绿的草,我乐乐呵呵向前跑,踏遍青山人未老。char[] chars = new char[9];int read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));read = fr.read(chars);System.out.println("读取到" + read + "个字符," + "分别是:" + new String(chars, 0, chars.length));fr.close();}
}/*
读取到9个字符,分别是:艳阳天那个风光好,
读取到9个字符,分别是:红的花是绿的草,我
读取到9个字符,分别是:乐乐呵呵向前跑,踏
读取到7个字符,分别是:遍青山人未老。,踏
读取到-1个字符,分别是:遍青山人未老。,踏
*/

2.6、转换流

转换流 将字节流转换成字符流,使用了装饰者模式,也可以成为装饰器设计模式。
包括两个:InputStreamReader 和OutputStreamWriter,见名知意,就是把字节流变成字符流。

可以传递输入流和字符集。
练习代码:

package java03.com.app.core.section4;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 13:30* @Modified By:*/
public class InputStreamReaderDemo {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("F:\\IdeaProjects\\JavaEE_Learning\\src\\java03\\com\\app\\core\\section4\\test.txt");// test.txt 内容:艳阳天那个风光好,红的花是绿的草,我乐乐呵呵向前跑,踏遍青山人未老。// 将字节输入流转换为字符输入流  参数为要转换的字节流和编码集InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);// 查看一下所使用的编码System.out.println(isr.getEncoding());while (true){int read = fis.read();int c = isr.read();if(c==-1){break;}System.out.println("转换之前返回的字节数据是:" + read + ",转换为字符是:" + (char) read);System.out.println("转换之后返回的字节数据是:" + c + ",转换为字符是:" + (char)c);System.out.println("------------------------------------------------------------------");}fis.close();}
}/*
UTF8
转换之前返回的字节数据是:232,转换为字符是:è
转换之后返回的字节数据是:65533,转换为字符是:�
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:65533,转换为字符是:�
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:38451,转换为字符是:阳
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:22825,转换为字符是:天
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:37027,转换为字符是:那
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:20010,转换为字符是:个
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:39118,转换为字符是:风
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:20809,转换为字符是:光
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:22909,转换为字符是:好
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:65292,转换为字符是:,
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:32418,转换为字符是:红
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:30340,转换为字符是:的
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:33457,转换为字符是:花
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:26159,转换为字符是:是
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:32511,转换为字符是:绿
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:30340,转换为字符是:的
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:33609,转换为字符是:草
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:65292,转换为字符是:,
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:25105,转换为字符是:我
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:20048,转换为字符是:乐
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:20048,转换为字符是:乐
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:21621,转换为字符是:呵
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:21621,转换为字符是:呵
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:21521,转换为字符是:向
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:21069,转换为字符是:前
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:36305,转换为字符是:跑
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:65292,转换为字符是:,
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:36367,转换为字符是:踏
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:36941,转换为字符是:遍
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:38738,转换为字符是:青
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:23665,转换为字符是:山
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:20154,转换为字符是:人
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:26410,转换为字符是:未
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:32769,转换为字符是:老
------------------------------------------------------------------
转换之前返回的字节数据是:-1,转换为字符是:
转换之后返回的字节数据是:12290,转换为字符是:。
------------------------------------------------------------------
*/

这个输出这里,有一点问题,前边两个不知道为什么显示错误,但是能看到这个转换前和转换后的对比,后边能正确输出,可能是IDEA的问题。

OutputStreamWriter:

package java03.com.app.core.section4;import java.io.*;
import java.nio.charset.StandardCharsets;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 14:01* @Modified By:*/
public class OutputStreamWriterDemo {public static void main(String[] args) throws IOException {FileOutputStream fos = new FileOutputStream("F:\\IdeaProjects\\JavaEE_Learning\\src\\java03\\com\\app\\core\\section4\\test.txt");fos.write('帅');// 将字节输入流转换为字符输入流  参数为要转换的字节流和编码集OutputStreamWriter osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8);// 查看所使用的编码集System.out.println(osw.getEncoding());osw.write("帅");osw.close();}
}

输出:

2.7、PrintStream和PrintWriter

它们都属于打印流,顾名思义,就是为了输出文本的。它属于处理流,使用处理流的方法:用处理流来包装节点流,程序通过处理流来执行输入输出功能,而节点流与底层的I/O设备、文件交互。
简单代码演示:

package java03.com.app.core.section4;import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.PrintWriter;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 14:00* @Modified By:*/
public class PrintStreamDemo {public static void main(String[] args) throws FileNotFoundException {PrintStream ps = new PrintStream("F:\\IdeaProjects\\JavaEE_Learning\\src\\java03\\com\\app\\core\\section4\\test.txt");ps.println("面朝大海");ps.println("春暖花开");/*test.txt:面朝大海春暖花开*/PrintWriter pw = new PrintWriter("F:\\IdeaProjects\\JavaEE_Learning\\src\\java03\\com\\app\\core\\section4\\test.txt");pw.println("王大卖瓜");pw.println("老鼠的儿子会打洞");ps.flush();ps.close();pw.flush();pw.close();/*test.txt:王大卖瓜老鼠的儿子会打洞*/}
}/*最终test.txt:王大卖瓜老鼠的儿子会打洞*/

我们一直使用的System.out就是PrintStream类

2.8、BufferedReader

缓冲流,BufferedReader流具有缓冲功能,他可以一次读取一行文本,以换行符为标志,如果没有读到换行符,那么程序会堵塞,等到读到换行符为止。
因为它具有一个readLine方法,可以方便的一次读取一行内容,所以经常把读取文本内容的输入流包装为BufferedReader,用来方便的读取输入流的文本内容。
案例演示:

package java03.com.app.core.section4;import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 17:07* @Modified By:*/
public class BufferedReaderDemo {public static void main(String[] args) throws IOException {FileReader fr = new FileReader("F:\\IdeaProjects\\JavaEE_Learning\\src\\java03\\com\\app\\core\\section4\\test.txt");/*test.txt内容:王大卖瓜老鼠的儿子会打洞*/BufferedReader br = new BufferedReader(fr);String s = br.readLine();System.out.println(s);}
}/*
王大卖瓜
*/

2.9、利用IO流进行异常日志收集

程序在运行时总会出现异常,我们不可能一直盯着控制台去看,那么就需要收集这些异常信息。简单练习如下:

package java03.com.app.core.section4;import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 17:14* @Modified By:*/
public class ExceptionDemo {public static void main(String[] args) throws FileNotFoundException {//收集异常信息try {String s = null;s.toString();}catch (Exception e){PrintWriter pw = new PrintWriter(".\\bug.txt");SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");pw.println(format.format(new Date()));e.printStackTrace(pw);pw.close();}}
}/*
可以看到bug.txt中多了几行文字:
2020-08-07 17:19
java.lang.NullPointerExceptionat java03.com.app.core.section4.ExceptionDemo.main(ExceptionDemo.java:19)*/

这个就是简单的演示一下,了解就行,因为有好多封装很好地异常日志类可以使用。

3、简单的加密解密

因为计算机底层保存的都是二进制,所以可以简单地进行加密解密操作,即通过异或,异或的规则为:pqq = p
那么,第一次异或即为加密,第二次即为解密。

package java03.com.app.core.section4;import java.io.*;
import java.util.Scanner;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 18:40* @Modified By:*/
public class EncryptionDemo {public static void main(String[] args) throws IOException {Scanner input = new Scanner(System.in);System.out.println("请输入文件的绝对路径:");String fileName = input.nextLine();// 为了得到上一级路径,需要用File读入File oldFile = new File(fileName);// 对于加密的文件,加上前缀mi-,区分File newFile = new File(oldFile.getParent(), "mi-" + oldFile.getName());// 为了进行读取写出,需要流FileInputStream fis = new FileInputStream(oldFile);FileOutputStream fos = new FileOutputStream(newFile);// 循环读入进行加密,加密解密原理为 进行^操作。p^4^4 = p, 任何一个数连续异或同一个数两次得到的结果还是它System.out.println("正在进行操作,这可能需要一段时间");while (true){// 每次读取一个字节int b = fis.read();// 如果返回 -1 表明读取完毕if (b == -1) break;fos.write(b^4);}System.out.println("加密/解密完成");}
}/* 第一次我们输入要加密的文件路径
请输入文件的绝对路径:
C:\Users\zlz1314\Desktop\close.png
正在进行操作,这可能需要一段时间
加密/解密完成
*//*第二次我们输入加密了的文件的路径进行解密
请输入文件的绝对路径:
C:\Users\zlz1314\Desktop\mi-close.png
正在进行操作,这可能需要一段时间
加密/解密完成
*/

4、Properties

properties文件与properties类,配置文件格式,它是Map类,所以存的是键值对。
put放入键值对,store保存到本地文件,因为需要I/O操作,所以需要创建I/O流。
简单实例:

package java03.com.app.core.section4;import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 17:26* @Modified By:*/
public class PropertiesDemo {public static void main(String[] args) throws IOException {Properties properties = new Properties();// 存放键值对properties.put("1", "雕虫小技");properties.put("2", "竟敢班门弄斧!");// 保存为文件, 需要输出流FileWriter fw = new FileWriter(".\\a.txt");properties.store(fw, "最强法海");// 不要忘记关闭流fw.close();}
}/* 第一行乱码,使用Unicode解析可以看到就是最强法海四个字
#\u6700\u5F3A\u6CD5\u6D77
#Fri Aug 07 17:32:12 CST 2020
1=雕虫小技
2=竟敢班门弄斧\!
*/

保存完了,怎么读取呢?load方法。

package java03.com.app.core.section4;import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Properties;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 17:26* @Modified By:*/
public class PropertiesDemo {public static void main(String[] args) throws IOException {Properties properties = new Properties();FileReader fr = new FileReader(".\\a.txt");properties.load(fr);System.out.println(properties.getProperty("1"));System.out.println(properties.get("2"));}
}/*
雕虫小技
竟敢班门弄斧!
*/

可以看到,这个get和getProperty都是可以的。

5、序列化和反序列化

目前我们能在文件中存取文本了,那能不能存取类呢?所以出现了序列化与反序列化技术,可以把类放进去!这个简直太牛了,所以一经提出,就被广泛使用,但是听老师说,近两年java官方给出的一份报告显示这个技术会引起大量的bug,java官方将推出新技术取代这个技术,所以能不用就不用,万一过两年没了呢。
要实现序列化,必须实现Serializable接口。然后使用的是ObjectInputStream和ObjectOutputStream,通过readObject和writeObject进行读写。
练习代码:

package java03.com.app.core.section4;import java.io.*;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 17:40* @Modified By:*/
public class SerializableDemo {public static void main(String[] args) throws IOException, ClassNotFoundException {//序列化与反序列化/*Book b = new Book("金苹果","讲述了种植过程");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(".//b.txtx"));oos.writeObject(b);oos.close();*/ObjectInputStream ois = new ObjectInputStream(new FileInputStream(".//b.txtx"));Object o = ois.readObject();System.out.println(o);Book b = (Book)o;System.out.println(b.getName());System.out.println(b.getInfo());ois.close();}static class Book implements Serializable {private String name;private String info;public Book(String name, String info) {this.name = name;this.info = info;}public Book() {}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}@Overridepublic String toString() {return "Book{" +"name='" + name + '\'' +", info='" + info + '\'' +'}';}}
}/*
Book{name='金苹果', info='讲述了种植过程'}
金苹果
讲述了种植过程
*/

序列化与反序列化下面被注释的是序列化的代码,因为没有什么输出,文档也是打不开的,所以就不做演示了,可以看到反序列化之后可以正确的输入这个类,而且可以进行类型强转,从而可以访问类的方法。
需要注意的是,如果,这个类的属性中还有其他的类,那么这个类也必须实现Serializable接口。

6、try-catch对于I/O流的支持

try-catch现在支持自动关闭I/O流,在之前的老版本还需要写在finall中,但是有很多不方便,比如,I/O流需要写在try里面才能捕捉,那我之后的代码还要用,怎么办,我有多个流怎么办,等等问题,所以后来推出了1.9版本中的写法,可以写在try外面,然后把引用给try的(),有多个可以用;分开。
注意的是,所有可以被try-catch自动关闭的,必须实现Closeable接口。
案例演示:

package java03.com.app.core.section4;import java.io.*;/*** @Author: deemoHui* @Description:* @Date Created in 2020-08-07 18:00* @Modified By:*/
public class TryCatchIODemo {public static void main(String[] args) throws IOException {//try-with-resources/*try {FileReader fr = new FileReader(".//a.txt");int c = fr.read();System.out.println((char)c);fr.close();} catch (IOException e) {e.printStackTrace();}*///jdk9FileReader fr = new FileReader(".//a.txt");// a.txt : 哈哈啊哈PrintWriter pw = new PrintWriter(".//bug.txt");try(fr;pw){int c = fr.read();System.out.println((char)c);pw.println((char)c);}catch (IOException e) {e.printStackTrace();}CloseDemo c = new CloseDemo();try(c){}catch (Exception e){}}static class CloseDemo implements Closeable{@Overridepublic void close() throws IOException {System.out.println("close方法执行。");}}
}/*
可以看到bug.txt中多了哈哈啊哈
close方法执行。
*/

Java学习-07 IO学习相关推荐

  1. sklearn学习07——集成学习

    sklearn学习07--集成学习 前言 一.集成学习 1.1.什么是集成学习? 1.2.Boosting 算法 二.AdaBoost算法及实现 2.1.AdaBoost算法 2.2.调sklearn ...

  2. Java中的IO学习总结

    今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬盘.内存.键盘等处理 ...

  3. Java学习笔记(7)——Java基础之IO多线程网络思维导图

    Java面向对象学习笔记之:包括IO(字节流,字符流,节点流,处理流).线程(线程创建,线程控制,线程同步).网络(TCP Scoket,  UDP Scoket)(全屏观看Java学习笔记(7)-- ...

  4. Java IO学习笔记总结

    Java IO学习笔记总结 前言 前面的八篇文章详细的讲述了Java IO的操作方法,文章列表如下 基本的文件操作 字符流和字节流的操作 InputStreamReader和OutputStreamW ...

  5. java IO学习心得

    File类: 在整个io包中,唯一表示与文件有关的类就是File类.使用File类可以进行创建或者删除文件等常用的操作.要想使用File类,则首先要观察File类的构造方法,此类的常用构造方法如下: ...

  6. Java学习07–前端基础之CSS

    Java学习07–CSS基础 1.CSS介绍 1.1.发展史 css1.0 基本 css2.0 div(块)+css html与css结构分离的思想网页变简单 css2.1 浮动,定位 css3.0 ...

  7. Java学习07:Java面向对象

    Java学习07: Java面向对象: 链接:https://pan.baidu.com/s/1gzlBk5OOVI6oEv-WOkHuhQ  提取码:iqov

  8. 深入学习java非阻塞IO

    深入学习java非阻塞IO 三大组件: 1. Channel:数据通道双向通道 (1)常见的channel: FileChannel:文件传输通道 DatagramChannel:UDP传输通道 So ...

  9. JAVA SE学习day_05: IO与流操作

    一.IO与流 以程序为主体,input(输入)是读.获取.使用输入流的过程,output(输出)是写.发送的过程. JAVA IO 标准的输入与输出 JAVA IO将读和写按照方向划分为: 输入:用于 ...

最新文章

  1. SAP PM技术对象
  2. 在网页中插入百度地图的那些事
  3. js isinteger_在JavaScript中使用示例使用Number isInteger()方法
  4. html css jq 弹幕,Jquery.barrager.js
  5. 由方位角和长度如何确定坐标 已知第一个点的坐标
  6. 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_14-异常处理-异常处理的问题分析...
  7. 史上最详细的hadoop安装教程(含坑点)
  8. sql注入工具、检测及手工注入集合
  9. Python 小节案例-计算体脂率
  10. c语言中平方根怎么用算法表示,C语言中平方根实现的详细分析
  11. Java调用百度翻译openapi实现简单翻译功能
  12. 淘宝评论API接口,item_review-获得淘宝商品评论API接口接入说明
  13. Mac用自带软件QuickTime Player进行录屏
  14. Linux下二维码生成工具:QRencode
  15. MATLAB拟合函数使用说明
  16. 突发!蚂蚁集团CEO宣布辞职,阿里方面表示属实!
  17. JSP入门教程(一)
  18. 用OpenVINO工具包轻松实现PaddleOCR实时推理
  19. 企业托管主机的时候需要考虑哪些影响因素?
  20. 丢失msvcp100.dll

热门文章

  1. 通过 WebRTC 共享屏幕很容易
  2. MTCNN中celebA数据集的处理(一个置信度,两个坐标点)
  3. 安装ubuntu16.04 14.04 登录时一直显示紫色问题
  4. 元组的拆包和具名元组
  5. 报错Warning: ReactDOM.render is no longer supported in React 18.Use createRoot instead.Until you...
  6. GoogleHacking 语法篇
  7. 【疫情分析--数据采集】
  8. 关于void (visit)(const ElemType )的理解
  9. 使用 UDP 进行消息(信令)数据传输的设计
  10. 《满庭芳·国色》色号记录