Java基础14-缓冲区字节流;File类
作业解析
阐述BufferedReader和BufferedWriter的工作原理,
是否缓冲区读写器的性能恒大于非缓冲区读写器的性能,为什么,请举例说明?
答: BufferedReader对Reader类进行了装饰,即在成员变量中声明一个Reader成员变量,在构造时将该成员变量进行初始化,BufferedReader在读取文件时,将读取到的数据存储在字符数组中,下一次读取时,从字符数组中取出对应的数据,避免对物理文件的频繁访问;BufferedWriter对Writer类进行了装饰,在写入数据时,先写入到字符数组中,当字符数组写满时,才将字符数组中的数据清理到物理文件中去。
根据上述工作原理可以看到缓冲区读写器的性能不一定大于非缓冲区读写器的性能。对BufferedReader来说,如果FileReader读取时采用字符数组读取,则会比BufferedReader要快;对BufferedWriter来说,如果一次写入的数据量很大,则FileWriter要快。写入数据1~1000000数字到文件中,分别使用FileWriter和BufferedWriter实现,考察其效率的不同
package com.kokojia.io; import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException; public class FileWriterBufWriterDemo { public static void main(String[] args) throws Exception {
/**
* 写入数据1~1000000数字到文件中,分别使用FileWriter和BufferedWriter实现,考察其效率的不同
*/ //非缓冲区字符输出流
FileWriter fw = new FileWriter("f.txt");
long startTime = System.currentTimeMillis();
for(int i=1;i<=1000000;i++) {
fw.write(i+"");
}
System.out.println("FileWriter over!Cost time: "+(System.currentTimeMillis()-startTime));//460
fw.close();
//缓冲区字符输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("f.txt"));
startTime = System.currentTimeMillis();
for(int i=1;i<=1000000;i++) {
bw.write(i+"");
}
System.out.println("BufWriter over!Cost time: "+(System.currentTimeMillis()-startTime));//264
bw.close();
}
}
文件切割:
把较大的文件切割成20k一个的小文件/**
* 文件切割:把较大的文件切割成size大小的小文件
* @param srcFile
* @param size
* @throws Exception
*/
private static void fileSplit(String srcFile,int size) throws Exception { FileInputStream fis = new FileInputStream(srcFile); //获取源文件名
String fileName = srcFile.substring(srcFile.indexOf("/")+1,srcFile.indexOf("."));
//获取源文件后缀名
String sufName = srcFile.substring(srcFile.indexOf(".")+1);
//获得源文件大小
int srcFileSize = fis.available();
//计算切割的数量
int nCount = srcFileSize/size+1; FileOutputStream fos = null; byte[] buf = null; int len = -1;
for(int i=1;i<=nCount;i++) {
fos = new FileOutputStream(srcFile.substring(0,srcFile.indexOf("/")+1)+fileName+"-"+i+"."+sufName);
if(i==nCount) {
int bufLength =srcFileSize-size*(nCount-1);
buf = new byte[bufLength];
fis.read(buf);
fos.write(buf);
}
else {
int bufLength = size;
buf = new byte[bufLength];
fis.read(buf);
fos.write(buf);
}
fos.close();
}
fis.close();
}
文件合成:
把小文件合并成大文件/**
* 文件合成,把小文件合成大文件
* @param srcFiles
* @param string
* @throws Exception
*/
private static void fileCombine(String[] srcFiles, String destFile) throws Exception {
FileOutputStream fos = new FileOutputStream(destFile);
FileInputStream fis = null;
for(String s: srcFiles) {
fis = new FileInputStream(s);
int len = -1;
byte[] buf = new byte[1024];
while((len=fis.read(buf))!=-1) {
fos.write(buf,0,len);
}
fis.close();
}
fos.close();
}
文件归档解档:
0=txt,1=jpg,2=avi,3=gif
解档归档工具类package com.kokojia.io; import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; public class Archive { /**
* 新建归档文件
* @param srcFiles
* @param destFile
* @throws Exception
*/ public void newArchiver(String[] srcFiles, String destFile) throws Exception {
FileOutputStream fos = new FileOutputStream(destFile);
for(String srcFile: srcFiles) {
addNewFile(srcFile,fos);
}
fos.close();
} private void addNewFile(String srcFile, FileOutputStream fos) throws Exception {
FileInputStream fis = new FileInputStream(srcFile);
//获取文件后缀名
String sufName = srcFile.substring(srcFile.lastIndexOf(".")+1);
//写入文件后缀名
if(sufName.equals("txt")) {
fos.write((byte)0);
}
if(sufName.equals("mkv")){
fos.write((byte)1);
}
if(sufName.equals("jpg")){
fos.write((byte)2);
}
//获取文件大小,写入文件大小
int fileLength = fis.available();
byte[] fileSizes = int2bytes(fileLength);
fos.write(fileSizes); //写入文件内容
int len = -1;
byte[] buf = new byte[1024];
while((len=fis.read(buf))!=-1) {
fos.write(buf,0,len);
}
fis.close();
} /**
* int转化为字节数组
*/
private byte[] int2bytes(int fileLength) {
byte[] fileSizes = new byte[4];
fileSizes[0] = (byte)fileLength;
fileSizes[1] = (byte)(fileLength>>8);
fileSizes[2] = (byte)(fileLength>>16);
fileSizes[3] = (byte)(fileLength>>24);
return fileSizes;
} /**
* 文件解档
* @param string
* @param string2
* @throws Exception
*/
public void unArchiver(String yarPath, String destPath) throws Exception {
FileInputStream fis = new FileInputStream(yarPath); byte bytes[] = new byte[1];
int len = -1;
int fileNo = 1;//记数文件个数
String sufNames[] = new String[] {"txt","mkv","jpg"} ;
while((len=fis.read(bytes))!=-1) { //获取文件大小
byte fileSize[] = new byte[4];
fis.read(fileSize);
int fileLength = bytes2int(fileSize); //获取文件后缀名
String sufName = sufNames[bytes[0]]; //创建输出文件
FileOutputStream fos = new FileOutputStream(destPath+"/"+fileNo+"."+sufName); byte buf[] = new byte[1024];
//计算读取次数
int nCount = fileLength/buf.length+1; for(int i = 1; i<=nCount;i++) {
if(i==nCount) {
byte buf2[] = new byte[fileLength-buf.length*(nCount-1)];
fis.read(buf2);
fos.write(buf2);
}
else {
fis.read(buf);
fos.write(buf);
}
}
fileNo++;
fos.close();
}
fis.close();
} /**
* byte数组转化为int
*/
private int bytes2int(byte[] fileSize) {
int fileLength = 0;
fileLength = (fileSize[0] & 0xff) | (fileSize[1] & 0xff)<<8 | (fileSize[2] & 0xff)<<16 | (fileSize[3] & 0xff)<<24;
return fileLength;
}
}
测试类
public class ArchiveDemo {
@Test
public void ArchiverTest() throws Exception {
Archive archive = new Archive();
String[] srcFiles = new String[] {"1.txt","2.2 logistic 回归.mkv","test.jpg"}; archive.newArchiver(srcFiles,"all.yar");
System.out.println("over");
} @Test
public void unArchiverTest() throws Exception {
Archive archive = new Archive();
archive.unArchiver("all.yar","1");
}
}
阐述HashSet与HashMap的异同。
答:HashSet的本质是HashMap,其value项为一个占位符(垃圾变量)。添加元素时,通过key的hash值确定其理应添加的数组位置。依次与当前数组中的元素进行对比,比对原则有三个:(hashcode1hashcode2) && ( o1o2 || (o1.equals(o2)) ),如果没有元素与之相同,则添加到该区间元素的末尾。通过key查询时,先得到key对应的hashcode, 然后定位到所在区间,简化了查询,最后按照上述的三个原则进行比对Charset类操作: isSupport()
3.1) 通过该类验证平台是否支持以下字符集:
gb2312
GB2312
gbk
GBK
utf-8
utf8
iso8859-1
iso-8859-13.2) 取出平台默认的字符集
System.out.println("默认字符集:"+Charset.defaultCharset());
System.out.println("是否支持gb2312: "+Charset.isSupported("gb2312"));
System.out.println("是否支持GB2312: "+Charset.isSupported("GB2312"));
System.out.println("是否支持gbk: "+Charset.isSupported("gbk"));
System.out.println("是否支持GBK: "+Charset.isSupported("GBK"));
System.out.println("是否支持utf-8: "+Charset.isSupported("utf-8"));
System.out.println("是否支持utf8: "+Charset.isSupported("utf8"));
System.out.println("是否支持iso8859-1: "+Charset.isSupported("iso8859-1"));
使用FileInputStream + FileOutputStream / BufferedInputStream + BufferedOuputStream
实现大文件复制,比较复制效率。import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException; public class CopyBigFile {
/**
* 使用FileInputStream + FileOutputStream / BufferedInputStream + BufferedOuputStream
实现大文件复制,比较复制效率。
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("1.txt");
for(int i = 0;i<1024*1024;i++) {
fw.write(i+",");
}
fw.close(); //非缓冲区字节输入流
FileInputStream fis=new FileInputStream("test.jpg");
//缓冲区字节输入流
BufferedInputStream bis=new BufferedInputStream(new FileInputStream("test.jpg")); //非缓冲区字节输出流
FileOutputStream fos=new FileOutputStream("FileOutput.jpg");
//缓冲区字节输入流
BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream("BufOutput.jpg")); int len=-1;
byte bytes[] = new byte[1024]; //非缓冲区复制文件
long startTime = System.currentTimeMillis();
while((len=fis.read(bytes))!=-1) {
fos.write(bytes, 0, len);
}
fis.close();
fos.close();
System.out.println("非缓冲区复制完成!耗时:"+(System.currentTimeMillis()-startTime)); //缓冲区复制文件
startTime = System.currentTimeMillis();
while((len=bis.read(bytes))!=-1) {
bos.write(bytes, 0, len);
}
bis.close();
bos.close();
System.out.println("缓冲区复制完成!耗时:"+(System.currentTimeMillis()-startTime)); System.out.println(System.lineSeparator());
System.out.println("over");
}
}
阐述对象回收的前提条件。
答:当内存中没有一个引用可以指向该对象时,该对象将会被回收。在Set集合中,添加对象后,如果将对象的引用置空,对象也不会被回收,因为Set集合中仍然存在该对象的引用。
缓冲区字节流
BufferedOutputStream:缓冲区字节输出流
- Object --> OutputStream --> FilterOutputStream --> BufferedOutputStream
- 使用装饰模式
BufferedInputStream : 缓冲区输入流
- Object --> InputStream --> FilterInputStream --> BufferedInputStream
- close():释放与之关联的系统资源。多次关闭没有影响。手动关闭时,从外部向里面关闭。
字节数组输出流:ByteArrayOutputStream
- Object --> OutputStream --> ByteArrayOutputStream
- 在内存中开辟空间,存放数据。不是缓冲区流
字节数组输入流 : ByteArrayInputStream
- Object --> InputStream --> ByteArrayInputStream
IO小结
流向
InputStream
OutputStream类型划分
a. 字符流(文本文件)
Reader | Writer
FileReader | FileWriter
b. 字节流(任何文件)
InputStream | OutputStream
FileInputStream | FileOutputStream性能划分
BufferedWriter: 缓冲区流(装饰模式,flush清理) | 非缓冲区流
BufferedReader: 缓冲区,read(fill)
readLine() LineNumberReaderBufferedInputStream.read(): -128 ~ 127 -1
BufferedOutputStream
转换流
将字节流转换成字符流 ,使用特定字符集读取byte并解码成字符,底层操作是字节流,如果需要将其转换成字符内容处理,就可以使用转换流
InputStreamReader
是从字节流到字符流的桥梁,读取字节数组并解码(使用指定的字符集)成字符。字符集可以使用名称指定也可以
指定charset对象,或者平台默认也可以。
每次read()方法调用,都会引发底层字节流读取一个或者多个字节数据。如果需要高效来处理,可以对其使用
BufferedReader进行包装。- Object --> Reader --> InputStreamReader
- 不是缓冲区流
- 使用时,尽量使用BufferedReader对其进行包装,提高效率。
OutputStreamWriter :
- Object --> Writer --> OutputStreamWriter
- 不是缓冲区流
- 使用时,尽量使用BufferedReader对其进行包装,提高效率。
标准IO流
System.out.println();
standard Input //标准输入,默认是键盘,System.in, System.setIn(...)
standard Output //标准输出,默认是控制台,System.out, System.setOut(xxx)
File类
目录:指文件所在文件夹
路径:精准定位文件的地址,分为相对路径和绝对路径 . | ..
作业
定义函数,输出一个byte的二进制字符串。
定义工具类,完成int数和byte[]之间的相互转换。
阐述IO流。
输入输出流
字符字节流
缓冲和非缓冲流
转换流.通过File对象打印输出指定路径下的整个目录树结构。
完善归档和解档程序,文件头包含文件名(文件名+扩展名)+ 长度
提示:前四个字节文件名长度+文件名+四个字节文件大小+文件内容提取指定的第n个文件
输出文件名列表
使用文本文件传输媒体文件
1)将媒体文件的字节数组写到文本中,每个字节转换成了0-255之间的字符
2)使用BufferedReader读行,读取的每行转换成int, 再转换成byte
3)将转换成的byte数据写入到文件中
4)检验
255 === 1111 1111
-1 === 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111
21697
bw.write(a); //97
os.write(255); // ---> byte -128使用标准io从控制台读取一行文本,写入到指定文件中,遇到\q字符退出程序
使用递归遍历指定目录的所有子目录,打印每个目录和文件的绝对路径
File
File.listFiles()
File.getAbsolutePath()
File.getName()阐述归档和解归档的实现原理
复制文件夹:递归实现
Java基础14-缓冲区字节流;File类的更多相关文章
- java基础——IO流之File类
1.File类的构造方法: File(String pathName):通过一个指定的字符串类型路径来创建一个文件对象 File (String parent,String child):通过指定 ...
- Java基础-类加载机制与自定义类Java类加载器(ClassLoader)
Java基础-类加载机制与自定义类Java类加载器(ClassLoader) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 关于类加载器的概念和分类我就不再废话了,因为我在之前的笔 ...
- Java基础-DBCP连接池(BasicDataSource类)详解
Java基础-DBCP连接池(BasicDataSource类)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程 ...
- -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流
File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) ...
- JAVA IO分析一:File类、字节流、字符流、字节字符转换流
因为工作事宜,又有一段时间没有写博客了,趁着今天不是很忙开始IO之路:IO往往是我们忽略但是却又非常重要的部分,在这个讲究人机交互体验的年代,IO问题渐渐成了核心问题. 一.File类 在讲解File ...
- java基础知识回顾之javaIO类--File类应用:过滤器接口FilenameFilter和FileFilter
FilenameFilter和FileFilter都是用来过滤文件,例如过滤,以.jpg或者.java结尾的文件,通过看他们的源码:通过使用File类中String[] list(FilenameFi ...
- java基础知识回顾之javaIO类--File类
File类是对文件系统中文件以及目录(文件夹)进行封装的对象,可以通过面向对象的思想来操作文件和目录(文件夹).File类保存文件或目录的各种元素的信息,包括文件名,文件长度,最后修改日期,是否可读, ...
- IO流--字符流与字节流--File类常用功能
IO流的常用方法: 1: 文件的读取和写入图解: 2:字节流: 读写文件的方法: 一般效率读取: 读取文件: FileInputStream(); 写数据: Fil ...
- Java自学第10期——File类与IO流(输入输出流、处理流、转换流、缓冲流、Properties集合、打印流)
1.IO简介 IO(输入输出)通过java.io包下的类和接口来支持,包下包括输入.输出两种IO流,每种输入输出流又可分为字符流和字节流两大类. 2.File类 File类是io包下与平台无关的文件和 ...
随机推荐
- php将字符串转为二进制数据串
/** * 将字符串转换成二进制 * @param type $str * @return type */ function StrToBin($str){ //1.列出每个字符 $arr = pre ...
- PyQt5中的信号与槽,js 与 Qt 对象之间互相调用
一.PyQt中的信号与槽 信号(Signal)和槽(Slot)是Qt中的核心机制,用在对象之间互相通信.在Qt中每个QObject对象和PyQt中所有继承自QWidget的控件(这些都是QObject ...
- vue.js实战——.native修饰符
https://blog.csdn.net/qq_29468573/article/details/80771625 除了用v-on在组件上监听自定义事件外,也可以监听DOM事件,这时可以用.nati ...
- MyBatis 3
MyBatis 3 学习笔记 一.Mybatis 基础知识 1.MyBatis 3编写步骤: 根据mybatis-config.xml配置文件创建一个SqlSessionFactory对象. sql映 ...
- 一个解释volatile关键字最好的例子
小例子 public class VolatileTest { private static volatile int INIT_VALUE = 0; private final static int ...
- Q_UNUSED 的使用
在构建比较大型的工程的时候,若继承,重构虚函数,写数据model等等比较多的时候,会给出大量的 “未引用的形参” ,“warning: unused parameter ” 的告警.这种告警多了会影 ...
- k8s-jenkins 自动化1
一个流水线例子: 设置参数化构建: 流水线指令: def label = "docker-${UUID.randomUUID().toString()}" podTemplate( ...
- 「Manacher算法」学习笔记
觉得这篇文章写得特别劲,插图非常便于理解. 目的:求字符串中的最长回文子串. 算法思想 考虑维护一个数组$r[i]$代表回文半径.回文半径的定义为:对于一个以$i$为回文中心的奇数回文子串,设其为闭区 ...
- 执行Git命令时出现各种 SSL certificate problem 的解决办法
执行Git命令时出现各种 SSL certificate problem 的解决办法 来源 https://www.cnblogs.com/chenzc/p/5842932.html 比如我在win ...
- windows下安装oracle11g测试是否成功与监听器问题和网页控制台登录
测试步骤1:请执行操作系统级的命令:tnsping orcl 测试步骤 2:请执行操作系统级的命令:sqlplus system/password@orcl 安装完oracle后要启动oracle服务 ...