Java IO学习笔记(一)

基础知识
1、流的分类  所有的流都位于java.io包
     根据流的方向分:输入流和输出流
     根据处理数据的单位分:字节流和字符流
     根据功能不同分:节点流和处理流
                                               各种流的抽象类,所有流都继承于这四个流
  字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer
注:写是往程序外写,用的是输出流;读是往程序里读,用输入流;输入流、输出流都是站在程序的角度来说
字节流:按照最原始的形式读,读出来的就是0、1串,但是是一个字节一个字节(即8位8位的)的读。
字符流是一个字符一个字符(一个字符是2个字节16位)的读。
节点流 :直接连接到数据源,从数据源上直接读写数据(如:文件、内存)
处理流:用于处理节点流,连接在已有的流上(包括节点流和处理流),用于处理流的数据,为程序提供更强大的读写功能,一个流的外面可以套多层处理流。
 
2、InputStream的基本方法
  继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8位),下图中深色为字节流,浅色为处理流。
 
(1)int read() throws IOException:读取一个字节并以整数的形式返回(0-255),方法的返回值即为督导如果返回-1表示已经读到了输入流的末尾。
(2)int read(byte[] buffer) throws IOException:读取一个字节并存储到一个数组buffer,把字节比作水滴,流为水流,buffer 相当于水桶, 该方法就相当于把一滴一滴的水滴接收后存放到水桶里,读满buffer字节处理后再对读到的数据进行处理(装满水桶),int返回的是实际读取的字节数,返回的是实际读了多少个字节,如果读取前已经到了输入流的末尾返回-1.
(3)int read(byte[] buffer, int offset, int length) throws IOException, 读取length个字节并存到字节数组buffer里,从buffer的offset位置开始存,返回的是实际读了多少个字节,返回的int可以比length小。
(4)void close() throws IOException 关闭流释放内存资源。
(5)long skip(long n) throws IOException 跳过多少了字节不读。
 
3、outputStream的基本方法
继承自outputStream的流是用于程序中输出数据,且数据的单位为字节;下图中深色为字节流,浅色为处理流
(1)void write(int b) throws IOException; 向输出流写入一个字节数据,该字节数据为参数b的低8位。
(2)void write(byte[] b) throws IOException; 将一个字节类型的数组中的数据写入输出流。
(3)void write(byte[] b, int off, int len) throws IOException; 将一个字节类型的数组中的从指定位置off开始的len个字节写入到输出流。
(4)void close() throws IOException; 关闭流释放内存资源
(5)void flush() throws IOException; 重要方法,当用close()方法关闭输出流时,有可能数据还没有完全写入到输出流,输出流就被粗暴地关闭了,因此在IO编程时要养成良好的习惯,关闭输出流之前务必调用flush()方法,将输出流缓冲中的数据全部写出到目的地。根据帮助文档,对于outputStream来说虽然有flush方法,且编程时通常会写flush方法,但对于outputStream及其子类该方法并未起作用。
4、Reader的基本方法
     继承自Reader的流都是用于向程序中输入数据,与InputStream的不同之处在于数据的单位为字符(16 bit),比如在处理中文字符的时候,中文字符占两个字节,如果采用字节流就有可能出现读了半个汉字的情况,因此字符流也很有必要。下图中深色为节点流,浅色为处理流。
 
 
 
5、Writer的基本方法
     继承自writer的流都是用于向程序中输入数据,与outputStream的不同之处在于数据的单位为字符(16 bit),比如在处理中文字符的时候,中文字符占两个字节,如果采用字节流就有可能出现写了半个汉字的情况,因此字符流也很有必要。下图中深色为节点流,浅色为处理流。
 
      这里void write(String string)方法是将一个字符串中的字符写入到输出流,其中的实现过程是调用了java.lang.String的toCharArray()方法将字符串转换成了字符数组写入到输出流中。
      void write(String string, int offset, int length) throws IOException 是从String字符串的offset位置开始,将length个字符写入到输出流。
5、流的各子类以及它们的基本方法
(1)文件处理
FileInputStream和FileOutputStream:
分别继承自InputStream和OutputStream,用于向文件中输入和输出字节。
常用构造方法:
FileInputStream用于从文件中读取数据的原始字节,比如读取图片,如果要读取字符类型的数据,需要用FileReader
FileInputStream(String name) throws FileNotFoundException 创建一个文件输入流,同时连接都系统中的名为name的文件上。
FileInputStream(File file) throws FileNotFoundException 创建一个文件输入流,同时连接到指定文件上。
FileOutputStream(String name) throws FileNotFoundException 创建一个文件输出流,并且将要输出的数据写入到名称指定的文件上。
FileOutputStream(File file) throws FileNotFoundException 创建一个文件输出流,并且将要输出的数据写入到指定的文件上。FileOutputStream当文件不存在时会自动创建文件,但不会自动创建不存在的路径。如果路径存不存在 、文件不存在且不能够被创建,文件存在但打不开,会抛出FileNotFoundException异常。
FileOutputStream(String name, boolean append) throws FileNotFoundException
FileOutputStream( File file, boolean append) throws FileNotFoundException
FileInputStream和FileOutputStream类支持其父类InputStream和OutputStream提供的所有读写方法。
注意:在实例化FileInputStream和FileOutputStream流时一定要用try...catch语句包起来用以处理可能抛出的FileNotFoundException,在调用读写方法时也一定要用try...catch语句包起来用以处理可能抛出的IOException,FileNotFoundException是IOException的子类。
练习小程序I:用字节输入流读文件中的内容
package test.io.file;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class FileInputStreamTest {
    public static void main(String args[]){
        FileInputStream  fin = null;
        int b = 0;
        try{
            //路径的“\”如果直接用反斜杠“”会提示错误,这里要用两个反斜杠“\”或者一个正斜杠“/”
            fin = new FileInputStream("E:\技术学习\java\test\Socket\test.txt");
        }catch(FileNotFoundException e){
            e.printStackTrace(); //将错误信息打印到控制台,不写就不会打印错误信息在控制台。
            System.out.println("文件不存在");
        }
        try {
            while((b= fin.read()) != -1){
                //System.out.print(b);
                System.out.print((char)b);
            }
            fin.close();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件读取错误");
        }
    }
}
如果用fileInputStream.read()读取中文汉字会乱码,因为fileInputStream为字节流,只能一个字节一个字节的读取内容,每个汉字占两个字节,读取出的都是半个汉字,识别不出,所以乱码。
注意:在练习的过程中出现一个奇怪的错误:练习的时候程序中int b = 0;这一行没有,下面try程序块中的代码为:
while(fin.read() != -1){
          System.out.print((char)fin.read() );
 }
会得到一个奇怪的结果:控制台上只打印出了位置为双数的内容。比如输入abcdefghijklmnopqrstuvwxyz这26个英文字母,打印结果为:
bdfhjlnprtvxz
这是因为每执行一次fileInputStream.read()方法就会去读取一个字节的内容,在while的条件里执行了一次fin.read(),读出的结果只是判断没有打印,而{}中的System.out.print((char)fin.read() );又执行了一次read方法,读出的是下一个字节的内容,因此输出的是下一个字节的内容,单数位置的字节就被空出来了。
 
练习小程序2:文件内容复制
package test.io.file;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutputStreamTest {
     public static void main(String args[]){
           FileOutputStream fos = null;
           FileInputStream fis = null;
           int b = 0;
           try{
                fis = new FileInputStream("E:/技术学习/java/test/Socket/TalkClient.java");
                fos = new FileOutputStream("E:/技术学习/java/test/Socket/testtest.txt");
           }catch(FileNotFoundException e){
                e.printStackTrace();
                System.out.println("文件不存在或文件打不开");
           }
           
           try {
                while((b=fis.read()) != -1){
                     fos.write(b);
                }
                fos.flush();
                fis.close();
                fos.close();
                System.out.println("文件已复制");
           } catch (IOException e) {
                e.printStackTrace();
                System.out.println("文件读写错误");
           }
     }
}
练习小程序3:字符流读文件
package test.io.file;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class FileReaderTest {
     public static void main(String[] agrs){
           FileReader fr = null;
           int b = 0;
           try {
                fr = new FileReader("E:/技术学习/java/test/Socket/TalkClient.java");
           } catch (FileNotFoundException e) {
                e.printStackTrace();
                System.out.println("文件不存在");
           }
           try {
                while((b = fr.read()) != -1){
                     System.out.print((char)b);
                }
                fr.close();
           } catch (IOException e) {
                e.printStackTrace();
                System.out.println("读文件错误");
           }
     }
}
练习小程序4:字符流写文件
package test.io.file;
import java.io.FileWriter;
import java.io.IOException;
public class FileWriterTest {
     public static void main(String args[]){
           FileWriter fw = null;
           try {
                fw = new FileWriter("E:/技术学习/java/test/Socket/test1.txt");
           } catch (IOException e) {
                e.printStackTrace();
           }
           try {
                for(int i=0; i<5000; i++){
                     fw.write(i);
                }
                fw.flush();
                fw.close();
                System.out.println("写入文件内容成功");
           } catch (IOException e) {
                e.printStackTrace();
           } 
     }
}
原文地址:https://www.cnblogs.com/bjh1117/p/6378820.html