Java I/O流入门笔记
一、I/O流体系
1. 字节流
InputStream
OnputStream
1)简单使用FileOutputStream
import java.io.FileOutputStream;
import java.io.IOException;public class ByteStreamTest {public static void main(String[] args) throws IOException {/*1.创建字节流输出对象构造函数入参可以是字符串表示文件路径,或File对象如果文件不存在会新建一个文件,但前提是父路径存在如果文件已存在,则会清空内容2.写数据write方法入参是int类型,实际上写入的内容是这个整数在ASCII码表上对应的字符3.释放资源每次使用完流都需要释放资源,否则就会一直占用
*/FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\a.txt");fos.write(97);fos.close();}
}
2 )三种写入数据的方式
// 1.一次写一个字节的数据fos.write(97);
// 2.一次写一个字节数组的数据byte[] bt = new byte[]{98,99,100};fos.write(bt);
// 3.一次写一个字节数组的部分数据 参数:字节数组,起始位置的下标,需要写入的长度fos.write(bt,1,2);
3 )换行和续写
/*换行写:写入一个换行符Windows: \r\nLinux: \nMac: \r在Windows中Java对回车进行了优化虽然完整的是\r\n 但是我们写其中一个\r或者\nJava也可以实现换行,底层会自动补全续写: 构造函数的第二个参数默认是false,不续写清空文件内容可以手动传入true
*/FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\a.txt",true);String s1 = "wodetianwozenmenameshuai";byte[] bytes1 = s1.getBytes();fos.write(bytes1);String s2 = "\r\n";fos.write(s2.getBytes());String s3 = "666";fos.write(s3.getBytes());fos.close();
4)简单使用FileIutputStream
import java.io.FileInputStream;
import java.io.IOException;
public class ByteStreamTest {public static void main(String[] args) throws IOException {/** 如果文件不存在,直接报错* 一次read读取一个字节,读出来的数据就是在ASCII上对应的数字* 读到文件末尾,read方法返回-1* */FileInputStream fis = new FileInputStream("D:\\studyspace\\myio\\a.txt");int b1 = fis.read();System.out.println((char) b1);int b2 = fis.read();System.out.println((char) b2);int b3 = fis.read();System.out.println((char) b3);int b4 = fis.read();System.out.println((char) b4);fis.close();}
}
5)FileIutputStream 循环读取
FileInputStream fis = new FileInputStream("D:\\studyspace\\myio\\a.txt");int b;while ((b = fis.read()) != -1) {System.out.println((char) b);}fis.close();
6)简单文件拷贝
// 小文件拷贝,缺点:速度慢FileInputStream fis = new FileInputStream("D:\\studyspace\\myio\\a.txt");FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\b.txt");
// 思路:读一个,写一个,缺点:速度慢int b;while ((b = fis.read()) != -1) {fos.write(b);}// 通常最先打开的,最后关闭fos.close();fis.close();
// 一次读取多个字节FileInputStream fis = new FileInputStream("D:\\studyspace\\myio\\a.txt");
// 入参的字节数组多大,一次就会读取多少个字节并写入到字节数组中byte[] bytes = new byte[2];
// 返回值为本次读取的长度int len1 = fis.read(bytes);
// 表示从什么位置开始 读取多长的数据 转化为字符串String s1 = new String(bytes, 0, len1);System.out.println(s1);// 多次读取则覆盖原来位置的数据int len2 = fis.read(bytes);String s2 = new String(bytes, 0, len2);System.out.println(s2);int len3 = fis.read(bytes);String s3 = new String(bytes, 0, len3);System.out.println(s3);fis.close();
long start = System.currentTimeMillis();
// 大文件拷贝FileInputStream fis = new FileInputStream("D:\\yxh\\奇妙能力歌.mp3");FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\奇妙能力歌.mp3");
// 一次读取1M的数据byte[] bytes = new byte[1024*1024];int len;while ((len = fis.read(bytes)) != -1) {// 读到多少数据就写多少数据fos.write(bytes,0,len);}fos.close();fis.close();long end = System.currentTimeMillis();System.out.println(end - start);
long start = System.currentTimeMillis();
// jdk1.7开始 实现了 AutoCloseable接口的 流,可以在 try(){} 这种写法中自动关闭try (FileInputStream fis = new FileInputStream("D:\\yxh\\奇妙能力歌.mp3");FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\奇妙能力歌.mp3");){// 一次读取1M的数据byte[] bytes = new byte[1024*1024];int len;while ((len = fis.read(bytes)) != -1) {// 读到多少数据就写多少数据fos.write(bytes,0,len);}} catch (IOException e) {e.printStackTrace();}finally {System.out.println("拷贝结束拉");}long end = System.currentTimeMillis();System.out.println(end - start);
2. 字符流
Reader
Writer
FileReader
import java.io.FileReader;
import java.io.IOException;
public class CharStreamTest {public static void main(String[] args) throws IOException {/** 字符流底层也是字节流,默认一次也是读取一个字节,不同的是会根据不同的编码读取* 如果遇到中文一次就会读取多个字节 GBK一次读取两个字节,UTF-8一次读取三个字节* */FileReader fr = new FileReader("D:\\studyspace\\myio\\a.txt");int b ;while ((b = fr.read()) != -1) {System.out.print((char) b);}fr.close();}
}
//批量读取字符FileReader fr = new FileReader("D:\\studyspace\\myio\\a.txt");int len;char[] chars = new char[2];while ((len = fr.read(chars)) != -1) {System.out.println(new String(chars,0,len));}fr.close();
FileWriter
FileWriter fw = new FileWriter("D:\\studyspace\\myio\\a.txt");
// 1.字符对应的编码值fw.write(25105);
// 2.直接写入字符串String str= "你好牛啊?";fw.write(str);
// 3.写入字符数组char[] chars = new char[]{'你','愁','啥','?'};fw.write(chars);
// 4.写入字符数组的一部分fw.write(chars,1,3);
// 5.写入字符串的一部分fw.write(str,2,3);fw.close();
字符流原理解析
① 创建字符输入流对象底层:关联文件,并创建缓冲区(长度为8192的字节数据)
② 读取数据底层:1. 判断缓冲区中是否有数据可以读取2. 缓冲区中没有数据:就从文件中获取,装到缓冲区中,尽量每次都装满缓冲区如果文件中也没数据了,就返回-13. 缓冲区中有数据:就从缓冲区中读取空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解吗并转成十进制返回有参的read方法:把读取字节、解码、强转三步合并,强转之后的字符放入字符数组中
Writer同理:字符会先写入到缓冲区中,当缓冲区满了、手动调用flush方法、调用close方法关闭字符流 时
才会把当前缓冲区中的数据写入到文件中
文件夹拷贝Demo
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class CopyFileTest {public static void main(String[] args) throws IOException {copydir(new File("D:\\adir"),new File("D:\\bdir"));}/*** @param src 源文件夹* @param tag 目标文件夹* @throws Exception*/private static void copydir(File src, File tag) throws IOException {tag.mkdir();File[] files = src.listFiles();for (File file : files) {if (file.isFile()) {FileInputStream fis = new FileInputStream(file);FileOutputStream fos = new FileOutputStream(new File(tag, file.getName()));byte[] bytes = new byte[1024];int len;while ((len = fis.read(bytes)) != -1) {fos.write(bytes,0,len);}fos.close();fis.close();} else {copydir(file,new File(tag,file.getName()));}}}
}
文件加密Demo
/*^ 异或运算1. boolean ^ boolean 相同为false 不同为true2. 数字 异或 100 ^ 1011001000001010---------11011101 * 2^6 + 1 * 2^5 + 0 + 1 * 2^3 + 1 * 2^2 + 1 * 2 + 0 = 64 + 32 + 8 + 4 + 2 = 110100 ^ 10 = 110110 ^ 10 = 100所以可以通过异或运算加解密* */FileInputStream fis = new FileInputStream("D:\\studyspace\\myio\\a.txt");FileOutputStream fos = new FileOutputStream("D:\\studyspace\\myio\\b.txt");int b;while ((b = fis.read()) != -1) {fos.write(b ^ 10);}fos.close();fis.close();
3. 字节缓冲流
BufferedInputStream
BufferedOutputStream
构造函数
// 默认创建一个大小为 8192的缓冲区private static int DEFAULT_BUFFER_SIZE = 8192;public BufferedInputStream(InputStream in, int size) {super(in);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size];}
单字节读写和字节数组读写
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\studyspace\\myio\\a.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\studyspace\\myio\\b.txt"));int b;while ((b = bis.read())!=-1) {bos.write(b);}bos.close();bis.close();
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\studyspace\\myio\\a.txt"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\studyspace\\myio\\b.txt"));int len;byte[] bytes = new byte[1024];while ((len = bis.read(bytes))!=-1) {bos.write(bytes,0,len);}bos.close();bis.close();
3. 字符缓冲流
字符流本身就有缓冲流再次封装对性能的提升不大,但是有了两个特别好用的方法 readLine
和newLine
BufferedReader
BufferedWriter
BufferedReader br = new BufferedReader(new FileReader("D:\\studyspace\\myio\\a.txt"));/** readLine方法在读取的时候,一次读取一整行,遇到回车换行结束* 但是读取的内容不包含换行符* *//*String line1 = br.readLine();System.out.println(line1);String line2 = br.readLine();System.out.println(line2);*/String line;while ((line = br.readLine()) != null) {System.out.println(line);}br.close();
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\studyspace\\myio\\a.txt"));bw.write("我结婚的时候,你一定要来哦~");
// 这是一个跨平台的换行操作,根据操作系统的不同,写入对应系统的换行符bw.newLine();bw.write("婚礼没有新娘我会很尴尬……");bw.newLine();bw.close();
/** 将b.txt中乱序的文本排序后写入a.txt* */BufferedReader br = new BufferedReader(new FileReader("D:\\studyspace\\myio\\b.txt"));String line;TreeMap<Integer,String> tm = new TreeMap<>();while ((line = br.readLine()) != null) {tm.put(Integer.parseInt(line.split("\\.")[0]),line);}BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\studyspace\\myio\\a.txt"));for (String value : tm.values()) {bw.write(value);bw.newLine();}bw.close();br.close();
4. 转换流
InputStreamReader
OutputStreamWriter
// 利用转换流按照指定编码读取
// jdk11 这种写法就被替代了,参数 charset 被集成到了字类 FileReader上
// new FileReader("D:\\studyspace\\myio\\ist.txt", Charset.forName("GBK"))InputStreamReader isr = new InputStreamReader(new FileInputStream("D:\\studyspace\\myio\\ist.txt"), "GBK");int b;while ((b = isr.read()) != -1) {System.out.print((char) b);}isr.close();OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\studyspace\\myio\\isr.txt"), "GBK");osw.write("呵呵");osw.close();
5. 序列化流
ObjectInputStream
ObjectOutputStream
Student student = new Student();student.setAge(18);student.setName("张三");student.setAddress("北京");ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\studyspace\\myio\\oos.txt"));oos.writeObject(student);oos.close();ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:\\studyspace\\myio\\oos.txt"));Student object = (Student) ois.readObject();System.out.println(object);ois.close();
import java.io.Serializable;public class Student implements Serializable {private static final long serialVersionUID = 6768132401505607054L;private int age;private String name;private transient String address;public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Student{" +"age=" + age +", name='" + name + '\'' +", address='" + address + '\'' +'}';}
}
Serializable
标志性接口,当类实现了此接口,就表示此类的对象需要序列化
serialVersionUID
相当于类的版本号,当没指定该属性时,Java会自动根据类的属性方法等计算出一个值,当类的属性方法修改后,计算出来的值就可能和之前的不一样,会导致反序列化失败,所以通常会手动指定该属性的值,并且非特殊情况不会轻易修改该值
Exception in thread "main" java.io.InvalidClassException: Student; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 985628350043525245at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:699)at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1885)at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1751)at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2042)at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)at ObjectStreamTest.main(ObjectStreamTest.java:21)Process finished with exit code 1
可以在idea中配置自动生成serialVersionUID,当类没有指定该属性时就会进行提示
transient
当需要某些属性不被序列化时,可以使用该关键字修饰属性
6. 打印流
打印流只有输出流没有输入流
// 字节打印流,没有缓冲区,自动刷新开启与否没有影响PrintStream ps = new PrintStream("D:\\studyspace\\myio\\ps.txt");// 原样输出 自动刷新 自动换黄ps.println(97);ps.print(true);ps.println();
// 占位符,和C语言类似ps.printf("%s爱上了%s","阿珍","阿强");ps.close();
// 字符打印流,有缓冲区,需要打开 自动刷新PrintWriter pw = new PrintWriter(new FileWriter("D:\\studyspace\\myio\\pw.txt"),true);pw.println(97);pw.print(true);pw.println();pw.printf("%s爱上了%s","阿珍","阿强");pw.close();
7. 压缩流
Java中只能识别zip格式的压缩包
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;public class ZipStreamTest {public static void main(String[] args) throws IOException {File src = new File("D:\\adir.zip");File dest = new File("D:\\adir");unzip(src,dest);}private static void unzip(File src,File dest) throws IOException {// 解压的本质:把压缩包里的每一个文件或文件夹读取出来,按层级拷贝到目的地当中// 创建一个解压缩流来读取压缩包中的数据ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
// 获取压缩包中的ZipEntry对象ZipEntry entry;while ((entry = zip.getNextEntry()) != null) {System.out.println(entry);if (entry.isDirectory()) {new File(dest,entry.toString()).mkdir();} else {int b;FileOutputStream fos = new FileOutputStream(new File(dest, entry.toString()));while ((b = zip.read()) != -1) {fos.write(b);}fos.close();zip.closeEntry();}}zip.close();}
}
压缩单个文件
public static void main(String[] args) throws IOException {File src = new File("D:\\a.txt");File dest = new File("D:\\");tozip(src,dest);}// 压缩单个文件private static void tozip(File src,File dest) throws IOException {// 创建压缩流关联压缩文件ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest, "a.zip")));
// 创建ZipEntry,标识压缩包里的一个文件或文件夹ZipEntry entry = new ZipEntry("a.txt");
// 把entry放入到压缩包中zos.putNextEntry(entry);
// 把src中文件的数据写入到压缩包里FileInputStream fis = new FileInputStream(src);int b;while ((b = fis.read()) != -1) {zos.write(b);}zos.closeEntry();zos.close();}
压缩文件夹
public static void main(String[] args) throws IOException {File src = new File("D:\\adir");ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(src.getParent(), src.getName() + ".zip")));tozip(src,zos,src.getName());zos.close();}/*** 获取src里的每一个文件,变成 ZipEntry放入压缩包* @param src 数据源* @param zos 压缩流对象* @param name 压缩包内的路径* @throws IOException*/private static void tozip(File src,ZipOutputStream zos,String name) throws IOException {File[] files = src.listFiles();if (files.length > 0) {for (File file : files) {if (file.isFile()) {zos.putNextEntry(new ZipEntry(name + "\\" + file.getName()));FileInputStream fis = new FileInputStream(file);int b;while((b = fis.read()) != -1) {zos.write(b);}fis.close();zos.closeEntry();} else {tozip(file,zos,name + "\\" + file.getName());}}}}
8. 常用工具包
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version>
</dependency>
hutool文档
Java I/O流入门笔记相关推荐
- hadoop 2 java hdfs_Hadoop2.6.0学习笔记(二)HDFS访问
鲁春利的工作笔记,谁说程序员不能有文艺范? 通过hadoop shell与java api访问hdfs 工作笔记之Hadoop2.6集群搭建已经将集群环境搭建好了,下面来进行一些HDFS的操作 1.H ...
- 《Java编程思想》读书笔记 第十三章 字符串
<Java编程思想>读书笔记 第十三章 字符串 不可变String String对象是不可变的,每一个看起来会修改String值的方法,实际上都是创建一个全新的String对象,以及包含修 ...
- Java高级开发工程师面试笔记
最近在复习面试相关的知识点,然后做笔记,后期(大概在2018.02.01)会分享给大家,尽自己最大的努力做到最好,还希望到时候大家能给予建议和补充 ----------------2018.03.05 ...
- 零基础学习Java开发,这些学习笔记送给你
因为Java具备很多特点,并且在企业中被广泛应用为此很多小伙伴选择学习Java基础开发,但是零基础学习Java技术开发需要我们制定Java学习路线图对于我们之后的学习会非常有帮助. 零基础学习Java ...
- Java TCP/IP Socket 编程 笔记
http://jimmee.iteye.com/blog/617110 http://jimmee.iteye.com/category/93740 Java TCP/IP Socket 编程 笔记( ...
- Java 8 函数式编程学习笔记
Java 8 函数式编程学习笔记 @(JAVASE)[java8, 函数式编程, lambda] Java 8 函数式编程学习笔记 参考内容 Java 8中重要的函数接口 扩展函数接口 常用的流操作 ...
- Think in Java第四版 读书笔记10 第16章 数组
Think in Java第四版 读书笔记10 第16章 数组 数组和容器很像 但他们有一些差别 16.1 数组为什么特殊 数组与容器的区别主要在效率和存储类型 效率:数组是简单的线性序列 使得数组的 ...
- Think in Java第四版 读书笔记9第15章 泛型
Think in Java第四版 读书笔记9第15章 泛型 泛型:适用于很多很多的类型 与其他语言相比 Java的泛型可能有许多局限 但是它还是有很多优点的. 本章介绍java泛型的局限和优势以及ja ...
- 只学一门java可行吗,java可以作为第一门编程语言学习吗
java可以作为第一门编程语言学习吗,语言,课程,入门,计算机科学,都在 java可以作为第一门编程语言学习吗 易采站长站,站长之家为您整理了java可以作为第一门编程语言学习吗的相关内容. 十年前, ...
最新文章
- 记一次数据中心云平台系统项目实施
- CSS捡屎记 // Web开发之精通CSS
- 【响应式Web前端设计】css中:overflow:hidden解决塌陷
- JQuery 和JavaScript的区别
- Linux Shell脚本专栏_批量检测网站是否异常脚本_08
- python-变量操作-字符串
- easyx鼠标放置前按钮颜色_七种正确使用鼠标的好习惯,让你摆脱鼠标手的痛苦...
- python不定参数的函数实现_python传入不定参数是什么
- python大牛是什么水平_yield--Python大牛必须掌握的高端语法
- 一键免费下载外文文献的方式
- cannot import name ‘utc‘
- 【JVM系列JKD8】参数参考表
- 一次聚类引发的一系列问题(多线程篇-多线程慢于单线程)
- win10中sql plus中文乱码
- VVC帧间预测(十)帧间帧内联合预测CIIP
- 微星主板在有RAID的情况下在NVME的SSD上安装Win10
- java蓝桥杯练习 拉马车
- 基于微信运动场地预约小程序 毕业设计毕业论文 开题报告和效果图(基于微信小程序毕业设计题目选题课题)
- PCB检查-allegro PDN进行简单电源直流压降分析
- 软件版本(release、stable、lastest)的区别