天天看点

JAVA 输入输出流

Java中把不同的输入输出源(键盘,文件,网络)抽象为流。

流可分为输入输出流。

流又分为字符流和字节流两大类。

Java输入流主要是由InputStream和Reader作为基类。输出流主要是OutputStream和Writer作为基类。

它们都是抽象基类无法创建实例。

字节流主要以InputStream和OutputStream作为基类。而字符流则主要以Reader和Writer作为基类。

可以从一个特定的IO设备(如键盘,网络)读写的流成为字节流,会和文件关联。也称为低级流(Low Level Stream)。

对一个流进行封装后的流称为处理流,也成为高级流。

InputStream 和 Reader分别有一个用于读取文件的输入流:FileInputStream 和 FileReader,它们都是字节流。

--------------------------------------------------------------------------------

InputStream包含的三个方法:

(1)int read()   读取单个字节。

(2)int read(byte[] b) 最多读取b.length的字节,并将其存储在数组b中。返回实际读取的字节数。

(3)int read(byte[] b,int of,int len) 此时读取的起点从off开始。

Reader的三个方法

(1)int read() 读取单个字符,字符数据可以直接转换为int类型。

(2)int read(char[] cbuf) 最多读取cbuf.length个字符

(3)int read(char[] cbuf,int off,int len) 从off位置开始读。

InputStream和Reader还支持移动记录指针:

(1)void mark(int readAheadLimit):  在记录指针当前位置记录一个标记(mark)

(2)boolean markSupport(): 判断当前流是否支持记录标记;

(3)void reset(): 将记录指针重定位到上一个标记。

(4)long skip(long n): 将记录指针向前移动n个字节/字符

----------------------------------------------------------------------------------

OutputStream 和 Writer都包含如下三个方法:

(1)void write(int c): 将指定字节/字符输出到流中。

(2)void write(byte[]/char[] buf): 将字节数组/字符数组输出到流中

(3)void write(byte[]/char[] buf, int off, int len): 将字节数组/字符数组从off位置开始,长度为len的字节/字符输出到流中。

此外,因为字符流以字符为单位,所以Writer还支持用字符串来代替字符数组。包含如下方法:

(1)void write(Strng str): 将字符串包含的字符输出到流中

(2)void write(Sring str,int off,int len): 将字符串从off位置开始,长度为len的字符输出到流中。

try {
      /** 获取文件输入流 */
      FileInputStream fis = new FileInputStream(file);

      /** 读取文件 */
      while ((length = fis.read(buffer)) > 0) {

        // 需要将字符数组转化为字符串后输出,不然输出的是乱码,转成字符串后中文仍是乱码
        System.out.println("----" + buffer);
        System.out.println("----" + new String(buffer, "utf-8"));
        System.out.println("----" + new String(buffer, 0, length));// offset

      }

    } catch (FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }      

============================================

上面介绍了输入输出流的4个抽象基类,并介绍了4个访问文件节点流的方法。使用比较繁琐。

处理流进行输入输出更简单,效率也更高。

通常认为字节流要比字符流更为强大,因为计算机中所以数据都是二进制的,而字节流可以处理所有二进制文件。但转换成字符就复杂了。所以一般:如果输入输出是文本内容则用字符流,如果输入输出是二进制,则用字节流。

四个抽象基类:            InputStream OutputStream Reader Writer

对应四个节点流方法: FileInputStream FileOutputStream FileReader FileWriter

处理流 :                      PrintStream 用来包装InputStream (包括FileInputStream) 如果需要输入文本,最好就用处理流。关闭上层的处理流,系统会自动关闭对应的节点流。

转换流 :                      InputStreamReader : 把字节流转换成字符输入流 InputStreamWriter 把字节流转换成字符输出流

​ 

System.in 代表键盘输入流,但其是Inputstream的实例,使用不方便,可以包装成InputStreamReader 将其转换为字符输入流,普通的Reader读取内容时不方便,可以转化为BufferReader利用BufferReader的readLine()可以一次读取一行。

/** 用转换流就可以不乱码了。windows使用的gbk,linux平台上中文一般utf-8. 根据tmp.txt的编码类型来选择 */
      fis = new FileInputStream(file);
      InputStreamReader reader = new InputStreamReader(fis, "gbk");
      BufferedReader br = new BufferedReader(reader);
      String readStr = null;
      while ((readStr = br.readLine()) != null) {
        System.out.println("-----: " + readStr);
      }      

自动解析编码:

public String convertCodeAndGetText(String str_filepath) {// 转码

        File file = new File(str_filepath);
        BufferedReader reader;
        String text = "";
        try {
                // FileReader f_reader = new FileReader(file);
                // BufferedReader reader = new BufferedReader(f_reader);
                FileInputStream fis = new FileInputStream(file);
                BufferedInputStream in = new BufferedInputStream(fis);
                in.mark(4);
                byte[] first3bytes = new byte[3];
                in.read(first3bytes);//找到文档的前三个字节并自动判断文档类型。
                in.reset();
                if (first3bytes[0] == (byte) 0xEF && first3bytes[1] == (byte) 0xBB
                                && first3bytes[2] == (byte) 0xBF) {// utf-8

                        reader = new BufferedReader(new InputStreamReader(in, "utf-8"));

                } else if (first3bytes[0] == (byte) 0xFF
                                && first3bytes[1] == (byte) 0xFE) {

                        reader = new BufferedReader(
                                        new InputStreamReader(in, "unicode"));
                } else if (first3bytes[0] == (byte) 0xFE
                                && first3bytes[1] == (byte) 0xFF) {

                        reader = new BufferedReader(new InputStreamReader(in,
                                        "utf-16be"));
                } else if (first3bytes[0] == (byte) 0xFF
                                && first3bytes[1] == (byte) 0xFF) {

                        reader = new BufferedReader(new InputStreamReader(in,
                                        "utf-16le"));
                } else {

                        reader = new BufferedReader(new InputStreamReader(in, "GBK"));
                }
                String str = reader.readLine();

                while (str != null) {
                        text = text + str + "/n";
                        str = reader.readLine();

                }
                reader.close();

        } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
        } catch (IOException e) {
                e.printStackTrace();
        }
        return text;
}