(1)一个人只要自己不放弃自己,整个世界也不会放弃你.
(2)天生我才必有大用
(3)不能忍受学习之苦就一定要忍受生活之苦,这是多么痛苦而深刻的领悟.
(4)做难事必有所得
(5)精神乃真正的刀锋
(6)战胜对手有两次,第一次在内心中.
(7)好好活就是做有意义的事情.
(8)亡羊补牢,为时未晚
(9)科技领域,没有捷径与投机取巧。
(10)有实力,一年365天都是应聘的旺季,没实力,天天都是应聘的淡季。
(11)基础不牢,地动天摇
(12)写博客初心:成长自己,辅助他人。当某一天离开人世,希望博客中的思想还能帮人指引方向.
(13)编写实属不易,若喜欢或者对你有帮助记得点赞+关注或者收藏哦~
Java IO在Android中应用基础篇
文章目录
1.为什么要学习Java I/O
扎实的Java基础:
- 对象序列化
- Json解析
- xml解析
- zip压缩均需要以I/O作为其基础
- 处理底层数据业务的时候
2.IO中经常看见的使用方式
DataOutputStream out = new DataOutputStream(
new BufferedOutputStream(
new FileOutputStream(
new File(file)
)));
(1)这种嵌套的原理是什么?
(2)输出流是从内存输出到打印设备或硬盘
(3)输入流是从文件读到内存中
(4)读入、写出,是从内存的角度来说的。
(5)BufferedOutputStream缓存的目的是为了让文件的读取更快,减少对磁盘的访问。
- 因为在没有Buffer的时候,它一定会访问磁盘,它是一个字节一个字节的去访问,如果有Buffer它可以访问一块,连续的去访问一块,这个时候可以去减少对磁头的调用。
(6)DataOutputStream就是文件的序列。
(7)FileOutputStream是为了将文件变成一个流
(8)没有Buffer也可以去读文件,只不过有的话,速度会更快,格式会更加符合我们的需求。
- 工厂模式是用来做选择的
- 现在的问题是哪个套哪个
3.装饰模式
3.1装饰模式之Android的Context源码
3.2装饰模式
3.2.1装饰模式的实现案例
3.2.1.1抽象构件角色
/**
* 抽象构件角色
*/
public interface Component {
void doSomeThing();
}
3.2.1.2具体构建角色
/**
* 具体构建角色
*/
public class ConcreteComponent implements Component {
@Override
public void doSomeThing() {
System.out.println("功能A");
}
}
3.2.1.3装饰角色
/**
* 装饰角色
* 1.实现抽象构建角色接口
* 2.并且持有抽象构建角色的引用,便于通过构造方法为具体构建角色赋值。
*/
public class Decorator implements Component {
/**
* 持有抽象构建角色的引用
*/
private Component component;
public Decorator(Component component) {
super();
this.component = component;
}
@Override
public void doSomeThing() {
component.doSomeThing();
}
}
3.2.1.4具体装饰角色
/**
* 具体装饰角色1
*/
public class ConcreteDecorator1 extends Decorator{
public ConcreteDecorator1(Component component) {
super(component);
}
@Override
public void doSomeThing() {
super.doSomeThing();
this.doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能B");
}
}
/**
* 具体装饰角色2
*/
public class ConcreteDecorator2 extends Decorator {
public ConcreteDecorator2(Component component) {
super(component);
}
@Override
public void doSomeThing() {
super.doSomeThing();
doAnotherThing();
}
private void doAnotherThing() {
System.out.println("功能C");
}
}
3.2.1.5客户端
public class Client {
public static void main(String[] args) {
//s1.创建具体构建角色
Component component1 = new ConcreteComponent();
//s2.创建具体装饰角色1
Component component2 = new ConcreteDecorator1(component1);
//s3.创建具体装饰角色2
Component component3 = new ConcreteDecorator2(component2);
//s4.调用具体构建角色方法
component3.doSomeThing();
}
@Test
public void test1(){
Component component =
new ConcreteDecorator2(
new ConcreteDecorator1(
new ConcreteComponent()));
component.doSomeThing();
}
}
3.2.2IO中的装饰模式
4.IO学习的关键方法
-
挑战
Java IO的学习是一件非常艰巨的任务。 -
全面
(1)它的挑战是来自于要覆盖所有的可能性。
(2)不仅存在各种I/O源端还有想要和他通信的接收端(文件/控制台/网络链接),而且还需要以不同的方式与他们进行通信(顺序/随机存取/缓冲/二进制/字符/行/字 等等)这些情况综合起来就给我们带来了大量的学习任务,大量的类需要学习。
- 历史
(1)我们要学会所有的这些java 的IO是很难的,因为我们没有构建一个关于IO的体系,要构
建这个体系又需要深入理解IO库的演进过程,所以,我们如果缺乏历史的眼光,很快我们会对什
么时候应该使用IO中的哪些类,以及什么时候不该使用它们而困惑。
(2)所以,在开发者的眼中,IO很乱,很多类,很多方法,很迷茫。
(3)装饰模式的灵活性
- 可以根据抽象构建角色,构建多个具体构建角色
- 可以根据抽象构建角色与抽象装饰角色构建多个具体装饰角色
4.1IO装饰模型的学习
(1)当我们写文件的时候,首先要创建一个DataInputStream,提供给BufferedInputStream用,由它来提高速度。
(2)DataInputStream是把什么变成DataInputStream?
- 是把文件变成DataInputStream,即把一个File变成一个Stream
- FileInputStream就可以把文件File转变成Stream
- DataInputStream的父类是FilterInputStream,它的读写有格式
- 而FileInputStream的父类是InputStream
- BufferedInputStream的父类也是FilterInputStream,是用来提高速度的,它的读写无格式
- 总的来说IO装饰模式就是为了让流的功能逐步得到增强。
5.Java I/O发展历史与详细介绍
5.1IO类结构
5.2字节流的学习
(1)FileInputStream与FileOutputStream是将File文件变成流,然后提供给BufferedOutputStream与BufferedInputStream用.
(2)ObjectOutputStream与ObjectInputStream是读写一个Object
(3)ByteArrayOutputStream与ByteArrayInputStream是针对byte数组提供的
(4)FilterInputStream与FilterOutputStream是一个通用的接口,它并不能直接使用,它所扮演的角色就是装饰模式中的装饰角色.它为以下各种具体装饰流提供了共性的方法。
public class FilterInputStream extends InputStream {
public class FilterOutputStream extends OutputStream {
5.2.1案例
public class DataStream {
/**
* 写
*/
@Test
public void testDataOutPutStream() {
try {
File file = new File("src/testtxt/dataStreamTest.txt");
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
out.writeBoolean(true);
out.writeByte((byte) 0x41);
out.writeChar((char) 0x4243);
out.writeShort((short) 0x4445);
out.writeInt(0x12345678);
out.writeLong(0x987654321L);
out.writeUTF("abcdefghijklmnopqrstuvwxyz严12");
out.writeLong(0x023433L);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读
*/
@Test
public void testDataInputStreamI() {
try {
File file = new File("src/testtxt/dataStreamTest.txt");
DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
System.out.println(Long.toHexString(in.readLong()));
System.out.println(in.readBoolean());
System.out.println(byteToHexString(in.readByte()));
System.out.println(charToHexString(in.readChar()));
System.out.println(shortToHexString(in.readShort()));
System.out.println(Integer.toHexString(in.readInt()));
System.out.println(Long.toHexString(in.readLong()));
System.out.println(in.readUTF());
System.out.println(Long.toHexString(in.readLong()));
in.close();
} catch (Exception e) {
}
}
// 打印byte对应的16进制的字符串
private static String byteToHexString(byte val) {
return Integer.toHexString(val & 0xff);
}
// 打印char对应的16进制的字符串
private static String charToHexString(char val) {
return Integer.toHexString(val);
}
// 打印short对应的16进制的字符串
private static String shortToHexString(short val) {
return Integer.toHexString(val & 0xffff);
}
}
5.2.2BufferedInputStream
(1)每次都读一个byte buf[]数组,即每次不是读一个字节,而是读一块。
public class BufferedStream {
private static final byte[] byteArray = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76,
0x77, 0x78, 0x79, 0x7A };
@Test
public void bufferedOutPutStream() {
try {
File file = new File("src/testtxt/BufferedStreamTest.txt");
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
bos.write(byteArray[0]);
bos.write(byteArray, 1, byteArray.length - 1);
bos.flush();
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void bufferedInputStream() {
try {
File file = new File("src/testtxt/BufferedStreamTest.txt");
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
for (int i = 0; i < 10; i++) {
if (bin.available() >= 0) {
System.out.println(byteToString((byte) bin.read()));
}
}
bin.mark(6666);
bin.skip(10);
byte[] b = new byte[1024];
int n1 = bin.read(b, 0, b.length);
System.out.println("剩余的有效字节数 : " + n1);
printByteValue(b);
bin.reset();
int n2 = bin.read(b, 0, b.length);
System.out.println("剩余的有效字节数 : " + n2);
printByteValue(b);
} catch (IOException e) {
e.printStackTrace();
}
}
private static String byteToString(byte b) {
byte[] barray = { b };
return new String(barray);
}
private static void printByteValue(byte[] buf) {
for (byte b : buf) {
if (b != 0) {
System.out.print(byteToString(b) + " ");
}
}
}
}
5.3字符流的学习
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cInQJ8nS-1619158576012)(6.png)]
(1)有了字节流之后为什么还要有字符流?
外文abcd是一个字节,而中文不是,每一个中国基本是2个字节以上。如果按字节去读中文文件,读出来就没有意义。
(2)字符流与节字流的区别
- 字符流有一个readline()
- 一个字符=2个字节(中文编码格式)
- 编码格式 UTF-8 GBK,这些编码格式的出现是为了兼容各种文字。
(3)为什么在xml、json、png、zip、apk、exe文件中很少使用到字符流?
- 因为这些文件将其读成字节都没有任何区别,使用字符流操作这些文件没什么用。
- 只有文件的每一行有意义,使用字符流才有意义。
5.3.1字符流
5.3.2字符流最常见用法
(1)一般是需要将字符流与字节流混合在一起使用的。
public class OutputStreamWriterTest {
private final static String STRING = "I like LiuManLin";
@Test
public void testOutputStreamWriter() throws IOException {
File file = new File("src/testtxt/OutputStreamWriter.txt");
// true, 设置内容可以追加
FileOutputStream fos = new FileOutputStream(file, true);
//todo 是否有一个封装好的writer?
OutputStreamWriter oswDef = new OutputStreamWriter(fos);
BufferedWriter bwdef = new BufferedWriter(oswDef);
bwdef.write(STRING);
bwdef.newLine();
bwdef.flush();
// bwdef.close(); //为什么不能在这写
System.out.println("oswDef encoding: " + oswDef.getEncoding());
OutputStreamWriter oswGBK = new OutputStreamWriter(fos, "GBK");
BufferedWriter bwGBK = new BufferedWriter(oswGBK);
bwGBK.write(STRING + "GBK");
bwGBK.newLine();
bwGBK.flush();
// bwGBK.close();
System.out.println("oswDef encoding: " + oswGBK.getEncoding());
OutputStreamWriter oswUTF8 = new OutputStreamWriter(fos, "UTF-8");
BufferedWriter bwUTF8 = new BufferedWriter(oswUTF8);
bwUTF8.write(STRING + "UTF-8");
bwUTF8.newLine();
bwUTF8.flush();
// bwUTF8.close();
System.out.println("oswDef encoding: " + oswUTF8.getEncoding());
bwdef.close();
bwGBK.close();
bwUTF8.close();
}
}
public class InputStreamReaderTest {
public static void testISRDefaultEncoder(InputStream is){
try{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String string;
while ((string = br.readLine()) != null) {
System.out.println(string);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void testISRGBK(InputStream is){
try {
InputStreamReader inputStreamReader = new InputStreamReader(is,"GBK");
BufferedReader gbkBr = new BufferedReader(inputStreamReader);
String string;
while ((string = gbkBr.readLine()) != null) {
System.out.println("code: " + inputStreamReader.getEncoding());
System.out.println(string);
}
gbkBr.close();
} catch (IOException e) {
}
}
public static void testISRUTF8(InputStream is){
try {
InputStreamReader inputStreamReader = new InputStreamReader(is,"UTF-8");
BufferedReader gbkBr = new BufferedReader(inputStreamReader);
String string;
while ((string = gbkBr.readLine()) != null) {
System.out.println("code: " + inputStreamReader.getEncoding());
System.out.println(string);
}
gbkBr.close();
} catch (IOException e) {
}
}
@Test
public void testReader() throws Exception{
testISRDefaultEncoder(
new FileInputStream(
new File("src/testtxt/OutputStreamWriter.txt")));
testISRGBK(
new FileInputStream(
new File("src/testtxt/OutputStreamWriter.txt")));
testISRUTF8(
new FileInputStream(
new File("src/testtxt/OutputStreamWriter.txt")));
}
}
(1)Writer与Reader只需要关注BufferedWriter与BufferedReader,OutputStreamWriter与InputStreamReader.
5.3.3字符流相关问题
(1)如果只用FileOutputStream fileOutputStream = new FileOutputStream(“d:/text.txt”);
不是也能输出到"d:/text.txt"吗?为什么要用其它两个呢?能起到什么作用呢?
答案:
FileOutputStream :是字节流,它一个字节一个字节的向外边送数据
OutputStreamWriter:是字符流,它一个字符一个字符的向外边送数据
(2)它们有什么区别么?
答案:
-
因为计算机是洋鬼子发明的,它们的英文字符占一个字节,而我们的中文是一个字符,至少占俩字节。
-
如果用stream,你读出来的英语再倒也罢了,读出来的中文可就是乱码或者一个个“????”。
如果你用WRITER,就不会有乱码了
(3)BufferedWriter Buffer是一个缓冲区,为什么要用BUFFER呢?
答案:
如果你直接用stream或者writer,你的硬盘可能就是读一个字符或者一个字节 就去读写
硬盘一次,IO负担巨大。可是你用了Buffer,你的硬盘就是读了一堆数据之后,读写一下硬
盘。这样对你硬盘有好处。
public class ObjectStream {
private File newFile(String path){
File file = new File(path);
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
return file;
}
private void writeObject(){
try {
FileOutputStream fos = new FileOutputStream("src/testtxt/object.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
for(int i = 0; i < 10; i++){
oos.writeObject(new Person("欧阳锋[" + i +"]", i));
}
oos.flush();
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void readObject() {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(
new BufferedInputStream(
new FileInputStream(newFile("src/testtxt/object.txt"))));
while (ois.available() != -1) {
System.out.println("available: "+ois.available());
try {
Object object = ois.readObject();
Person person = (Person) object;
System.out.println(person);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch (EOFException e){
//用EOFException来判断结束
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void writeObjectByArray(){
try {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream(newFile("src/testtxt/objectArrays.txt")));
Person[] persons = new Person[10];
for(int i = 0; i < 10; i++){
Person person = new Person("洪七公[" + i + "]", i);
persons[i] = person;
}
oos.writeObject(persons);
oos.close();
} catch (Exception e) {
}
}
public void readObjectByArray() throws IOException {
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(
new FileInputStream(newFile("src/testtxt/objectArrays.txt")));
Person[] persons = (Person[]) oos.readObject();
if(null != persons && persons.length > 0){
for(Person p : persons){
System.out.println(p);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
oos.close();
}
}
/**
* 通过集合写入对象
*/
private void writeObjectByList() {
try {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("src/testtxt/objectByList.txt"));
List<Person> persons=new ArrayList<Person>();
for (int i = 1; i < 10; i++) {
Person person = new Person("欧阳鹏 List[" + (20+i)+"]", 20+i);
persons.add(person);
}
//写入List
oos.writeObject(persons);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void readObjectByList(){
ObjectInputStream oos = null;
try {
oos = new ObjectInputStream(
new FileInputStream(newFile("src/testtxt/objectByList.txt")));
List<Person> persons = (List<Person>) oos.readObject();
if(null != persons && persons.size() > 0){
for(Person p : persons){
System.out.println(p);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void testWriteObject(){
writeObject();
}
@Test
public void testRead(){
readObject();
}
@Test
public void testWriteByArray(){
writeObjectByArray();
}
@Test
public void testReadObjectByArray() throws IOException {
readObjectByArray();
}
@Test
public void testWriteByList(){
writeObjectByList();
}
@Test
public void testReadObjectByList(){
readObjectByList();
}
}
6.File与RandomAccessFile
6.1RandomAccessFile
6.1.1为什么要有RandomAccessFile?
它与其他文件读写的区别在于读写的方式不一样。
6.1.2常用方法简介
(1)构造方法:RandomAccessFile raf = newRandomAccessFile(File file, String mode);
(2)其中参数 mode 的值可选 “r”:可读,“w” :可写,“rw”:可读性;
6.2RandomAccessFile的特点与优势
(1)即可以读也可以写
RandomAccessFile不属于InputStream和OutputStream类系的,它是一个完全独立的类,所有方法(绝大多数都只属于它自己)都是自己从头开始规定的,这里面包含读写两种操作
(2)可以指定位置读写
RandomAccessFile能在文件里面前后移动,在文件里移动用的seek( ),所以它的行为与其它的I/O类
有些根本性的不同。总而言之,它是一个直接继承Object的,独立的类。只有RandomAccessFile才有seek搜寻方法,而这个方法也只适用于文件.
6.2.1案例
public class RandomAccessFileTests {
private static final File file = new File("src\\testtxt\\raf.txt");
/**
* 向文件中写入内容
*/
@Test
public void testRandomAccessFileWriter() throws IOException{
//要先将已有文件删除、避免干扰。
if(file.exists()){
file.delete();
}
RandomAccessFile rsfWriter = new RandomAccessFile(file, "rw");
//不会改变文件大小、但是他会将下一个字符的写入位置标识为10000、
//也就是说此后只要写入内容、就是从10001开始存、
rsfWriter.seek(10000);
printFileLength(rsfWriter); //result: 0
//会改变文件大小、只是把文件的size改变、
//并没有改变下一个要写入的内容的位置、
//这里注释掉是为了验证上面的seek方法的说明内容
rsfWriter.setLength(10000);
System.out.println("oo");
printFileLength(rsfWriter); //result: 0
System.out.println("xx");
//每个汉子占3个字节、写入字符串的时候会有一个记录写入字符串长度的两个字节
rsfWriter.writeUTF("猪八戒背媳妇儿");
printFileLength(rsfWriter); //result: 10014
//每个字符占两个字节
rsfWriter.writeChar('a');
rsfWriter.writeChars("abcde");
printFileLength(rsfWriter); //result: 10026
//再从“文件指针”为5000的地方插一个长度为100、内容全是'a'的字符数组
//这里file长依然是10026、因为他是从“文件指针”为5000的地方覆盖后面
//的200个字节、下标并没有超过文件长度
rsfWriter.seek(5000);
char[] cbuf = new char[100];
for(int i=0; i<cbuf.length; i++){
cbuf[i] = 'a';
rsfWriter.writeChar(cbuf[i]);
}
printFileLength(rsfWriter); //result: 10026
//再从“文件指针”为1000的地方插入一个长度为100、内容全是a的字节数组
//这里file长依然是10026、因为他是从“文件指针”为5000的地方覆盖后面
//的200个字节、下标并没有超过文件长度
byte[] bbuf = new byte[100];
for (int i = 0; i < bbuf.length; i++) {
bbuf[i] = 1;
}
rsfWriter.seek(1000);
rsfWriter.writeBytes(new String(bbuf));
printFileLength(rsfWriter);
}
/**
* 从文件中读取内容
* 这里我们要清楚现在文件中有什么内容、而且还要清楚这些内容起始字节下标、长度
*
* @throws IOException
*/
@Test
public void testRandomAccessFileRead() throws IOException{
/*
* 对文件中内容简单说明:
* 1、从0到1000 为空
* 2、从1001到1100是100个1
* 3、从1101到5000是空
* 4、从5001到5200是字符'a'
* 5、从5201到10000是空
* 6、从10001到10011是字符串"陈华应"
* 7、从10012到10023是"aabcde"
*/
RandomAccessFile rsfReader = new RandomAccessFile(file, "r");
//可按照自己想读取的东西所在的位置、长度来读取
//读取"猪八戒背媳妇儿"
rsfReader.seek(10000);
System.out.println(rsfReader.readUTF());
//读取100个字符'a'
rsfReader.seek(5000);
byte[] bbuf = new byte[200];
rsfReader.read(bbuf);
System.out.println(new String(bbuf));
//读取100个1
byte[] bbuf2 = new byte[100];
rsfReader.seek(1000);
rsfReader.read(bbuf2, 0, 100);
for(byte b : bbuf2){
System.out.print(b);
}
//读取字符'aabcde'
byte[] bbuf3 = new byte[12];
rsfReader.seek(10014);
rsfReader.read(bbuf3);
System.out.println(new String(bbuf3));
}
/**
* 打印文件长度
* @param rsfWriter 指向文件的随机文件流
* @throws IOException
*/
private static void printFileLength(RandomAccessFile rsfWriter)
throws IOException {
System.out.println("file length: " + rsfWriter.length() + " file pointer: " + rsfWriter.getFilePointer());
}
}
6.2.2应用场景
(1)网络数据的断点续传
6.3NIO——FileChannel
(1)Channel是对I/O操作的封装。
(2)FileChannel配合着ByteBuffer,将读写的数据缓存到内存中,然后以批量/缓存的方式read/write,省去了非批量操作时的重复中间操作,操纵大文件时可以显著提高效率(和Stream以byte数组方式有什么区别?经过测试,效率上几乎无区别)。
public class FileChannelTest {
@Test
public void testCopyFileByStream() {
File sourceFile = new File("F://01_人生智慧视频//test.mp4");
File targetFile = new File("D://target.mp4");
if(targetFile.exists()){
targetFile.delete();
}
try {
targetFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
//1.字节流读写
copyFileByStream(sourceFile, targetFile);
}
/**
* NIO方式读写
*/
@Test
public void testCopyFileByFileChannel(){
File sourceFile = new File("F://01_人生智慧视频//test.mp4");
File targetFile = new File("D://target.mp4");
if(targetFile.exists()){
targetFile.delete();
}
try {
targetFile.createNewFile();
} catch (Exception e) {
e.printStackTrace();
}
//1.NIO读写,速度要高出很多,特别是读写文件很大的时候
copyFileByFileChannel(sourceFile, targetFile);
}
private void copyFileByFileChannel(File sourceFile,File targetFile){
Instant begin = Instant.now();
RandomAccessFile randomAccessSourceFile;
RandomAccessFile randomAccessTargetFile;
try {
randomAccessSourceFile = new RandomAccessFile(sourceFile, "r");
randomAccessTargetFile = new RandomAccessFile(targetFile, "rw");
} catch (Exception e) {
e.printStackTrace();
return;
}
FileChannel sourceFileChannel = randomAccessSourceFile.getChannel();
FileChannel targetFileChannel = randomAccessTargetFile.getChannel();
ByteBuffer byteBuffer = ByteBuffer.allocate(1024*1024);
try {
while(sourceFileChannel.read(byteBuffer) != -1) {
byteBuffer.flip();
targetFileChannel.write(byteBuffer);
byteBuffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
sourceFileChannel.close();
} catch (Exception e2) {
e2.printStackTrace();
}
try {
targetFileChannel.close();
}catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("total spent: " + Duration.between(begin, Instant.now()).toMillis());
}
private void copyFileByStream(File sourceFile,File targetFile) {
Instant begin = Instant.now();
FileInputStream fis;
FileOutputStream fos;
try {
fis = new FileInputStream(sourceFile);
fos = new FileOutputStream(targetFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
byte[] readed = new byte[1024*1024];
try {
while (fis.read(readed) != -1) {
fos.write(readed);
}
fos.flush();
} catch( IOException e){
e.printStackTrace();
} finally {
try{
fos.close();
}catch (Exception e) {
e.printStackTrace();
}
try {
fis.close();
} catch (Exception e2) {
e2.printStackTrace();
}
}
System.out.println("total spent: " + Duration
.between(begin, Instant.now()).toMillis());
}
}
6.3.1为什么NIO要比使用字节流要快?
(1)因为它的底层使用了管道技术。
(2)大文件操作的时候使用。
7.打赏鼓励
感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!