【30】Java IO在Android中应用基础篇

(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.打赏鼓励

感谢您的细心阅读,您的鼓励是我写作的不竭动力!!!

7.1微信打赏

在这里插入图片描述

7.2支付宝打赏

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
城市应急指挥系统是智慧城市建设的重要组成部分,旨在提高城市对突发事件的预防和处置能力。系统背景源于自然灾害和事故灾难频发,如汶川地震和日本大地震等,这些事件造成了巨大的人员伤亡和财产损失。随着城市化进程的加快,应急信息化建设面临信息资源分散、管理标准不统一等问题,需要通过统筹管理和技术创新来解决。 系统的设计思路是通过先进的技术手段,如物联网、射频识别、卫星定位等,构建一个具有强大信息感知和通信能力的网络和平台。这将促进不同部门和层次之间的信息共享、交流和整合,提高城市资源的利用效率,满足城市对各种信息的获取和使用需求。在“十二五”期间,应急信息化工作将依托这些技术,实现动态监控、风险管理、预警以及统一指挥调度。 应急指挥系统的建设目标是实现快速有效的应对各种突发事件,保障人民生命财产安全,减少社会危害和经济损失。系统将包括预测预警、模拟演练、辅助决策、态势分析等功能,以及应急值守、预案管理、GIS应用等基本应用。此外,还包括支撑平台的建设,如接警心、视频会议、统一通信等基础设施。 系统的实施将涉及到应急网络建设、应急指挥、视频监控、卫星通信等多个方面。通过高度集成的系统,建立统一的信息接收和处理平台,实现多渠道接入和融合指挥调度。此外,还包括应急指挥基础平台建设、固定和移动应急指挥通信系统建设,以及应急队伍建设,确保能够迅速响应并有效处置各类突发事件。 项目的意义在于,它不仅是提升灾害监测预报水平和预警能力的重要科技支撑,也是实现预防和减轻重大灾害和事故损失的关键。通过实施城市应急指挥系统,可以加强社会管理和公共服务,构建和谐社会,为打造平安城市提供坚实的基础
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值