JAVA网络编程期末复习资料 第二章流
第二章 流
JAVA流被分为字节流、字符流,两者有什么区别
字符流是一个字符一个字符地往外读取数据。一个字符是2个字节
字节流是最原始的一个流,读出来的数据就是010101这种最底层的数据表示形式,只不过它是按照字节来读的,一个字节是8位。
输入流和输出流都是站在程序的角度上来说的
节点流和处理流概念及分类。如何区分节点流和处理流
节点流为可以从一个特定的数据源(节点)读取数据(如:文件、内存)
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能
节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据。
处理流是包在别的流上面的流,相当于是包到别的管道上面的管道
为什么需要处理流呢
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能
具体各种流的归属
掌握InputStream、OutputStream、Reader、Writer基本用法
InputStream
- int read() throws IOException
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1表示已经到输入流的末尾 - int read (byte[] buffer) throws IOException
//读取一个字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾返回-1 - int read(byte[] buffer,int offset,int length) throws IOException
//读取length个字节,并存储到一个字节数组buffer,从数组offset位置开始
//返回实际读取的字节数,如果读取前已到输入流的末尾返回-1 - void close() throws IOException
//关闭流释放内存资源 - long skip (long n) throws IOException
//跳过n个字节不读,返回实际跳过的字节数
OutputStream
- void write(int b)throws IOException
向输出流中写入一个字节数据,该字节数据为参数b的低8位 - void write(byte[] b)throws IOException
将一个字节类型的数组中的数据写入输出流 - void write (byte[] b ,int off , int len)throws IOException
将一个字节类型的数组中的从指定位置(off)开始的C,len个字节写入到输出流 - void close() throws IOException
关闭流释放内存资源 - void flush() throws IOException
将输出流中缓冲的数据全部写入到目的地
Reader
- int read() throws IOEXception
//读取一个字符并以整数的形式返回(0~65535)
//如果返回-1则代表已经到输入流的末尾 - int read(char[] cbuf)throws IOException
//读取一系列字符并存储到一个数组cbuf
//返回实际读取的字符数,如果读取前已到输入流的末尾,则返回-1 - int read(char[] cbuf,int offset,int length)throws IOException
//读取length个字符,并存储到一个数组cbuf,从cbuf的offset位置开始存储
//返回实际读取的字符数,如果读取前已到输入流的末尾,则返回-1 - void close() throws IOException
//关闭流释放内存资源 - long skip (long n)throws IOException
跳过n个字符不读,返回实际跳过的字节数
Writer
- void write(int c) throws IOException
//向输出流中写入一个字符数据,该字节数据为参数b的低16位 - void write (char[] cbuf)throws IOException
//将一个字符类型的数组中的数据写入输出流 - void write(char[] cbuf,int offset,int length)throws IOException
//将数组中的从指定位置(offset)开始的length个字符写入到输出流 - void write (String string)throws IOException
//将一个字符串中的字符写入到输出流 - void write(String string,int offset,int length) throws IOException
//将一个字符串从数组的offset开始的length个字符写入到输出流 - void close() throws IOException
//关闭流释放内存资源 - void flush() throws IOException
//将输出流中缓存的数据全部写入到目的地
节点流FileInputStream、FileOutputStream、FileWriter的基本用法(熟悉例子)
FileInputStream读取文件
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class TestFileInputStream {
public static void main(String args[]) {
int b = 0;// 使用变量b来装调用read()方法时返回的整数
FileInputStream in = null;
// 使用FileInputStream流来读取有中文的内容时,读出来的是乱码,因为使用InputStream流里面的read()方法读取内容时是一个字节一个字节地读取的,而一个汉字是占用两个字节的,所以读取出来的汉字无法正确显示。
// FileReader in =
// null;//使用FileReader流来读取内容时,中英文都可以正确显示,因为Reader流里面的read()方法是一个字符一个字符地读取的,这样每次读取出来的都是一个完整的汉字,这样就可以正确显示了。
try {
in = new FileInputStream("D://java网络编程//第二章//test.txt");
// in = new FileReader("D:/CS/tmp/TestFileInputStream.java");
} catch (FileNotFoundException e) {
System.out.println("系统找不到指定文件!");
System.exit(-1);// 系统非正常退出
}
long num = 0;// 使用变量num来记录读取到的字符数
try {// 调用read()方法时会抛异常,所以需要捕获异常
while ((b = in.read()) != -1) {
// 调用int read() throws Exception方法时,返回的是一个int类型的整数
// 循环结束的条件就是返回一个值-1,表示此时已经读取到文件的末尾了。
// System.out.print(b + "\t");// 如果没有使用“(char)b”进行转换,那么直接打印出来的b就是数字,而不是英文和中文了
System.out.print((char) b);
// “char(b)”把使用数字表示的汉字和英文字母转换成字符输入
num++;
}
in.close();// 关闭输入流
System.out.println();
System.out.println("总共读取了" + num + "个字节的文件");
} catch (IOException e1) {
System.out.println("文件读取错误!");
}
}
}
FileOutputStream往一个文件里面写入数据
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestFileOutputStream {
public static void main(String args[]) {
int b = 0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("D://java网络编程//第二章//test.txt");
out = new FileOutputStream("D://java网络编程//第二章//test1.txt");
// 指明要写入数据的文件,如果指定的路径中不存在TestFileOutputStream1.java这样的文件,则系统会自动创建一个
while ((b = in.read()) != -1) {
out.write(b);
// 调用write(int c)方法把读取到的字符全部写入到指定文件中去
}
in.close();
out.close();
} catch (FileNotFoundException e) {
System.out.println("文件读取失败");
System.exit(-1);// 非正常退出
} catch (IOException e1) {
System.out.println("文件复制失败!");
System.exit(-1);
}
System.out.println("TestFileInputStream.java文件里面的内容已经成功复制到文件TestFileOutStream1.java里面");
}
}
用FileWriter(字符流)向指定文件中写入数据,用FileReader(字符流)读取指定文件里面的内容
/*使用FileWriter(字符流)向指定文件中写入数据
写入数据时以1个字符为单位进行写入*/
import java.io.FileReader;
import java.io.FileWriter;
public class TestFile_WR {
public static void main(String args[]) {
/*
* 使用FileWriter输出流从程序把数据写入到Uicode.dat文件中 使用FileWriter流向文件写入数据时是一个字符一个字符写入的
*/
FileWriter fw = null;
try {
fw = new FileWriter("D://java网络编程//第二章//test1.txt");
// 字符的本质是一个无符号的16位整数
// 字符在计算机内部占用2个字节
// 这里使用for循环把0~60000里面的所有整数都输出
// 这里相当于是把全世界各个国家的文字都0~60000内的整数的形式来表示
for (int c = 0; c <= 60000; c++) {
fw.write(c);
// 使用write(int c)把0~60000内的整数写入到指定文件内
// 调用write()方法时,我认为在执行的过程中应该使用了“(char)c”进行强制转换,即把整数转换成字符来显示
// 因为打开写入数据的文件可以看到,里面显示的数据并不是0~60000内的整数,而是不同国家的文字的表示方式
}
fw.close();
/*
* 使用FileReader(字符流)读取指定文件里面的内容 读取内容时是以一个字符为单位进行读取的
*/
int b = 0;
long num = 0;
FileReader fr = null;
fr = new FileReader("D://java网络编程//第二章//test1.txt");
while ((b = fr.read()) != -1) {
System.out.print((char) b + "\t");
num++;
}
fr.close();
System.out.println();
System.out.println("总共读取了" + num + "个字符");
} catch (Exception e) {
e.printStackTrace();
}
}
缓冲流有哪些?各有什么作用?(熟悉例子)
BufferedInputStream类实例
package BufferStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
public class TestBufferStream {
public static void main(String args[]) {
FileInputStream fis = null;
try {
fis = new FileInputStream("D://java网络编程//第二章//test.txt");
// 在FileInputStream节点流的外面套接一层处理流BufferedInputStream
BufferedInputStream bis = new BufferedInputStream(fis);
int c = 0;
System.out.println((char) bis.read());
System.out.println((char) bis.read());
// public void mark(int readlimit)
// 在调用mark的地方做上标记,标记流当前位置。
// 参数readlimit说明在读取readlimit个字符后书签做废。?????
bis.mark(23);
for (int i = 0; i <= 35 && (c = bis.read()) != -1; i++) {
System.out.print((char) c);
}
System.out.println();
bis.reset();// 重新回到原来标记的地方
for (int i = 0; i <= 15 && (c = bis.read()) != -1; i++) {
System.out.print((char) c);
}
bis.reset();// 重新回到原来标记的地方
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
BufferedWriter与BufferedReader实例
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
public class TestBufferStream1 {
public static void main(String args[]) {
try {
BufferedWriter bw = new BufferedWriter(new FileWriter("D://java网络编程//第二章//test.txt"));
// 在节点流FileWriter的外面再套一层处理流BufferedWriter
String s = null;
for (int i = 0; i < 100; i++) {
s = String.valueOf(Math.random());
//“Math.random()”将会生成一系列介于0~1之间的随机数。
// static String valueOf(double d)这个valueOf()方法的作用就是把一个double类型的数转换成字符串
// valueOf()是一个静态方法,所以可以使用“类型.静态方法名”的形式来调用
bw.write(s);// 把随机数字符串写入到指定文件中
bw.newLine();
//调用newLine()方法使得每写入一个随机数就换行显示
}
bw.flush();// 调用flush()方法清空缓冲区
BufferedReader br = new BufferedReader(new FileReader("D://java网络编程//第二章//test.txt"));
// 在节点流FileReader的外面再套一层处理流BufferedReader
while ((s = br.readLine()) != null) {
// 使用BufferedReader处理流里面提供String readLine()方法读取文件中的数据时是一行一行读取的
// 循环结束的条件就是使用readLine()方法读取数据返回的字符串为空值后则表示已经读取到文件的末尾了。
System.out.println(s);
}
bw.close();
br.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
转换流有哪些?各有什么作用?
- 转换流有两种,一种叫InputStreamReader,另一种叫OutputStreamWriter。
- 如果用一个FileOutputStream流往文件里面写东西, 得要一个字节一个字节地写进去,但是如果我们在FileOutputStream流上面套上一个字符转换流,那我们就可以一个字符串一个字符串地写进去
数据流、打印流、对象流有哪些?各有什么作用?
数据流
- DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流需要分别“套接”在InputStream和OutputStream类型的节点流上
打印流
- PrintWriter和PrintStream都属于输出流,分别针对于字符和字节。PrintWriter和PrintStream提供了重载的print
- Println方法用于多种数据类型的输出
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误相信
- PrintWriter和PrintStream有自动flush功能
对象流
直接将Object写入或读出
- transient关键字:transient透明的,用它来修饰的成员变量在序列化的时候不予考虑。也就是当成不存在
- serializable接口:标志性接口,通过这个接口标记的类的对象可以被序列化,并且是由JKD帮控制这个类的对象怎么序列化
- externalizable接口:通过这个接口标记的类就可以自己控制对象的序列化