精华内容
下载资源
问答
  • 什么是流?C++流类和流对象

    千次阅读 2019-01-15 13:34:45
    程序中常用的 cin 和 cout,分别用于从...数据像水一样从一个地方流动到另一个地方,因此,在 C++ 中将此过程称为 “(stream)”。 在 C++ 的标准类库中,将用于进行数据输入输出的类统称为“类”。cin ...

    程序中常用的 cin 和 cout,分别用于从键盘输入数据和向屏幕输出数据(简称为标准 I/O)。除此之外,程序还可以从文件中读入数据,以及向文件中写入数据(简称为文件 I/O)。

    数据输入和输出的过程也是数据传输的过程。数据像水一样从一个地方流动到另一个地方,因此,在 C++ 中将此过程称为 “流(stream)”。

    在 C++ 的标准类库中,将用于进行数据输入输出的类统称为“流类”。cin 是流类 istream 的对象,cout 是流类 ostream 的对象。要使用流类,需要在程序中包含 iostream 头文件。

    C++ 中常用的几个流类及其相互关系如图1所示。

    图1中的箭头代表派生关系。例如,ios 是抽象的基类,它派生出 istream 和 ostream。 istream 和 ostream 又共同派生了 iostream 类。

    为了避免多继承的二义性,从 ios 派生出 istream 和 ostream 时,均使用了 virtual 关键字(虚继承)。

    • istream 是用于输入的流类,cin 就是该类的对象。
    • ostream 是用于输出的流类,cout 就是该类的对象。
    • ifstream 是用于从文件读取数据的类。
    • ofstream 是用于向文件写入数据的类。
    • iostream 是既能用于输入,又能用于输出的类。
    • fstream 是既能从文件读取数据,又能向文件写入数据的类。

    标准流对象

    iostream 头文件中定义了四个标准流对象,它们是 cin、cout、cerr 和 clog。

    • cin 对应于标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据。
    • cout 对应于标准输出流,用于向屏幕输出数据,也可以被重定向为向文件写入数据。
    • cerr 对应于标准错误输出流,用于向屏幕输出出错信息,不能被重定向。
    • clog 对应于标准错误输出流,用于向屏幕输出出错信息,不能被重定向。


    cerr 和 clog的区别在于:cerr 不使用缓冲区,直接向显示器输出信息;而输出到 clog 中的信息会先被存放到缓冲区,缓冲区满或者刷新时才输出到屏幕。

    cout 是 ostream 类的对象。在 Visual Studio 2010 安装文件夹中有vc\crt\src\cout.cpp文件,该文件中 cout 的定义如下:

    _PURE_APPDOMAIN_GLOBAL static filebuf fout(_cpp_stdout);
    _PURE_APPDOMAIN_GLOBAL extern _CRTDATA2 ostream cout (&fout);

    简单地看,就是:

    ostream cout(&fout);

     

    ostream 类的无参构造函数和复制构造函数都是私有的,因此在程序中一般无法定义 ostream 类的对象,唯一能用的 ostream 类的对象就是 cout。

    当然,上面关于 cout 对象的定义语句说明 ostream 类是有一个公有构造函数的,如果知道这个构造函数是什么样的,那么也能自己定义 ostream 类的对象——但这么做并无必要。

    cout 可以被重定向,而 cerr 不能。所谓重定向,就是将输入的源或输出的目的地改变。例如,cout 本来是输出到屏幕上的,但是经过重定向,本该输出到屏幕上的东西就可以被输出到文件中。

    例如下面的程序:

    #include <iostream>
    using namespace std;
    int main()
    {
        int x,y;
        cin >> x >> y;
        freopen("test.txt", "w", stdout);  //将标准输出重定向到 test.txt文件
        if( y == 0 )  //除数为0则输出错误信息
            cerr << "error." << endl;
        else
            cout << x /y ;
        return 0;
    }

    第 7 行的 freopen 是一个标准库函数,第二个参数 w 代表写模式,第三个参数代表标准输出。该语句的作用是将标准输出重定向为 test.txt 文件。

    重定向之后,所有对 cout 的输出都不再出现在屏幕上,而是出现在 test.txt 文件中。

    test.txt 文件会和本程序的可执行文件出现在同一个文件夹中。重定向仅对本程序有效,不影响其他程序。

    运行本程序,输入
    6 2↙
    程序没有输出,但是打开 test.txt文件,可以看到文件中有
    3

    如果输入
    4 0↙
    则程序在屏幕上输出
    error.

    说明 cerr 不会被重定向。

    cin 也是可以被重定向的。如果在程序中加入

    freopen("input.dat", "r", stdin);

    第二个参数 r 代表读入方式,第三个参数 stdin 代表标准输入。执行此语句后,cin 就不再从键盘读入数据,而是从 input.dat 文件中读人数据,input.dat 文件中有什么,就相当于从键盘输入了什么。 

    展开全文
  • 1.File类型:用于表示一个文件或者文件夹的路径的对象(抽象路径名) 2.路径:用于描述文件或者文件夹的所在路径的所在的字符串 3.路径分类:绝对路径和相对路径 4.绝对路径:从跟目录开始的路径,称为绝对路径,在...

    File文件,字节输入流,字节输入流,字符输入流,字节输出流的详解

    File文件概述
    1.File类型:用于表示一个文件或者是文件夹的路径的对象(抽象路径名)
    2.路径:用于描述文件或者是文件夹的所在路径的所在的字符串
    3.路径分类:绝对路径和相对路径
    4.绝对路径:从跟目录开始的路径,称为绝对路径,在window中盘符路径就是跟目录,在Linu目录中从根目录开始的路径就是绝对路径
    5.相对路径:相对于某个路径而言的路径,相对于不同的路径,同样的相对路径,表达的是不同的路径
    File文件的构造方法:
    1.File(String path) 把字符的路径,封装成一个File对象
    2.File(String parent,String child) 将父级路径和子级路径封装成File对象,其实就是描述的就是父级路径和子级路径封装的一个路经
    3.File(File parent,String child) 将父级File对象和字级路径封装成一个File对象,其实就是在描述父级路径和资级路径封装的路径

    public class FileDemo01 {
         public static void main(String[] args) {
        	 //将一个字符串串封装成一个file文件对象
    	     File file = new File("x");
    	     System.out.println(file);
    	     
    	     //将一个父级路径和子级路径封装成一个file文件,其实 就是描述的是父级和子级拼接后的路径
    	     File file2 = new File("x/y","z");
    	     System.out.println(file2);
    	     
    	     //将父级File对象和字节路径封装成一个file对象,其实就是父级路径和子级路径的拼接后的路径
    	     File file3 = new File("x/y/z");
    	     file3 = new File("x/y/z","aaa.txt"); 
    	     System.out.println(file3);
    	     
    	 }
    }
    

    File类型的创建方法和删除方法
    1.boolean createNewFile() 创建当前的File对象所描述的路径的文件
    2.boolean mkdir() 创建当前对象的所描述的路径的文件夹(如果父级路径不存在,那么就会自动创建父级路径)
    3.boolean mkirs() 创建当前的File对象所描述的路径的文件夹
    4.delete():删除调用者所描述的文件或者文件夹
    备注:delete在删除文件夹的时候,只能删除空的文件夹,delete不能走回收站

           //创建一个文件
    		File file = new File("x/y/a.txt");
    		file.createNewFile();
    		//创建一个文件夹
    		File nFile = new File("k");
    		nFile.mkdir();
    		//创建多级文键夹
    		File nFile2 =new File("a/b/c/n");
    		nFile2.mkdirs();
    		//删除
    		nFile.delete();
    

    File类型的重名功能
    1.renameTo(File dest)
    调用者是当前的文件或者文件夹的路径对象
    参数列表是变化后的文件或者是文件夹的路径对象
    2.注意事项:
    如果在同一个文件夹下,修改路径就是 重命名
    如果不在同一个文件夹下,修改路径就是剪切

          //重命名方法,实现数据的重名称,如果在不同的目录下相同的文件就是剪切
    	   File file = new File("x/y/a.txt");
    	   File file2 = new File("a/b/c/d/a.txt");
    	   file.renameTo(file2);
    	   //调用者是当前的文件夹或者是目录,被调用者是变化之后的文件夹或者路径对象,如果在相同的目录下就是重命名
    	   File file3 = new File("a/b/c/d/f.txt");
    	   file2.renameTo(file3);
    

    File文件的判断功能和获取功能
    1.exists();判断当前调用者File文件,是否存在
    2.isFile();判断当前调用者是否是文件
    3.isDiretory():判断当前文件是不是文件夹
    4.getAbsolutepath():获取当前File对象的绝对路径
    5.getPath():获取的就是在构造方法中封装的路径
    6.String[] String:获取当前文件夹中的所有的文件和文件夹的名称,到数组中
    7.File[] listFiles():获取当前文件夹的所有的文件和文件夹的File对象在File对象数组中

    File file = new File("a");
    System.out.println(file.exists());       //判断文件是否存在
    System.out.println(file.isFile());       //判断当前调用者是不是文件
    System.out.println(file.isDirectory());  //判读当前的调用者是不是文件夹
    //获取最底层的文件的名称
    File file = new File("a/b/c/d/f.txt");
    //打印构造方法的路径
    System.out.println(file.getName());
    //打印文件的路径
    System.out.println(file.getParent());
    //打印文件的绝对路径
    System.out.println(file.getAbsolutePath());
    

    通过控制台输入一个字符串,判断是否是指定的文件夹下,所有的大于20M的以.wmv的文件的绝对路径?

    package cn.ujiuye.file;
    import java.io.File;
    import java.util.Scanner;
    /**
     * @author liugang
     *
     */
    public class FileTest {
    	public static void main(String[] args) {
    		@SuppressWarnings("resource")
    		Scanner sc = new Scanner(System.in);
    		while (true) {
    			System.out.println("请输入你要查询的路径:");
    			String src = sc.next();
    			if (src.equals("d:/aaa")) {
    				File file = new File(src);
    				File[] listFiles = file.listFiles();
    				//判断该文件夹下所有的大于.20M的所有的文件的绝对路径
    				if (listFiles != null) {
    					for (File file2 : listFiles) {
    						if (file2.isFile() &&file2.getName().endsWith(".wmv") &&file.length() > 20 * 1024 * 1024) {
    							System.out.println(file2.getAbsolutePath());
    						}
    					}
    					break;
    				}
    			} else {
    				System.out.println("您当前输入的路径不对,请重新输入");
    			}
    		}
    
    	}
    }
    
    

    IO概述
    站在内存的角度上,从其他的设备进入内存的,都是输入,从内存到其他的设备的都是输出,I/O就是用于设备之间的进行传递的数据交互的对象的所属的类型。
    字节流
    可以直接操作字节信息的流对象,根据流对象,可以分成字节输入流和字节输出流,顶层父类分别是:InputStream和OuputStream

    InputStream
    1.字节输入流的顶层父类
    2.常用的方法:
    int read(): 从当前的字节流获取一个字节
    int read(byte[] arr):将arr.length个字节,读取到arr中
    InputStream是一个抽象类,不能直接创建对象,只能由子类创建对象
    read():一次读取一个字节,返回值类型是int类型,原因是要把返回的字节的前面加上24个0.无论读取到的是负数还是整数,都会是变成整数,只要是从文件中读取的数据,都是整数,如果返回值是-1,说明不是从文件中读取的数据,而是专门为方法准备的文件末尾的标记,说明:虽然每次都调用了该方法,但是返回的却不同,因为文件的指针不断的向后移。

           //创建字节输入流对象,将输入流从磁盘的文件中读取到计算机的内存中
    		FileInputStream fis = new FileInputStream("a.txt");
    		//读取的字节
    		int ins;
    		while((ins = fis.read())!=-1) {
    			System.out.println((char)ins);
    		}
    		//关闭流
    		fis.close();
    
     public class FileInPutStreamDemo03 {
    	public static void main(String[] args) throws IOException {
    		//创建字节输入流对象,将输入流从磁盘的文件中读取到计算机的内存中
    		FileInputStream fis = new FileInputStream("a.txt");
    		byte[] arr = new byte[2];
    		//显然将你读取到的数据写到文件中去
    		int len =fis.read(arr);
    		System.out.println(Arrays.toString(arr) + ">>>" +new String(arr,0,len)+">>>"+len);
    		
    		len =fis.read(arr);
    		System.out.println(Arrays.toString(arr) + ">>>" +new String(arr,0,len)+">>>"+len);
    		
    		fis.close();
    	}
    }
    

    OutputStrea字节输出流
    1.字节输出流的顶层父类
    2.常用方法:
    write(int b) :将一个字节信息写到指定的设备中
    write(byte[] arr):将一个字节的所有的信息,写到指定的设备中
    write(byte[] arr,int offsert,int len):将一个字节数组从arr中的offert索引开始,共len字节写到指定的设备中
    3.字节输出流
    FileOutputStream(File f) 将f的描述的路径封装成字节输出流对象
    FileOutputStream(String path):将path描述的文件路径封装成字节输出流对象,使用字节输出流写入数据,关联到文件中

    package cn.ujiuye.inputOut;
    
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    /**
     * @author liugang
     *
     */
    public class FileOutStreamDemo06 {
        public static void main(String[] args) throws IOException {
        	//创建一个文件输出流对象
    		FileOutputStream fis = new FileOutputStream("y.txt");
    		//声明一个数组
    		byte[] arr = {100,101,102};
    		//fis.write(arr);
    		//将数组指定的元素填到指定的位置
    		fis.write(arr,0,2);
    		fis.close();
    	}
    }
    
    package cn.ujiuye.inputOut;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    /**
     * @author liugang
        *    一个一个的拷贝
     */
    public class FileOutStreamDemo05 {
        public static void main(String[] args) throws IOException {
        	//创建一个文件输入流对象
        	FileInputStream fis = new FileInputStream("y.txt");
        	//创建一个文件输出流对象
    		FileOutputStream fos = new FileOutputStream("y.copy.txt");
    		int read;
    		while((read = fis.read())!=-1){
    			fos.write(read);
    		}
    		//关闭字节
    		fos.close();
    		fis.close();
    		
    	}
    }
    
    

    高效缓存流
    1.BufferedInputStream和BufferOutputStream
    2.是包装类型:本身不具备读写的功能,只是在具体的流对象的基础上,对其进行加强,例如FileInputStream和FileOutputStream,原本的效率较低,加强之后,就效率较高。

    package cn.ujiuye.inputOut;
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    /**
     * @author liugang
        *    一个一个的拷贝
     */
    public class BufferedOutStreamInputStream {
        public static void main(String[] args) throws IOException {
        	
        	long start = System.currentTimeMillis();
        	//创建一个文件输入流对象
        	FileInputStream fis = new FileInputStream("aa.avi");
        	//创建一个文件输出流对象
    		FileOutputStream fos = new FileOutputStream("bb.avi");
    		//加强版的输入流和输出流  高效缓存流
    		BufferedInputStream in = new BufferedInputStream(fis);
    		BufferedOutputStream out =  new BufferedOutputStream(fos);
    		//从文件中读取数据
    		int read;
    		while((read = in.read())!=-1) {
    			//把数据从内存中写到文件中去
    			out.write(read);
    		}
    		//关闭字节
    		in.close();
    		out.close();
    		long end = System.currentTimeMillis();
    		System.out.println(end - start);
    	}
    }
    
    

    字符流
    使用字符流处理字符的问题:
    1.使用字节流写字符
    可以使用,但是要先把字符串转化成字节数组,再储存在文件中,比较麻烦
    2,使用字节流读取字符
    如果是纯文本可以一次读取一个字节
    如果是存中文,可以一次读取两个字节(GBK)
    如果是中英文混砸,每次不知道读取多少字节,因此无论字节数组准备多大都会出现乱码
    解决方法:
    在GBK编码中,如果是一个英文,那么读取的字节是正数,如果读取的是正数,那么就可以断定是英文字符,就读取一个字节转化为字符即可。
    在GBK编码,如果是一个中文,那么就一定读取的是第一个字节是负数,如果读取的是一个负数,就说明读取到的就是一个中文,两个字节一起转化为字符。
    字符流的使用
    1.顶级顶层父类:Reader Writer
    2.常用方法:
    Reader:
    read():读取一个字符,返回值如果是-1,表达到达文件的末尾
    read(char[] arr):将一堆字符储存在一个字符数组中
    Writer:
    writer(int c):写出一个字符
    write(String str):写出一个字符串
    write(将一个字符数组的所有的内容写出)
    write(char[] arr,int offset,int len):将字符数组的一部分写到目标中
    3.抽象类不能直接创建子类。需要具体的子类来创建
    4.使用FileReader和FileWriter可以作为创建对象的类型

    public class FileReaderDemo01 {
        public static void main(String[] args) throws IOException {
    		//加载字符输入流对象
        	FileReader reader = new FileReader("a.txt");
    		//循环遍历,实现数据的读取操作,每次内部会根据其数据的特点会分配空间
        	int b;
    		while((b = reader.read()) != -1) {
    			System.out.println(b + "::" +(char)b);
    		}
    		reader.close();
    	}
    
    public class WriterDemo02 {
        public static void main(String[] args) throws IOException {
    		//字符输出流
        	FileWriter wr = new FileWriter("a.txt",true);
    		//直接写入你想写入的对象
        	wr.write("你好你好呀");
    		wr.write("谢女士,请问你还好吗?");
    		wr.write("加油");
    		wr.write("love");
    		wr.close();
    	}
    }
    
    public class WriterDemo03 {
        public static void main(String[] args) throws IOException {
    		//字符输入流
        	FileReader fr = new FileReader("a.txt");
        	//字符输出流
        	FileWriter wr = new FileWriter("a_copy.txt");
        	
        	//循环遍历数据实现复制操作
        	int b;
        	while((b = fr.read())!= -1) {
        		wr.write(b);
        	}
        	//关闭流对象
        	fr.close();
        	wr.close();
    	
    	}
    }
    

    字符流的拷贝
    1.使字符输入流读取信息,使用的字符流出流写出信息,完成文件的使用字符流拷贝
    2.字符流拷贝的必要性:
    没有必要使用字符流来进行拷贝,因为字符流会先将字节信息转化为字符,读取到内存中,最后还有把字符信息转化为字节信息,写到另外的一个文件中,中间做了两个没有意义的相反的操作,浪费了时间.
    应用场景:
    1.如果是在读取到字符以后,需要人为的阅读和修改这个字符,那么就使用字符流
    2.如果只是简单的将信息进行转移或者是拷贝,就不需要转成字符了
    在这里插入图片描述

    public class FileReaderDemo03 {
        public static void main(String[] args) throws IOException {
    		//创建字符输入流和字节输出流
        	FileReader fr = new FileReader("a.txt");
    		FileWriter fw = new FileWriter("a_capy1.txt");
    		//创建数组,一次读入一组字符,加快读的效率
    		char[] chs = new char[1024*8];
    		int b;
    		while((b = fr.read(chs))!=-1) {
    			fw.write(chs,0,b);
    		}
    		fr.close();
    		fw.close();
    	}
    }
    
    
    

    字符流不能操作非纯文本文件:因为当字符流读取到一个字节的时候,需要查询编码表是不是非纯文本,如果是,就有可能读取的字符无法转化成对应的字符,因为这个字节信息在编码表中没有对应的字符,就只能使用英文的?来代替,这一步就是对内容进行篡改,字符信息,后面再转化就不可能正确了.

    高效缓存字符流和高效缓存字节流基本上类似,就不多介绍了,下面举个例题来介绍一下:将文件夹中的第一行转化成最后一行,第二行转化成倒数第二行?

    package cn.ujiuye.writerreader;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * @author liugang
     *
     */
    public class BufferReadWriterTest {
        public static void main(String[] args) throws IOException {
        	//定义一个缓存字符输入流
    		BufferedReader br = new BufferedReader(new FileReader("x.txt"));
    		//定义一个集合
    		List<String> list = new ArrayList<String>();
    		//集合遍历
    		String line;
    		while((line = br.readLine())!=null) { //一行一行的读入数据,便于反转时读出方便
    			list.add(line);
    		}
    		br.close();
    		//定义一个字符输出流
    		BufferedWriter bw = new BufferedWriter(new FileWriter("x_copyfan.txt"));
    		//遍历集合倒序输出
    		for(int i = list.size()-1;i >= 0;i--) {
    			bw.write(list.get(i));
    			bw.newLine();              //换行操作
    		}
    		bw.close();
    	}
    }
    
    
    展开全文
  • 什么是事件? ans:事件:描述从页面中接收事件的顺序 (1) 事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点 (2) 事件捕获:不太具体的节点先接收事件,而具体的节点最后接收到事件...
    1. 什么是事件流?
      ans:事件流:描述从页面中接收事件的顺序
      (1) 事件冒泡:事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的节点
      (2) 事件捕获:不太具体的节点先接收事件,而具体的节点最后接收到事件
      (3) “DOM2级事件”:规定事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

    2. 事件“捕获”和“冒泡”执行次数和事件的执行顺序

    ans:按照DOM2级事件
    (1) 事件执行次数:元素绑定多少个事件,就执行多少次。前提是:

    • 事件确实被触发
    • 事件绑定几次就算几个事件,就算类型和功能完全一样也不会被覆盖

    (2) 事件执行顺序:关键是判断是否为目标元素

    • 非目标元素:根据W3C的标准执行:捕获->目标元素->冒泡(不依据事件绑定顺序)
    • 目标元素:依据事件绑定顺序:先绑定的事件先执行(不依据捕获冒泡标准)
    • 最终顺序:父元素捕获->目标元素事件1->目标元素事件2->子元素捕获->子元素冒泡->父元素冒泡
    • 子元素事件执行前提是事件确实“落”到子元素布局区域上,而不是简单的具有嵌套关系
    1. 事件模型
      ans:即事件处理程序。事件就是用户或浏览器自身执行的某种动作,而响应某个事件的函数就叫做事件处理程序(或事件监听器)。浏览器的事件模型,就是 通过监听函数对事件作出反应。

    (1) HTML事件处理程序:HTML的 on- 属性

    <input type="button" value="Click Me" onclick="doSomething()">
    

    元素的事件监听属性,都是on+事件名,例如onload, onclick。使用这个方法指定的监听代码,只会在冒泡阶段触发。
    缺点:HTML代码和JavaScript代码高度耦合,若要更换事件处理程序,则要同时改动HTML代码和JavaScript代码。另外,若用户在HTML元素一出现在页面上就触发相应事件,而此时事件处理程序若不具备执行条件(例如函数还没被解析出来),就会出现错误。

    (2) DOM0级事件
    将一个函数赋值给事件处理程序 属性,见代码:

    var btn = document.getElementById("myBtn");
    btn.onclick = function() {
        console.log("Clicked");
    }
    

    用这种方式指定的监听函数,同样只会在冒泡阶段触发。
    缺点:同一个事件只能定义一个监听函数,如果定义两次onclick属性,后面的会覆盖前面的。

    (3)DOM2级事件处理程序
    “DOM2级事件”定义了两个方法:addEventListener和 removeEventListener,所有的DOM节点都包含这两个方法,它们都接收三个参数:
    addEventListener(要处理的事件名,作为事件处理程序的函数,布尔值)
    布尔值:true: 在捕获阶段调用事件处理程序;false:在冒泡阶段调用
    见代码:

    var btn = document.getElementById("myBtn");
    btn.addEventListener("click", function() {
        console.log(this.id);
    }, false);
    btn.addEventListener("click", function() {
        console.log("hello world!");
    }, false);
    
    

    通过addEventListener()添加的事件处理程序只能通过removeEventListener()来移除,三个参数必须完全相同,所以添加的匿名函数无法删除

    优点:

    • 同一个事件可以添加多个监听函数。
    • 能够指定在哪个阶段(捕获阶段还是冒泡阶段)触发监听函数。
    • 除了 DOM 节点,其他对象(比如window、XMLHttpRequest等)也有这个接口,它等于是整个 JavaScript 统一的监听函数接口。
    1. 什么是事件代理?
      ans:由于事件会在冒泡阶段从子节点传递到父节点,所以可以通过将子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件。此即为事件代理。

    2. 什么是事件对象?
      ans:在触发DOM上的某个元素时,会产生一个事件对象event,作为参数传给监听函数。里面包含着所有与事件有关的信息,包括导致事件的元素、事件的类型等。例如鼠标操作导致的事件中,会包含鼠标位置的信息。浏览器原生提供一个Event对象,所有的事件都是这个对象的实例,或者说继承了Event.prototype对象。Event对象本身就是一个构造函数,可以用来生成新的实例。

    event = new Event(type, options);
    

    第一个参数type是字符串,表示事件的名称;第二个参数options是一个对象,表示事件对象的配置。该对象主要有下面两个属性。

    • bubbles:布尔值,可选,默认为false,表示事件对象是否冒泡。
    • cancelable:布尔值,可选,默认为false,表示事件是否可以被取消,即能否用Event.preventDefault()取消这个事件。
    1. addEventListener() 和attachEvent()的区别?
      ans:attachEvent()和detachEvent()为IE事件处理程序中定义的两个方法。
      attachEvent()的特点:
    • attachEvent()和detachEvent()接收两个参数:attachEvent(事件处理程序名称,事件处理程序函数)
    var btn = document.getElementById("myBtn");
    btn.attachEvent("onclick", function() {       // 注意第一个参数时“onclick”,和 addEventListener() 中的“click”有所区别
        console.log("Clicked");
    })
    
    • 通过attachEvent()添加的事件处理程序都会被添加到冒泡阶段
    • 和addEventListener() 一样,attachEvent()可以为一个元素添加多个事件处理程序,通过detachEvent()移除,同样需要每个参数保持一致,所以匿名函数也没法移除。
    • attachEvent(),事件处理程序在全局作用域中运行,即this === window;而DOM0级事件处理程序中,程序中的this指向当前元素,即事件处理程序在元素的作用域中运行。
    • 与DOM方法不同,通过attachEvent()添加的事件处理程序,以跟添加顺序相反的顺序被触发。以下代码,先看到"hello world!",再看到"Clicked"
    var btn = document.getElementById("myBtn");
    btn.attachEvent("onclick", function() {
        console.log("Clicked");
    }) 
    btn.attachEvent("onclick", function() {
        console.log("hello world!")
    })
    
    

    总结

    • addEventListener() 传递三个参数,attachEvent()传递两个参数,且attachEvent()传递的事件名前面必须加 on-
    • addEventListener() 先绑定先触发,attachEvent()先绑定后触发
    • addEventListener() 添加的事件处理程序在元素的作用域中运行,attachEvent()添加的事件处理程序在全局作用域中运行
    • addEventListener() 添加的事件处理程序可以选择添加到捕获或冒泡阶段,attachEvent()添加的事件处理程序只被添加到冒泡阶段
    1. 如何定义跨浏览器的事件处理程序?
      ans:要保证处理事件的代码能在大多数浏览器上一致的运行,只用关注冒泡阶段
      代码如下:
    var EventUtil = {
        addHandler: function(element, type, handler) {
            if (element.addEventListener) {
                element.addEventListener(type, handler, false);
            } else if (element.attachEvent) {
                element.attachEvent("on" + type, handler);
            } else {
                element["on" + type] = handler;
            }
        },
        removeHandler: function(element, type, handler) {
            if (element.removeEventListener) {
                element.removeEventListener(type, handler, false);
            } else if (element.detachEvent) {
                element.detachEvent("on" + type, handler);
            } else {
                element["on" + type] = null;
            }
        }
    }
    
    var btn = document.getElementById("myBtn");
    var handler = function() {
        console.log("Clicked");
    }
    EventUtil.addHandler(btn, "click", handler);
    EventUtil.removeHandler(btn, "click", handler);
    

    先检测传入的元素中是否存在DOM2级方法,若存在的时IE的方法,则采取第二种方案,最后一种即采用DOM0级方案。

    展开全文
  • JAVA SE自学 基础篇 IO基础什么是IOjava.io.File字节过滤 目标 IO的概念 java.io.file类 字节 过滤 对象流 对象序列化与反序列化 对象克隆 什么是IO 不同介质之间的数据传输其实就是IO I ( input ),...


    目标

    • IO的概念
    • java.io.file类
    • 字节流
    • 过滤流
    • 对象流
    • 对象序列化与反序列化
    • 对象克隆

    什么是IO

    不同介质之间的数据传输其实就是IO

    • I ( input ),输入,也称为读
    • O( output ),输入,也称为写

    常见的IO发生于:

    • 程序 ---- 磁盘
    • 程序 ---- 程序
    • 程序 ---- 内存区
    • 本机程序 ---- 其他机器上的程序
    • 本机程序 ---- 本机的其他程序

    那如何区分是入还是出? 站在程序自身的角度来分析问题.

    java.io.File

    file 类是对文件系统中文件(file)和 目录(directory)的抽象目录也称为文件夹(folder)

    如何知道一个File示例映射到一个物理文件还是物理目录?

    • isFile():boolean
    • isdirectory():boolean

    那如何创建一个File实例?

    File f = new File"地址";
    

    如何判断一个文件或者目录是否存在?

    f.excits()
    

    如何在磁盘上创建一个不存在的文件呢?

     f.createNewFile()
    

    如何在磁盘上创建一个不存在的目录呢?

    f.mkdir()
    

    如何在磁盘上创建多级目录呢?

    f.mkdirs()
    

    如何删除磁盘上的文件或目录呢?

    f.delete()
    

    如何获取文件长度(字节数)?

     f.length(): long
    

    如何获取父级和子级?

    f.getParent() : String 
    f.getParentFile() : File 
    f.list() : String[] 
    f.listFiles() : File[]
    

    要注意的是,File类并不提供读/写文件内容的API, 要进行内容读写, 要用到流( Stream ).

    字节流

    流 ( Stream ), 就像两个端点之间的管道一样, 数据通过这个管道进行传输. 管道中流动的是bytes, 所以本质上来讲, 所有的流都基于字节传输. 这称为字节流. 从方向上来说, 可分为输入流( Input Stream )和输出流 ( Output Stream ).

    在java.io包中, 字节输入流和输出流的抽象父类分别是:

    • inputStream
      • read():int // 读一个字节(0-255),如果达到流的尾部返回-1。
      • read(byte[] b):int // b作为buffer,最多读取b.length个字节,返回实际读到的字节数,如果到达流的尾部返回- 1。
      • read(byte[] ,int offset,int len):int //最多读len个字节,装b中(从offset开始),返回值的含义同上
    • OutputSteam
      • write(int)//写一个字节到流中
      • write(byte[ ] b)//写b.length个字节写到流中
      • write(byte[ ] b,int offset,int len )// 把b中从offset开始的len个字节写到流中
      • flush()//清空缓冲区

    在IO操作过程中,可能产生FileNotFoundException和IOexception,前者继承后者,还有产生EOFException,表示倒了流的末尾

    过滤流

    过滤流用于对基础流进行功能增强, 例如:

    • BufferedInputStream继承了FilterInputStream, 它自带8192字节的缓 冲区, 目的是减少磁盘IO, 提高性能.
    • DataInputStream继承了FilterInputStream, 它支持readInt(), readDouble()…等读取流数据的方式.

    • 所有的过滤器都是对基础流的包装, 它们都是这样创建的:
    BufferedInputStream bis = new BufferedInputStream(基础流);
    

    对象流与对象序列化

    ObjectOutputStream和ObjectInputStream称为对象流, 它们提供如下方法:

    • writeObject(obj)
    • readObject(): Object

    如何创建对象流?

    //我要读文件
    FileInputStream fis = new FileInputStream"C:\\dog.dat";
    //包装成对象
    ObjectInputStream ois = new ObjectInputStream( fis ); 
    

    把对象以byte[ ]的形式写入流中,称为序列化(Serialization)
    反正,把流中的byte[ ]读取出来,还原为对象,称之为反序列化(DeSeriable)

    序列化与反序列化常用于对象缓存,对象克隆,网络中的对象传输. . .

    注意事项:

    1. 要进行序列化的对象所属的类必须实现Serializable接口, 否则抛出NotSerializableException
    2. 反序化时, 必须保证本地class的SerialVersionUID和流中的SerialVersionUID一致, 否则抛出 InvalidClassException
    3. 序列化一个对象时, 它的所有属性都要可序列化, 除非添加了transient关键字 ( 序列化过程会忽略transient成 员 )

    对象克隆

    克隆的应用场景: 有时候, A把一个对象传递给B, 但A不希望B的修改影响这个对象, 所以A把对象克隆一个, 再传给B, B的修 改就无法影响到A手中持有的原始对象.

    克隆有两种:

    • 浅克隆: 实现标记接口Cloneable, 重写Object.clone()
    • 深克隆:
      • 方式一: 手工重写Object.clone(), 逐个COPY对象的属性
      • 方式二: 使用ByteArrayOutputStreamObjectOutputStream序列化到byte[], 再使用 ByteArrayInputStreamObjectInputStream反序列化

    浅克隆:

    在这里插入图片描述

    利用序列化实现深克隆:

    在这里插入图片描述

    字符流

    很多时候, 介质间传输的是文本消息, 这种情况下, 以byte为单位对流进行读写非常不便, 所以我们需要以char为单位进行读 写的流, 这种流称为字符流.
    字符流的抽象类是:

    • Read
    • Write

    常见的Reader有:

    • InputStreamReader:称之为转换流,它是字节利用桐乡字符流的桥梁
    • BuferedReader:缓冲字符流,它自带8K缓冲区,他包装一个Reader,提供更好的性能。
    • FileReader:读文本文件的便捷类,它使用平台默认的charset,不能更改。
    • StringReader:为String提供流式操作
    展开全文
  • 1… 什么是对象输入输出? 如果希望将Java对象写入到IO中,或从IO中读取Java对象,则要使用对象输入输出,称为对象的序列化和反序列化 ObjectInputStream 对象输入:用来读取对象,即反序列化 ...
  • 什么是面向对象,以及什么是类和对象 ​ 1.1面向过程与面向对象的区别 ​ 面向对象是一种现在最为流行的程序设计方法 。将面向过程与面向对象进行比较。 ​ 首先这两个种都是一种编程思维, 在一些简单的动作...
  • 4:文件流对象 一:c语言的输入与输出 C语言中用到最频繁的输入输出方式就是scanf()与printf()。scanf()从标准输入设备读取数据,并将值存放在变量中。printf()将指定的文字/字符串输出到标准输出设...
  • 输出流对象

    2019-10-06 03:23:36
    什么是输出流对象呢? cout实际上是C++系统定义的对象名,称为:输出流对象。我们通常使用cout和“<<”实现输出语句 简称cout语句。“<<”是 “插入运算符”与cout配合使用的。 转载于:...
  • 对象输入输出 InputStream字节输入的顶层父类,直接子类:9个 InputStream常用子类: FileInputStream ByteArrayInputStream ObjectInputStream OutputStream字节输出的顶层父类,直接子类:6个 ...
  • 什么是流

    2017-09-24 22:17:05
    2. 比如标准输入一个,标准输出也一个。 3. 所有的 stream 对象 EventEmitter 的实例,可以发射事件。 4. 流是一种有起点和终点的数据传输手段。 上一个的输出,下一个的输入 上一个的输出,下一个...
  • Java对象流

    2017-11-12 19:30:01
    对象流对象流属于高级流,通过这组流可以方便的读写java中的任何对象. 对象输出流:用于写出对象,由于底层读写都字节读写,所以无论什么样的数据都要转换为字节才能写出.对象输出流可以自行将给定的对象转换为一组...
  • 什么是流

    2019-01-12 17:02:21
    什么是流?流,简单来说就是建立在面向对象基础上的一种抽象的处理数据的工具。在流中,定义了一些处理数据的基本操作,如读取数据,写入数据等,程序员是对流进行所有操作的,而不用关心流的另一头数据的真正流向。...
  • 什么是Javascript 对象

    2019-08-06 13:41:41
    1.首先谈谈什么是JavaScript JavaScript是一门非常流行的web脚本语言,这门语言可用于 HTML 和 web,更可广泛用于服务器、PC、笔记本电脑、平板电脑和智能手机等设备。 JavaScript一般运行在客户端,当然也可以运行...
  • 打印对象流

    2019-09-07 19:40:32
    对象流:把对象保存到文件。 这里有几个概念,对象的序列化就是把内存中的对象保存到文件中 反序列化,把文件内容读取到内存中 序列化和缓存一般有结合,服务器连接数据库取查数据的话需要消耗很长时间。我们可以...
  • IO——对象流

    2019-04-08 17:22:17
    对象流:...1、什么是序列化与反序列化? 序列化:指把堆内存中的 Java 对象数据,通过某种方式把对象存储到磁盘文件中或者传递给其他网络节点(在网络上传输)。这个过程称为序列化。通俗来说就是将...
  • 中国科学技术大学软件学院 第8章C++输入输出类层次 目录 8.1概述 8.2格式化输入/输出 8.3重载的插入符和提取符 8.4常用成员函数/O 8.5的错误处理 8.6文件操作 8.7字符串流 中国科学技术大学软件学院 SCHOOL OF...
  • 什么是IO

    2017-03-22 10:01:25
    用于处理设备上数据。在流中一般以字节的形式存放着数据!...字节流:处理字节数据的流对象。设备上的数据无论图片或者dvd,文字,它们都以二进制存储的。二进制的最终都以一个8位为数据单元进行体现,所
  • 节点流:可以从或向一个特定的地方(节点)...处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。 常用的节点流 父 类 InputStream OutputStream Reader Write
  • 什么是节点和处理

    千次阅读 2018-11-18 18:01:53
    按照流是否直接与特定的地方(如磁盘、内存、设备等)相连,分为节点流和处理流两类。节点流:可以从或向一...处理流的构造方法总 要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。JAV...
  • java 什么是流

    万次阅读 2019-02-25 16:05:31
    我们先来用java创建文件,java中文件... 使用绝对路径或相对路径创建File对象 package file; import java.io.File; public class TestFile { public static void main(String[] args) { // 绝对路径 Fil...
  • 2.使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系 3.使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写 4.关闭文件 #include #include #include ...
  • 面向对象的程序设计(Object-Oriented Programming,简记为OOP),当下最流行的程序设计方式之一,它将程序
  • 什么是面向对象设计

    2013-06-16 19:29:06
    早期的面向对象是由OOP发展而来的。早期的OOD的特点:1、不是基于OOA的。大多数方法基于结构化反省的结果进行的OOD,如基于数据图进行的OOD。2、OO编程方法的延伸。3、不是纯OO的。4、不是只针对软件生命周期的...
  • 1.字符 1.1为什么会出现字符【理解】 字符的介绍 由于字节操作中文不是特别的...什么是字符集 是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等 l计算机要准确的存储和识别各
  •  c++中,我们用控制可以实现输出:Hello World!  现在要用于计算的话,譬如2^3。可以用 cout << 2 * 2 * 2<<endl;轻松得到答案。  但如果换成2^10,2^20,2^100等,这个时候我们不能可能每次...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,403
精华内容 2,961
关键字:

什么是流对象