标签:mit 常用 ring between off serial tween 流式 har
? 在Java程序中,对于数据的输入/输出操作以“流”(Stream)方式进行;J2SDK提供了各种各样的“流”
类,用以获取不同种类的数据:程序中通过标准的方法输入或输出数据。
读入写出
Java.io 包中定义了多个流类型(类或抽象类)来实现输入/输出功能;可以从不同的角度对其进行分类:
J2SDK所提供的所有流类型位于包 Java.io内,都分别继承自以下四种抽象流类型
输入流:InputStream(字节流),Reader(字符流)
输出流:OutPutStream(字节流),Writer(字符流)
这四个类都是抽象类,可以把这四个类想象成四根不同的管道。一端接着你的程序,另一端接着数据源,你可以通过输出管道从数据源里面往外读数据,也可以通过输入管道往数据源里面输入数据,总之,通过这四根管道可以让数据流进来和流出去。
io包里面定义了所有的流,所以一般说流指的就是io包里面的
什么叫输入流?什么叫输出流?
用一根管道一端插进文件里,一端插进程序里面,然后开始读数据,那么这是输入还是输出呢?
如果站在文件的角度上,这叫输出。
如果站在程序的角度上,这叫输入。
记住,以后说输入流和输出流都是站在程序的角度上来说。
你要是对原始的流不满意,你可以在这根管道外面再套其它的管道,套在其它管道之上的流叫处理流。为什么需要处理流呢?这就跟水流里面有杂质,你要过滤它,你可以再套一层管道过滤这些杂质一样。
类型 | 字符流 | 字节流 |
---|---|---|
File(文件) | FileReader、FileWriter | FileInputStream、FileOutputStream |
Memory Array |
CharArrayReader、 CharArrayWriter |
ByteArrayInputStream、 ByteArrayOutputStream |
Memory String |
StringReader、StringWriter | - |
Pipe(管道) | PipedReader、PipedWriter | PipedInputStream、PipedOutputStream |
节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据。
典型的节点流是文件流:
文件的字节输入流(FileInputStream),文件的字节输出流(FileOutputStream),
文件的字符输入流(FileReader),文件的字符输出流(FileWriter)。
处理类型 | 字符流 | 字节流 |
---|---|---|
Buffffering | BufffferedReader、 BufffferedWriter |
BufffferedInputStream、 BufffferedOutputStream |
Filtering | FilterReader、FilterWriter | FilterInputStream, FilterOutputStream |
Converting between bytes and chaacter |
InputStreamReader、 OutputStreamWriter |
- |
Object Serialization | - | ObjectInputStream、 ObjectOutputStream |
Data conversion | - | DataInputStream、 DataOutputStream |
Counting | LineNumberReader | LineNumberInputStream |
Peeking ahead | PusbackReader | PushbackInputStream |
Printing | PrintWriter | PrintStream |
处理流是包在别的流上面的流,相当于是包到别的管道上面的管道。
我们看到的具体的某一些管道,凡是以InputStream结尾的管道,都是以字节的形式向我们的程序输入数据。
继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit);下图中深色为节点流,浅色为处理流
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//读取length个字节
//并存储到一个字节数组buffer,从length位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
以File(文件)这个类型作为讲解节点流的典型代表
【演示:使用FileInputStream流来读取FileInputStream.java文件的内容】
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("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
// in = new FileReader("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
} catch (FileNotFoundException e) {
System.out.println("系统找不到指定文件!");
System.exit(-1);// 系统非正常退出
}
long num = 0;// 使用变量num来记录读取到的字符数
// 调用read()方法时会抛异常,所以需要捕获异常
try {
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("文件读取错误!");
}
}
}
继承自OutputStream的流是用于程序中输出数据,且数据的单位为字节(8bit):下图中深色的为节点流,浅色为处理流。
//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
【使用FileOutputStream流往一个文件里面写入数据】
public class TestFileOutputStream {
public static void main(String args[]) {
int b = 0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
out = new FileOutputStream("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\StudentNew.java");
// 指明要写入数据的文件,如果指定的路径中不存在StudentNew.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("Student.StudentNew.java里面");
}
}
FileInputStream和FileOutputStream这两个流都是字节流,都是以一个字节为单位进行输入和输出的。所以对于占用2个字节存储空间的字符来说读取出来时就会显示成乱码。
Reader : 和InputStream一模一样,唯一的区别就在于读的数据单位不同
继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit)
//读取一个字节并以整数的形式返回(0~255)
//如果返回-1就说明已经到了输入流的末尾
int read() throws IOException
//读取一系列字节并存储到一个数组buffer
//返回实际读取的字节数,如果读取前已到输入流的末尾,则返回-1
int read(byte[] buffer) throws IOException
//读取length个字节
//并存储到一个字节数组buffer,从length位置开始
//返回实际读取的字节数,如果读取前以到输入流的末尾返回-1.
int read(byte[] buffer,int offset,int length) throws IOException
//关闭流释放内存资源
void close() throws IOException
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException
继承自Writer的流都是用于程序中输出数据,且数据的单位为字符(16bit);
//向输出流中写入一个字节数据,该字节数据为参数b的低16位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b,int off,int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中缓冲的数据全部写出到目的地
void flush() throws IOException
【演示:使用FileWriter(字符流)向指定文件中写入数据】
/*使用FileWriter(字符流)向指定文件中写入数据写入数据时以1个字符为单位进行写入*/
public class TestFileWriter{
public static void main(String args[]){
/*使用FileWriter输出流从程序把数据写入到Uicode.dat文件中
使用FileWriter流向文件写入数据时是一个字符一个字符写入的*/
FileWriter fw = null;
try{
fw = new FileWriter("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\StudentNew.java");
//字符的本质是一个无符号的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内的整 数,而是不同国家的文字的表示方式
}
/*使用FileReader(字符流)读取指定文件里面的内容
读取内容时是以一个字符为单位进行读取的*/
int b = 0;
long num = 0;
FileReader fr = null;
fr = new FileReader("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\StudentNew.java");
while((b = fr.read())!= -1){
System.out.print((char)b + "\t");
num++;
}
System.out.println();
System.out.println("总共读取了"+num+"个字符");
}catch(Exception e){
e.printStackTrace();
}
}
}
FileReader和FileWriter这两个流都是字符流,都是以一个字符为单位进行输入和输出的。所以读取和写入占用2个字节的字符时都可以正常地显示出来,以上是以File(文件)这个类型为例对节点流进行了讲解,所谓的节点流指定就是直接把输入流或输出插入到数据源上,直接往数据源里面写入数据或读取数据。
缓冲流要”套接“在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。J2SDK提供了四种缓冲流,常用构造方法如下:
BufferedReader(Reader in)
BufferedReader(Reader in,int sz) //sz 为自定义缓冲区的大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in,int size)
BufferedOutputStream(InputStream in)
BufferedOutputStream(InputStream in,int size)
缓冲输入流支持其父类的mark和reset方法。
BufferedReader提供了readLine方法用于读取一行字符串
BufferedWriter提供了newLine用于写入一个行分隔符
对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会使内存中的数据立刻写出带有缓冲区的,缓冲区(Buffffer)就是内存里面的一小块区域,读写数据时都是先把数据放到这块缓冲区域里面,减少io对硬盘的访问次数,保护我们的硬盘。可以把缓冲区想象成一个小桶,把要读写的数据想象成水,每次读取数据或者是写入数据之前,都是先把数据装到这个桶里面,装满了以后再做处理。这就是所谓的缓冲。先把数据放置到缓冲区上,等到缓冲区满了以后,再一次把缓冲区里面的数据写入到硬盘上或者读取出来,这样可以有效地减少对硬盘的访问次数,有利于保护我们的硬盘。
【缓冲流测试代码:BufferedInputStream】
public class TestBufferStream {
public static void main(String args[]) {
FileInputStream fis = null;
try {
fis = new FileInputStream("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.java");
// 在FileInputStream节点流的外面套接一层处理流BufferedInputStream
BufferedInputStream bis = new BufferedInputStream(fis);
int c = 0;
System.out.println((char) bis.read());
System.out.println((char) bis.read());
bis.mark(100);// 在第100个字符处做一个标记
for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
System.out.print((char) c);
}
System.out.println();
bis.reset();// 重新回到原来标记的地方
for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
System.out.print((char) c);
}
bis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
public void mark(int readlimit)
//标记此输入流中的当前位置。 随后对reset方法的调用会将该流重新定位在最后一个标记的位置,以便后续读取重新读取相同的字节。
//readlimit参数指示此输入流允许在标记位置无效之前读取许多字节。
public void reset()
throws IOException
//将此流重新定位到上次在此输入流上调用mark方法时的位置。
【演示:BufferedReader】
public class TestBufferStream{
public static void main(String args[]){
try{
BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\教学 \\班级\\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.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("E:\\教学 \\班级\\Test\\Lesson2\\src\\com\\kuang\\chapter\\Student.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();
}
}
}
InputStream isr = new InputStreamReader(System.in,"ISO8859-1")
转换流非常的有用,它可以把一个字节流转换成一个字符流
转换流有两种,一种叫InputStreamReader,另一种叫OutputStreamWriter。
【转换流测试代码】
public class TestTransform1 {
public static void main(String args[]) {
try {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:/java/char.txt"));
osw.write("MircosoftsunIBMOracleApplet");// 把字符串写入到指定的文件 中去
System.out.println(osw.getEncoding());// 使用getEncoding()方法取得 当前系统的默认字符编码
osw.close();
osw = new OutputStreamWriter(new FileOutputStream( "D:\\java\\char.txt", true), "ISO8859_1");
// 如果在调用FileOutputStream的构造方法时没有加入true,那么新加入的字符 串就会替换掉原来写入的字符串,在调用构造方法时指定了字符的编码
osw.write("MircosoftsunIBMOracleApplet");// 再次向指定的文件写入字符 串,新写入的字符串加入到原来字符串的后面
System.out.println(osw.getEncoding());
osw.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class TestTransform2{
public static void main(String args[]){
try{
InputStreamReader isr = new InputStreamReader(System.in);
//System.in这里的in是一个标准的输入流,用来接收从键盘输入的数据
BufferedReader br = new BufferedReader(isr);
String s = null; s = br.readLine();
//使用readLine()方法把读取到的一行字符串保存到字符串 变量s中去
while(s != null){
System.out.println(s.toUpperCase());//把保存在内存s中的字符串打 印出来
s = br.readLine();//在循环体内继续接收从键盘的输入
if(s.equalsIgnoreCase("exit")){ //只要输入exit循环就结束,就会退出
break;
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}
DataInputStream (InputStream in)
DataOutputStream (OutputStream out)
【数据流测试代码】
public class TestDataStream{
public static void main(String args[]){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//在调用构造方法时,首先会在内存里面创建一个ByteArray字节数组
DataOutputStream dos = new DataOutputStream(baos);
//在输出流的外面套上一层数据流,用来处理int,double类型的数
try{
dos.writeDouble(Math.random());//把产生的随机数直接写入到字节数组 ByteArray中
dos.writeBoolean(true);//布尔类型的数据在内存中就只占一个字节
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());//先写进去的就先读出来,调用 readDouble()方法读取出写入的随机数
System.out.println(dis.readBoolean());//后写进去的就后读出来,这里面 的读取顺序不能更改位置,否则会打印出不正确的结果
dos.close();
bais.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
PrintWriter(Writer out)
PrintWriter(Writer out,boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(OutputStream out,boolean autoFlush)
PrintStream(OutputStream out)
PrintStream(OutputStream out,boolean autoFlush)
【测试代码】
/*这个小程序是重新设置打印输出的窗口,
* 把默认在命令行窗口输出打印内容设置成其他指定的打印显示窗口
*/
public class TestPrintStream{
public static void main(String args[]){
PrintStream ps = null;
try{
FileOutputStream fos = new FileOutputStream("E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\log.txt");
ps = new PrintStream(fos);//在输出流的外面套接一层打印流,用来控制打印 输出
if(ps != null){
System.setOut(ps);//这里调用setOut()方法改变了输出窗口,以前写 System.out.print()默认的输出窗口就是命令行窗口.
//但现在使用System.setOut(ps)将打印输出窗口改成了由ps指定的文件里 面,通过这样设置以后,打印输出时都会在指定的文件内打印输出
//在这里将打印输出窗口设置到了log.txt这个文件里面,所以打印出来的内容会 在log.txt这个文件里面看到
}
for(char c=0;c<=1000;c++){
System.out.print(c+"\t");//把世界各国的文字打印到log.txt这个文件 中去
}
}catch(Exception e){
e.printStackTrace();
}
}
}
直接将Object 写入或读出
transient关键字
serializable接口
externaliazble接口
public class TestObjectIo {
public static void main(String args[]) {
T t = new T();
t.k = 8;// 把k的值修改为8
try {
FileOutputStream fos = new FileOutputStream( "E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\TestObjectIo.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
// ObjectOutputStream流专门用来处理Object的,在fos流的外面套接 ObjectOutputStream流就可以直接把一个Object写进去
oos.writeObject(t);// 直接把一个t对象写入到指定的文件里面
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream( "E:\\教学\\班级 \\Test\\Lesson2\\src\\com\\kuang\\chapter\\TestObjectIo.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
// ObjectInputStream专门用来读一个Object的
T tRead = (T) ois.readObject();
// 直接把文件里面的内容全部读取出来然后分解成一个Object对象,并使用强制转换 成指定类型T
System.out.print(tRead.i + "\t" + tRead.j + "\t" + tRead.d + "\t" + tRead.k);
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/*
* 凡是要将一个类的对象序列化成一个字节流就必须实现Serializable接口
* Serializable接口中没有定义方法,Serializable接口是一个标记性接口,用来给类作标记, 只是起到一个标记作用。
* 这个标记是给编译器看的,编译器看到这个标记之后就可以知道这个类可以被序列化 如果想把某个 类的对象序列化,就必须得实现Serializable接口
*/
class T implements Serializable {
// Serializable的意思是可以被序列化的
int i = 10;
int j = 9;
double d = 2.3;
int k = 15;
// transient int k = 15;
// 在声明变量时如果加上transient关键字,那么这个变量就会被当作是透明的,即不存在。
}
Inputstram/Outputstream
Reader/Writer
FileInputstram/Fileoutputstream
FileReader/FileWriter
Inputstreamreader/Outputstreamwriter
Datainputstream/out
PrintStream/PrintWriter
这个流里面要注意关键字transient,序列化时不会考虑这个属性
Serializable接口,是一个标记性接口,通过这个接口标记的类的对象可以序列化,并且是JDK控制这个类的序列化
还有一个接口是externaliazble,通过这个接口标记的类可以字节控制对象的序列化(不推荐a)
标签:mit 常用 ring between off serial tween 流式 har
原文地址:https://www.cnblogs.com/shitouzi-shi/p/14391261.html