IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> java网络编程 个人笔记 第二章 流 -> 正文阅读

[Java知识库]java网络编程 个人笔记 第二章 流

I/O介绍

I/O的挑战:

  • 与不同的源和接收端进行交互,包括文件、控制台、网络连接等
  • 以不同的方式与它们进行通信(顺序、随机存取、缓冲、二进制、按照字符、按行、按字节等)
  • 大多数I/O需要进行异常处理

java流式输入/输出原理

流是用来读写数据的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据

想读文件里面的数据,需要通过一个流的方式来读。因为如果想从程序数据,对于计算机来说,无论读什么类型的数据都是以01010010这样的形式来读取的

输入输出流分类

java.io包中定义了多个流类型(类或抽象类)来实现I/O功能:可以从不同的角度对其进行分类:

  • 按数据流的方向不同可以分为输入流输出流
  • 按处理数据单位不同可以分为字节流字符流
  • 按照功能不同可以分为节点流处理流

字符流是一个字符一个字符地往外读取数据。一个字符是2个字节
字节流是最原始的一个流,读出来的数据就是010101这种最底层的数据表示形式,只不过它是按照字节来读的,一个字节是8位。

J2SDK所提供的所有流类型位于包java.io内都分别继承自以下四种抽象流类型
四种抽象流
这四个类都是抽象类,可以把这四个类想象成四根不同的管道。一端接着你的程序,另一端接着数据源,你可以通过输出管道从数据源里面往外读数据,也可以通过输入管道往数据源里面输入数据。总之通过这四根管道可以让数据流进来和流出去

输入流和输出流都是站在程序的角度上来说的

节点流和处理流

节点流为可以从一个 特定的数据源(节点)读写数据(如:文件,内存)
在这里插入图片描述
处理流是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写能力

节点流的类型

节点流就是一根管道直接插到数据源上面,直接读数据源里面的数据,或者是直接往数据源里面写入数据

典型的节点流是文件流:文件的字节输入流(FileInputStream),文件的字节输出流(FileOutputStream)、文件的字符输入流(FileReader)、文件的字符输出流(FileWriter)
节点流类型

处理流的类型

处理流是包在别的流上面的流,相当于是包到别的管道上面的管道
处理流的类型

InputStream(输入流)

继承来自InputStream(以流InputStream结尾)的,都是以字节的形式向我们的程序输入数据
输入流

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个字节不读,返回实际跳过的字节数

代码展示

int read() 方法展示

package InputStream;

import java.io.*;
public class First {
	public static void main(String[] args) {
		int b = 0;
		FileInputStream in = null;
		try{
			in = new FileInputStream("D:\\java网络编程\\第二章\\test.txt");
		}catch(FileNotFoundException e){
			System.out.println("系统找不到指定文件!");
			System.exit(-1);
		}

		long num = 0;
		try{
			while((b = in.read()) != -1){
				System.out.print((char)b+"\t");
				num++;
			}
			in.close();
			System.out.println();
			System.out.println("总共读取了"+num+"个字节的文件");
		}catch (IOException e1){
			System.out.println("文件读取错误!");
		}
	}
}

读取的文件内容:
在这里插入图片描述
输出结果:
在这里插入图片描述
这是因为中文是2个字节,而read()方法只能读取一个字节,于是展示出来的是乱码

int read(byte[]) 方法展示

byte[] arr = new byte[10];
try{
    while((b = in.read(arr)) != -1){
        System.out.println("总共读取了"+b+"个字节的文件");
        for(int i = 0;i < arr.length;i++){
            System.out.print((char)arr[i]+"\t");
        }
        System.out.println();
    }
    in.close();
    System.out.println();
}catch (IOException e1){
    System.out.println("文件读取错误!");
}

结果展示:
在这里插入图片描述

int read(byte[],off,len)方法展示:

byte[] arr = new byte[20];
try{
  while( (b = in.read(arr,3,10) )!= -1) {
      System.out.println("总共读取了" + b + "个字节的文件");
      for (int i = 0; i < arr.length; i++) {
          System.out.print((char) arr[i] + "\t");
      }
      System.out.println();
  }
   in.close();
   System.out.println();
}catch(IOException e1){
   System.err.print("文件读取错误");
}

注意,这里的offset是数组的,所以前面使用的10长度对于这里的3off和10len就不够用了,设成20后可行
结果展示:

在这里插入图片描述

void close()方法上面都有展示这里就跳过了
long skip(long)方法展示:

byte[] arr = new byte[20];
 try{
     long c = in.skip(3);
     System.out.println("总共跳过"+c+"个字节");
    while( (b = in.read(arr,3,10) )!= -1) {
        System.out.println("总共读取了" + b + "个字节的文件");
        for (int i = 0; i < arr.length; i++) {
            System.out.print((char) arr[i] + "\t");
        }
        System.out.println();
    }
     in.close();
     System.out.println();
 }catch(IOException e1){
     System.err.print("文件读取错误");
 }

结果展示:
在这里插入图片描述

OutputStream输出流

OutputStream
继承自outputs team的流是用于程序中输入数据,且数据的单位为字节(8 bit);下图中深色为节点流,浅色为处理流
在这里插入图片描述

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
    将输出流中缓冲的数据全部写入到目的地

代码展示

write(int b)方法代码展示:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;


public class write {
    public static void main(String[] args){
        int b =0;
        FileOutputStream out = null;
        try{
            out = new FileOutputStream("D:\\java网络编程\\第二章\\test1.txt");
        }catch(FileNotFoundException e){
            System.err.println(e.getMessage());
        }


        Scanner scan = new Scanner(System.in);
        try{
            out.write(scan.nextInt());
        }catch(IOException e){
            System.out.println(e.getMessage());
        }
    }
}

结果:
在这里插入图片描述
在这里插入图片描述
输入了123,然后输出了},这是因为}的ASCII码是123

同理,用scan.nextByte输入也是同样的结果

write(Byte[])方法展示

byte[] c = new byte[10];
for(int i = 0;i<10;i++){
    Scanner scan1 = new Scanner(System.in);
    c[i] = scan1.nextByte();
}
try{
    out.write(c);
    out.flush();
	out.close();
}catch(IOException e){
    System.out.println(e.getMessage());
}

这里输入了长度为10的byte数组c之后,可以在test1文件中读到输入的对应ASCII码的结果

flush():清空缓冲区。
进行流的操作时,数据先被读到内存时,然后再将数据写到文件中,那么当你数据读完时,调用close()关闭读写流,这时就可能造成数据丢失。原因是:读入数据完成时不代表写入数据完成,一部分数据可能会留在缓冲区中,flush()方法就是去解决这个问题的,把最后缓冲区中的数据写入到文件中,这样就保证了数据的完整性。所以之后再调用close()方法关闭读写流。

Reader流

和InputStream一模一样,唯一的区别就在于读的数据单位不同

继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit),下图中深色的为节点流,浅色的为处理流

Reader流

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个字符不读,返回实际跳过的字节数

代码展示

read() 方法展示:

package Reader;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class ReaderDemo2 {
    public static void main(String[] args) throws IOException {
        Reader r = new FileReader("D://java网络编程//第二章//reader.txt");
        int num = 0;
        while((num = r.read())!= -1){
            System.out.println(num);
        }
        r.close();
    }
}

结果:
在这里插入图片描述

read(char[]) 方法展示:

package Reader;

import java.io.*;
import java.util.*;

public class ReaderDemo1 {
    public static void main(String[] args) throws IOException{
        Reader r = new FileReader("D://java网络编程//第二章//reader.txt");
        char[] i = new char[3];
        int num = 0;
        while((num = r.read(i))!= -1){
            System.out.println(new String(i));
        }
        r.close();
    }
}

结果:
在这里插入图片描述

**read(char[],offset,len)**方法展示:

public class ReaderDemo3 {
    public static void main(String[] args) throws IOException {
        Reader r = new FileReader("D://java网络编程//第二章//reader.txt");
        char[] i = new char[3];
        int num = 0;
        while((num = r.read(i,0,3))!= -1){
            System.out.println(new String(i));
        }
        r.close();
    }
}

结果:
在这里插入图片描述
long skip(int)方法展示:

public static void main(String[] args) throws IOException {
    Reader r = new FileReader("D://java网络编程//第二章//reader.txt");
    char[] i = new char[3];
    int num = 0;
    long num1 = 0;
    num1 = r.skip(3);
    System.out.println(num1);
    while((num = r.read(i))!= -1){
        System.out.println(new String(i));
    }
    r.close();
}

结果:
结果

Writer流

继承自Writer的流都是用于程序中输出数据,且数据的单位为字符(16bit);下图中深色为节点流,浅色为处理流

Write流

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
    //将输出流中缓存的数据全部写入到目的地

代码展示

同上面的OutputStream类似
write() 方法展示:

FileWriter write= null;
try{
    write = new FileWriter("D:\\java网络编程\\第二章\\test1.txt");
}catch(Exception e){
    System.err.println(e.getMessage());
}

Scanner scan = new Scanner(System.in);
try{
    write.write(scan.nextInt());
    write.flush();
    write.close();
}catch(Exception e1){
    System.out.println(e1.getMessage());
}

在控制栏中输入了121,也就是y的ASCII码,得到结果::

write(char[]) 方法展示:

FileWriter write = null;
try{
    write = new FileWriter("D:\\java网络编程\\第二章\\test1.txt");
}catch(Exception e){
    System.out.println(e.getMessage());
}

char[] c = new char[3];
for(int i = 0;i<3;i++){
    Scanner scan = new Scanner(System.in);
    c[i] = scan.next().charAt(0);
}

try{
    write.write(c);
    write.flush();
    write.close();
}catch(Exception e1){
    System.out.println(e1.getMessage());
}

由于Scanner的返回值是String类型,无法直接放入char数组c中,所以这里用.charAt()方法,将String的第一位输入到c中

在控制栏中输入,你,我,他,(中间是回车)得到结果:
在这里插入图片描述
同理write(char[],offset,len)方法,这里就不多展示

write(String string) 方法展示:

Scanner scan = new Scanner(System.in);
try{
    write.write(scan.next());
    write.flush();
    write.close();
}catch(Exception e1){
    System.out.println(e1.getMessage());
}

在控制台中输入你我他123abc(连续的)
得到结果:
在这里插入图片描述

write(String ,offset,len方法同理,不予演示

节点流

以File这个类型作为讲解节点流的典型代表

FileInputStream和FileoutputStream分别继承自InputStream和OutputStream用于向文件中输入和输出字节

注意

  • 在实例化FileInputStream和FileOutputStream流时要用try-catch语句以处理其可能抛出的FileNotFoundException
  • 在读写数据时也要用try-catch语句以处理可能抛出的IOException
  • FileNotFoundException是IOException的子类

常用构造方法

  • public FileInputStream(File file);
    //通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定
  • public FileInputStream (String name);
    //通过打开一个到实际文件的链接来创建一个FileInputStream,该文件通过文件系统中的路径名name指定
  • public FileOutputStream(File file);
    创建一个向指定File对象表示的文件中写入数据的文件输出流
  • public FileOutputStream(File file ,boolean append);
    创建一个向指定File对象表示的文件中写入数据的文件输出流,如果第二个参数为true,则将字节写入文件末尾处,而不是写入文件开始处
  • public FileOutputStream(String name);
    创建一个具有指定名称的文件中写入数据的输出文件流
  • public FileOutputStream(String name,boolean append);
    创建一个向具有指定name的文件中写入数据的输出文件流。如果第二个参数为true,则将字节写入文件的末尾处,而不是写入文件开始处

同理,这些基本方法也可以套用到FileWriter和FileReader里

代码实现

public class FileInputStreamDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("D://java网络编程//第二章//test.txt");
        File file1 = new File("D://java网络编程//第二章//test1.txt");
        FileInputStream in = new FileInputStream(file);
        FileOutputStream out = new FileOutputStream(file,true);
        byte[] b = new byte[in.available()];
        int length = 0;

        while ((length = in.read(b)) != -1) {
            System.out.print(new String(b));
        }

        in.close();
    }
}

实例测试

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里面");
    }
}

就是简单的把内容从文件a复制到文件b中

用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();
        }
    }

这里写入的是16位的整数,查看文件时会发现都是按一定规律排序的,而不是数字,可以把这里的write方法理解为多了一步,将数字转换为字符的步骤

处理流

缓冲流(Buffering)

定义

  • 带有缓冲区的,缓冲流就是内存里面的一小块区域,读写数据时都是先把数据放到这块缓冲区域里面,减少IO对硬盘的访问次数,保护我们的硬盘
  • 先把数据放置到缓冲区上,等到缓冲区满了以后,再一次吧缓冲区里面的数据写入到硬盘上或者读出来,这样可以有效地减少对硬盘的访问次数,有利于保护我们的硬盘
  • 缓冲输入流支持其父类的mark和reset方法
  • BufferedReader提供了readLine方法用于读取一行字符串(以\r或\n分隔),BufferedWriter提供了newLine用于写入一个行分隔符。
  • 缓冲输出流,使用flush方法将会使内存中的数据立刻写出

缓冲流实例解析

  • 往文件写入数据时,直接从节点流FileWriter写入觉得不好写,因此在节点流的外部报了一层处理流BufferedWriter,这样写入数据时是先通过处理流把数据写入到缓冲区(Buffer)里面,再通过节点流写入到文件
  • 读取文件里面的数据时,通过节点流FileReader,直接读取数据是一个一个字符地读取,这样读取的效率太慢了,因此在节点流FileReader外部包了一层处理流BufferedReader处理流存放到内存的缓冲区里面,然后再使用flush()方法把缓冲区里面的数据立刻写出来
  • 缓冲流要“套接”在相应的节点流之上,对读写的数据提供了级冲的功能,提高了读写的效率,同时增加了一些新的方法

代码演示

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();
        }
    }
}

没搞懂这个mark里面的readlimit有啥用

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();
        }
    }
}

static String valueOf(double) 方法可以将double类型变成String
Math.Random()方法不加参数,范围是0~1
newLine()方法使得每写入一个字符就换一次行

转换流

  • InputStreamReader和OutputStreamWriter用于字节数据数据之间转换
  • InputStreamReader需要和InputStream套接,OutputStreamWriter需要和OutputStream套接
  • 转换流在构造时可以指定其编码集合
  • 转换流有两种,一种叫InputStreamReader,另一种叫OutputStreamWriter。
  • 如果用一个FileOutputStream流往文件里面写东西, 得要一个字节一个字节地写进去,但是如果我们在FileOutputStream流上面套上一个字符转换流,那我们就可以一个字符串一个字符串地写进去

代码实例

OutputStreamWriter实例
public class TestOutputStreamWriter {
    public static void main(String args[]) {
        try {
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D://java网络编程//第二章//test.txt"));
            osw.write("MircosoftsunIBMOracleApplet");
// 把字符串写入到指定的文件中去
            System.out.println(osw.getEncoding());
// 使用getEncoding()方法取得当前系统的默认字符编码
            osw.close();
            osw = new OutputStreamWriter(new FileOutputStream("D://java网络编程//第二章//test.txt", true), "ISO8859_1");
            // 如果在调用FileOutputStream的构造方法时没有加入true,那么新加入的字符串就会替换掉原来写入的字符串,在调用构造方法时指定了字符的编码
            osw.write("MircosoftsunIBMOracleApplet");// 再次向指定的文件写入字符串,新写入的字符串加入到原来字符串的后面
            System.out.println(osw.getEncoding());
            osw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用getEncoding()方法获取当前系统的默认字符编码
在调用FileOutputStream的构造方法时,可以指定字符的编码方式

InputStreamReader实例
package 转换流;

import java.io.*;
public class TestInputStreamReader{
    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();
        }
    }
}

equalsIgnoreCase()方法可以对比变量的内容是否和预设的内容相同

数据流

  • DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,它属于处理流需要分别“套接”在InputStream和OutputStream类型的节点流上
  • DataInputStream和DataOutputStream提供了可以存取与机器无关的JAVA原始类型数据等方法

代码实现

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;

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();
		}
	}
}

在调用构造方法时,datastream就会在内存里面创建一个数组,类型应该取决于data使用的类型和流的类型(猜测)
在这里ByteArrayOutputStream就是创建一个Byte类型的字节数组,套接在OutputStream上可以处理int、double等类型的数据
用writeDouble()方法可以把double类型的数据写入Byte数组中
用writeBoolen()方法可以把boolen类型的数据写入Byte数组中
在调用ByteArrayInputStream的构造方法时,通过toByteArray()方法访问之前baos的数组
再调用read方法读取存储在数组中的数据,这里的读取顺序不能更改,一定要什么先放入数组,先读什么,否则会打印出不正确的结果

打印流(Print)

  • PrintWriter和PrintStream都属于输出流,分别针对于字符和字节。PrintWriter和PrintStream提供了重载的print
  • Println方法用于多种数据类型的输出
  • PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriter和PrintStream有自动flush功能

代码实现

/*这个小程序是重新设置打印输出的窗口,
 * 把默认在命令行窗口输出打印内容设置成其他指定的打印显示窗口*/
import java.io.FileOutputStream;
import java.io.PrintStream;

public class TestPrintStream {
	public static void main(String args[]) {
		PrintStream ps = null;
		try {
			FileOutputStream fos = new FileOutputStream("D:/CS/tmp/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 <= 60000; c++) {
				System.out.print(c + "\t");// 把世界各国的文字打印到log.txt这个文件中去
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

setOut()方法将原本System.out.print()方法输出的位置改成了我们选择的路径
打印流不将结果打印在命令行界面,而是直接将结果打印到设置的路径
可以用于多种数据类型的输出
会自动flush()

对象流(Object)

直接将Object写入或读出

  • transient关键字:transient透明的,用它来修饰的成员变量在序列化的时候不予考虑。也就是当成不存在
  • serializable接口:标志性接口,通过这个接口标记的类的对象可以被序列化,并且是由JKD帮控制这个类的对象怎么序列化
  • externalizable接口:通过这个接口标记的类就可以自己控制对象的序列化

代码实现

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

public class TestObjectIo {
	public static void main(String args[]) {
		T t = new T();
		t.k = 8;// 把k的值修改为8
		try {
			FileOutputStream fos = new FileOutputStream("D:/CS/tmp/TestObjectIo.txt");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			// ObjectOutputStream流专门用来处理Object的,在fos流的外面套接ObjectOutputStream流就可以直接把一个Object写进去
			oos.writeObject(t);// 直接把一个t对象写入到指定的文件里面
			oos.flush();
			oos.close();
			FileInputStream fis = new FileInputStream("D:/CS/tmp/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关键字,那么这个变量就会被当作是透明的,即不存在。
}

Serializable接口意思为可序列化的,要想将一个类的对象序列化成一个字节流就必须实现该接口
该接口没有定义方法,只能用作标记,只给编辑器看
在构造了一个对象t后,用writeObject()方法写入到文件中,用readObject()方法读出,新建一个T类型对象接收,通过访问他的变量,即可得到结果
如果将结果前加上transient关键词,则被当做不存在,在访问时,结果会返回0

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-10 10:55:44  更:2021-12-10 10:55:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:35:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码