1.IO是什么意思?data source是什么意思?

IO:Input Output

data source:数据流。

 

2.字节流和字符流有什么区别?输入流输出流有什么区别?

    字节流和字符流是流的一种划分,按照处理流的数据单位进行的划分。两类都分为输入和输出操作。在字节流中输出数据主要是使用OutputStream完成,输入是使用InputStream;在字符流中输出主要是使用Writer类来完成,输入流主要使用Reader类来完成。这四个都是抽象类。

    字符流处理的单元为2个字节的Unicode字符,分别是操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。字节流是最基本的,所有的InputStream和OutputStream的子类都是字节流,主要用来处理二进制数据,它是按字节来处理的。但实际中很多数据都是文本,又提出了字符流的概念,它是按虚拟机的编码来处理,也就是说要进行字符集的转化,这两个之间通过InputStreamReader、OutputStreamWriter(转换流)来关联,实际上是通过byte()和String来关联的。

   流就像管道一样,在程序和文件之间,输入和输出的方向是针对程序而言,向程序中读入读入东西,就像输入流,从程序中向外读东西,就是输出流。输入流是得到数据,输出流是输出数据。

 

3.节点流和处理流有什么区别?

节点流和处理流是把流按照功能的另一种划分。

节点流,可以从或向一个特定的地方(节点)读写数据。

处理流是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。

 

4.Word文档能使用字符流操作吗?

不能。因为Word文档不是纯文本文件,除了文字还包含很多格式信息。不能用字符流操作,可以用字节流操作。

 

5.BufferedInputStream和BufferedOutputStream的特点?

    BufferedInputStream和BufferedOutputStream分别是【缓冲】字节输入、输出流,还有【缓冲】字符输入输出流(BufferedReader和BufferedWriter)。

    缓冲流是处理流,他不是直接连接数据源/目的地,而是以一个节点流为参数,在节点流的基础上,提供一些简单参数。

    先说不带缓冲的流的工作原理吧:它读取到一个字节/字符,就向用户指定的路径写进去,读一个写一个,所以就慢了。带缓冲的流的工作原理:读取到一个字节/字符,先不输出,等凑足了缓冲的最大容量后一次性写进去,从而提高了工作效率。

优点:减少对硬盘的读取次数,降低对硬盘的损耗。

 

6.使用BufferedReader和BufferedWriter实现文本的拷贝。

package IO;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import java.io.Writer;

public class CopyFile {

	public static void main(String[] args) throws Exception {
		//第一部分:准备从文件读数据到程序
		//创建读取对象reader
		Reader reader = new FileReader(new File("e:\\a.txt"));
		//创建缓冲流包装reader
		BufferedReader br = new BufferedReader(reader);
		
		//第二部分:准备从程序写到文件
		//创建写入对象writer
		Writer writer = new FileWriter(new File("e:\\a2.txt"));
		//创建缓冲包装对象
		BufferedWriter bw = new BufferedWriter(writer);
		
		String str = null;
		//用循环边读边写
		while((str=br.readLine()) != null) {
			bw.write(str);
			bw.newLine();
		}
		
		//清除缓冲区
		bw.flush();
		//copy完成后关闭资源
		bw.close();
		br.close();
	}
}

docer中把文件出现复制到docer容器中的命令_数据流和对象流

 

7.InputStreamReader和OutputStreamWriter的作用是?

二者都是转换流,从字节流转换成字符流,是包装流,以一个节点流为参数,提供一些方便读写【字符】的方法。

package IO;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;

public class InputStreamReaderDemo {

	public static void main(String[] args) throws Exception {
		//节点流
		InputStream is = new FileInputStream("e:\\a.txt");
		//处理流,把字节流转换成字符流
		InputStreamReader isr = new InputStreamReader(is,"utf-8");
		int temp = 0;
		//用转换流对象isr进行读写操作,以字符(而不是字节)为单位读取文本文件,方便操作
		while((temp = isr.read()) != -1) {
			System.out.print((char) temp +" ");//打印出来的字符会以空格隔开
		}
		isr.close();
		is.close();
	}

}

docer中把文件出现复制到docer容器中的命令_节点流与处理流_02

 

 

 

8.PrintStream打印流经常用于什么情况?System.out是打印流吗。

PrintStream:字节打印流,是OutputStream的实现类。提供了多个重载的print,println等方法,可以方便地向文本文件写入数据。

System.out是字节打印流(PrintStream的对象),它被称作标准的输出流,输出的目的地是标准的输出设备,即显示器。所以,当我们使用System.out.print时会向屏幕(显示器)输出数据。

 

9.实现字节数组和任何基本类型、引用类型执行的相互转换。

提示:使用ByteArrayInputStream和ByteArrayOutputStream。

(1)字节数组和基本类型之间的转换,以boolean为例:

    ①输出一个boolean类型的数据:

boolean flag = true;//先定义一个boolean类型的变量
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
dos.writeBoolean(flag);
	
byte[] b = baos.toByteArray();
//接下来可以把byte数组建成一个数据包(DatagramPacket)发送出去;

     ②读取一个boolean类型的数据:

byte[] b = new byte[1024];
//我们已接收到包含一个Boolean类型数据的数据包;数据信息已经包含在byte数组b里,接下来就把boolean类型的数据读出来并保持原类型
	
ByteArrayInputStream bais = new ByteArrayInputStream(b);
DataInputStream dis = new DataInputStream(bais);
boolean flag = dis.readBoolean();//这样数据就读出来了并保持着原来的数据类型

 

(2)字节数组和引用类型之间的转换:

  ①输出一个引用类型信息:

//先建一个类,如User
User user = new User();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(user);

byte[] b = baos.toByteArray();
//接下来可以把byte数组构建成一个数据包发送出去

  ②读取一个引用类型信息

byte[] b = new byte[1024];
//我们已接收到包含一个User类型数据的数据包(代码略)
//数据信息已经包含在byte数组b里,接下来就把User类型的数据读出来并保持原类型
ByteArrayInputStream bais = new ByteArrayInputStream(b);
ObjectInputStream ois = new ObjectInputStream(bais);
User user = (User)ois.readObject();//这样数据就读出来了并保持着原来的数据类型

 

10.DataInputStream和DataOutputStream的特点是?

  二者都是处理流,要以一个节点流为参数;二者被称为数据流,是用来操作基本数据类型的。用DataInputStream写入一个类型的数据,用DataOutputStream读出数据时可以保持类型不变。

  如:用DataInputStream写入一个int类型数据,用DataOutputStream读出来的还是一个int数据,即可以直接当作int类型的数据来进行操作,不用作任何转换。

数据流特点:

     ①写入是什么类型的数据,读出的是相应类型的数据

     ②要先写后读,用DataOutputStream流写,用DataInputStream流读

     ③读写顺序要一致,否则会报EOF(End of file)异常

     ④数据流可以跨平台写入和读出,适合网路应用

 实例:

package IO;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class DataStreamDemo {

	public static void main(String[] args) throws IOException {
		//1.写数据
		OutputStream os = new FileOutputStream(new File("e:\\a1.txt"));//构建节点流
		DataOutputStream dos = new DataOutputStream(os);//用数据流包装节点流
		
		int n = 123456;
		String str = "CSDN博客";
		
		dos.writeInt(n);//用数据流写一个int类型数据
		dos.writeUTF(str);//String
		dos.writeDouble(3.14);//double
		dos.writeChar('周');//char
		dos.writeBoolean(true);//boolean
		
		
		//2.读数据,(按上面写的顺序才行)
		InputStream is = new FileInputStream(new File("e:\\a1.txt"));
		DataInputStream dis = new DataInputStream(is);
		int n1 = dis.readInt(); //用数据流读出刚才写入的int类型数据
		String str1 = dis.readUTF();
		double d = dis.readDouble();
		char c = dis.readChar();
		boolean flag = dis.readBoolean();
		
		//打印输出用数据流读出的数据
		System.out.println(n1);
		System.out.println(str1);
		System.out.println(d);
		System.out.println(c);
		System.out.println(flag);

		//关闭资源
		dis.close();
		dos.close();
	}

}

运行结果:

docer中把文件出现复制到docer容器中的命令_序列化和反序列化_03

 

11.中文乱码是怎么造成的?Unicode字符集是几个字节表示一个字符,为什么需要utf-8?

字符流的读写根据需要,设置编码方式,若编码方式设置不当,就会出现中文乱码。

Unicode字符集2个字节表示一个字符。

 

12.序列化和反序列化指的是什么?

(1)序列化:

        将对象以byte流的形式写入到文件中-》序列化;

        将要被序列化对象的类要实现Serializable接口。 

(2)反序列化:

         将文件中的数据以byte流的形式读到程序中来,依然是一个对象-》反序列化

 

13.想序列化某个类的对象,该类必须实现Serializable借口吗?说说该接口的特点。

要序列化的对象必须实现Serializable接口,以启动序列化的功能。

Serializable接口特点:

①需要被序列化的对象的类必须实现Serializable接口;

②给类加个序列化编号,即给类定义一个标记,例:public static final long serialVersionUID = 1L;

新的修改后的类还可以操作曾经序列化的对象;

③静态类是不能被序列化的(序列化只能对堆中的对象进行序列化,不能对"方法区"中的对象进行序列化);

④不需要序列化的字段前加transient,如:private transient String password;

 

15.代码实现从源目录拷贝文件到目标文件(结合递归算法)。

package IO;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyDir {

	public static void main(String[] args) {
		try {
			copyDirectiory("E:\\learning_note","E:\\learning_note2");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	/**
	 * 复制单个文件
	 * @param sourceFile
	 * @param targetFile
	 * @throws IOException
	 */
	private static void copyFile(File sourceFile, File targetFile) throws IOException {
		BufferedInputStream inBuff = null;
		BufferedOutputStream outBuff = null;
		
		try {
			//新建文件输入流
			inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
			//新建文件输出流
			outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
			//缓冲数组
			byte[] b = new byte[1024*5];
			int len;
			while((len = inBuff.read(b)) != -1) {
				outBuff.write(b, 0, len);
			}
			
			//刷新此缓冲的输出流
			outBuff.flush();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
		
			//关闭流
			if(inBuff != null) {
				inBuff.close();
			}
			if(outBuff != null) {
				outBuff.close();
			}
		}
		
	}
	
	/**
	 * 复制目录
	 * @param sourceDir
	 * @param targetDir
	 * @throws IOException
	 */
	private static void copyDirectiory(String sourceDir,String targetDir) throws IOException {
		//检查源目录
		File fSourceDir = new File(sourceDir);
		if(!fSourceDir.exists() || !fSourceDir.isDirectory()) {//不存在或不是目录结构
			return;
		}
		//检查目标目录,如不存在就创建
		File fTargetDir = new File(targetDir);
		if(!fTargetDir.exists()) {
			fTargetDir.mkdirs();
		}
		//遍历源目录下的文件或目录
		File[] file = fSourceDir.listFiles();
		for(int i=0; i<file.length; i++) {
			if(file[i].isFile()) {
				File sourceFile = file[i]; //源文件
				File targetFile = new File(fTargetDir,file[i].getName());//目标文件
				copyFile(sourceFile, targetFile);
				
			}
			//递归复制子目录
			if(file[i].isDirectory()) {
				//准备复制的源文件夹
				String subSourceDir = sourceDir+File.separator+file[i].getName();
				//准备复制的目标文件夹
				String subTargetDir = targetDir+File.separator+file[i].getName();
				//复制子目录
				copyDirectiory(subSourceDir,subTargetDir);
			}
		}	
	}
}

docer中把文件出现复制到docer容器中的命令_数据流和对象流_04

 

16.代码实现统计几个.java文件的行数的功能。

package IO;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class CountLines {
	private int count;

	/**
	 * 统计一个Java文件的行数
	 * 
	 * @throws IOException
	 */
	private void countLine(File sourceFile) throws IOException {
		BufferedReader br = null;
		try {
			// 新建文件输入流
			br = new BufferedReader(new FileReader(sourceFile));
			while (br.readLine() != null) {
				count++;
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			br.close();
		}
	}

	/**
	 * 统计一个目录下所有Java文件的行数
	 * @throws IOException 
	 */
	private void countDir(String sourceDir) throws IOException {
		// 检查源目录
		File fSourceDir = new File(sourceDir);
		if (!fSourceDir.exists() || !fSourceDir.isDirectory()) {
			System.out.println("源目录不存在");
			return;
		}
		//遍历目录下的文件或目录
		File[] file = fSourceDir.listFiles();
		for(int i=0; i<file.length; i++) {
			if(file[i].isFile()) {
				if(file[i].getName().toLowerCase().endsWith(".java")) {
					countLine(file[i]);
				}
			}
			//递归统计代码行数
			if(file[i].isDirectory()) {
				//准备统计的文件夹
				String subSourceDir = sourceDir+File.separator+file[i].getName();
				//统计子目录
				countDir(subSourceDir);
			}
		}
		
	}

	public static void main(String[] args) throws IOException {
		CountLines cl = new CountLines();
		cl.countDir("e:\\javaFile");
		System.out.println(cl.count);
	}

}