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包下与平台无关的文件和 ...
随机推荐
- django.db.utils.ProgrammingError: (1146, "Table 'db_gold.user_ip_info' doesn't exist") RuntimeError: Model class scanhosts.models.HostLoginInfo doesn't declare an explicit app_label and isn't in an a
Error Msg 创建了一个apps的目录将所有app放入apps文件中, 将apps路径加入sys.path中:sys.insert(0, os.path.join(BASE_DIR, " ...
- node.js、js读取excel、操作excel、创建excel之js-xlsx.js
node.js篇 第一步引入包 npm install xlsx -save 第二步使用 var xl =require('xlsx'); //workbook 对象,指的是整份 Excel 文档.我 ...
- Ceva定理的四种证明方法
${\color{Teal} {Ceva定理}}$设$D.E.F$依次为三角形ABC的边$AB.BC.CA$的内点,记 $λ$=(A,B,D),$μ$=(B,C,E),$v$=(C,A,F) 求证:三 ...
- js 前端常用排序算法总结
(冒泡排序.快排顺序.选择排序.插入排序.归并排序) 下面是前端比较常用的五个算法demo: 冒泡算法:比较两个相邻的数值,if第一个>第二个,交换他们的位置元素项向上移动至正确的顺序. fun ...
- nginx的概念与几种负载均衡算法
Nginx的背景 Nginx和Apache一样都是一种WEB服务器.基于REST架构风格,以URI(Uniform Resources Identifier,统一资源描述符)或URL(Uniform ...
- x86汇编寄存器,函数参数入栈说明
https://en.wikipedia.org/wiki/X86_calling_conventions
- 怎么用MATLAB产生FPGA所需的hamming窗系数
需求 在FPGA处理中如果需要对待处理数据加窗,则需要窗系数存储在ROM中以供使用. 前言 MATLAB窗函数说明 流程 比如加个hamming窗,8192点,16bit放大,最终系数18bit位宽. ...
- canvas基础(一)
获取元素与画笔: <canvas id="myCanvas" width="200" height="200">该浏览器不支持c ...
- 集合源码分析[3]-ArrayList 源码分析
历史文章: Collection 源码分析 AbstractList 源码分析 介绍 ArrayList是一个数组队列,相当于动态数组,与Java的数组对比,他的容量可以动态改变. 继承关系 Arra ...
- FTP文件上传 支持断点续传 并 打印下载进度(二) —— 单线程实现
这个就看代码,哈哈哈哈哈 需要用到的jar包是: <dependency> <groupId>commons-net</groupId> <artifact ...