Java IO流

IO流

1.File类

  • java.io.File类: 文件和文件目录路径的抽象表示形式,与平台无关

    1.java所有的文件操作都在java.io这个包下操作。

    2.File表示一个文件或者一个文件目录

  • File能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。

  • 构造函数:

      • public File(String pathname) 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
        • 绝对路径: 是一个固定的路径,从盘符开始

        • 相对路径: 是相对于某个位置开始

          1.String pathname:字符串路径名。
          
          

    2.绝对路径:从盘符开始,完整的描述文件位置的路径就是绝对路径。(D:\test\java-demo1\a.txt)

    3.相对路径:java中默认的当前路径在user.dir(项目)中存储。(.\java-demo1\a.txt)
      ```
    
      • public File(String parent,String child) 以parent为父路径, child为子路径创建File对象。
      • public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象
  • 路径中的每级目录之间用一个路径分隔符隔开。

    • windows和DOS系统默认使用“\”来表示
    • UNIX和URL使用“/”来表示
  • File类的使用:

    • 产生文件:

    • 1.File file1 = new File("D:\\\file-test\\\a.txt");
      2.File file2 = new File("D:\\\file-test\\\\","a.txt");
      3.File filePath = new File("D:\\file-test\\");
           File file3 = new File(filePath,"a.txt");
      4.URI uri=new URI("file:///D:/file-test/a.txt"); 
            file4 = new File(uri);            
            file.createNewFile();
      
    • 产生文件目录:

      • public boolean mkdir() : 创建文件目录。 如果此文件目录存在, 就不创建。如果此文件目录的上层目录不存在, 也不创建。

      • //只能产生文件的当前目录
        file4.mkdir();
        //判断文件目录是否存在
        if (!filePath.exists()){//如果不存在
                    filePath.mkdir();//产生当前目录
                }
        
        • public boolean mkdirs() : 创建文件目录。 如果上层文件目录不存在, 一并创建.
      • //产生所有的子目录
        file4.mkdirs();
        
    • 删除文件:

    • public boolean delete(): 删除文件或者文件夹。

          • 删除注意事项:Java中的删除不走回收站。要删除一个文件目录, 请注意该文件目录内不能包含文件或者文件目录
    • file4.delete();
      
    • 打印文件目录:
  • //打印用户默认目录
    System.out.println(System.getPropertie(user.dir));
    //打印所有System参数的文件目录
    System.out.println(System.getProperties());
    //打印项目的运行目录
    System.out.println(FileDemo1.class.getResource("/").getPath());//一般文件和配置文件都放在class.path中
    

File类的获取功能

    • public String getAbsolutePath(): 获取绝对路径
    • public String getPath() : 获取路径
    • public String getName() : 获取名称
    • public String getParent(): 获取上层文件目录路径。 若无, 返回null
    • public long length() : 获取文件长度(即:字节数) 。 不能获取目录的长度。
    • public long lastModified() : 获取最后一次的修改时间, 毫秒值
    • public String[] list() : 获取指定目录下的所有文件或者文件目录的名称数组
    • public File[] listFiles() : 获取指定目录下的所有文件或者文件目录的File数组
  • //获取文件的绝对路径
    file4.getAbsolutePath();
    //获取文件的路径
    file4.getPath();
    //获取文件的名称
    file4.getName();
    //获取文件长度
    file4.length();
    //获取指定目录下的所有文件或者文件目录的名称数组
     String[] files = filePath.list();
            for (String s : files) {
                System.out.println(s);
            }
    
public class FileDemo1 {
    /**
     * File:表示文件或者目录
     * @param args
     */
    public static void main(String[] args) throws IOException {
        File file1 = new File("D:\\file-test\\a.txt");
        System.out.println(File.separator);
        File file2 = new File("D:\\file-test\\","a.txt");
        File filePath = new File("D:\\file-test\\");
        File file3 = new File(filePath,"a.txt");

        //产生目录
        //file4.mkdir();//产生当前目录
        if (!filePath.exists()){
            filePath.mkdir();//产生当前目录
        }
        file4.createNewFile();
        //默认的文件目录
        System.out.println(System.getProperties());
        File file5 = new File("a.txt");//user.dir,一般只在测试使用
        file5.createNewFile();
        //删除文件
        //file5.delete();
        //获取绝对路径
        System.out.println(file5.getAbsolutePath());
        //获取文件的路径
        System.out.println(file5.getPath());
        //获取文件的名称
        System.out.println(file5.getName());
        //获取文件长度
        System.out.println(file5.length());
        System.out.println("------------");
        String[] files = filePath.list();
        //获取指定目录下的所有文件或者文件目录的名称数组
        for (String s : files) {
            System.out.println(s);
        }

    }
}

2.IO流原理及流的分类

  1. Java IO原理
  • I/O是Input/Output的缩写, I/O技术是非常实用的技术, 用于处理设备之间的数据传输。 如读/写文件,网络通讯等。

  • BIO(阻塞IO),NIO,AIO

  • Java程序中,对于数据的输入/输出操作以“流(stream)” 的方式进行。

  • java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。

  • 输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。

  • 输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HDpdBHu8-1692186060400)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230813153639032.png)]

  1. IO流的分类
  • 按操作数据单位不同分为: 字节流(8 bit),字符流
  • 按数据流的流向不同分为: 输入流,输出流
字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter

image.png

3.字符流和字节流

1.InputStream & Reader

  • InputStream

    • int read() 从输入流中读取数据的下一个字节。 返回 0 到 255 范围内的 int 字节值。 如果因为已经到达流末尾而没有可用的字节, 则返回值 -1。
    • int read(byte[] b) 从此输入流中将最多 b.length 个字节的数据读入一个 byte 数组中。 如果因为已经到达流末尾而没有可用的字节, 则返回值 -1。 否则以整数形式返回实际读取的字节数。
    • int read(byte[] b, int off,int len) 将输入流中最多 len 个数据字节读入 byte 数组。 尝试读取 len 个字节, 但读取的字节也可能小于该值。 以整数形式返回实际读取的字节数。 如果因为流位于文件末尾而没有可用的字节, 则返回值 -1。
    • public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。
    //字节输入流
    .close() // 关闭此流并释放与此流相关的所有系统资源
    .read() // 从输入流中读取数据的下一个字节
    .read(byte[] b) // 从输入流中读取一批字节,并存储到一个字节数组b中
    
    //文件字节输入流
    FileInputStream(File file) // 读取源是一个文件
    FileInputStream(String name) // 读取源是一个路径
    
  • Reader

    • int read() 读取单个字符。 作为整数读取的字符, 范围在 0 到 65535 之间 (0x00-0xffff)(2个字节的Unicode码) , 如果已到达流的末尾, 则返回 -1
    • int read(char[] cbuf) 将字符读入数组。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。
    • int read(char[] cbuf,int off,int len) 将字符读入数组的某一部分。 存到数组cbuf中, 从off处开始存储, 最多读len个字符。 如果已到达流的末尾, 则返回 -1。 否则返回本次读取的字符数。
    • public void close() throws IOException 关闭此输入流并释放与该流关联的所有系统资源。
    //字符输入流
    .close() // 关闭此流并释放与此流相关的所有系统资源
    .read() // 从输入流中读取一个字符
    .read(char[] cbuf) // 从输入流中读取一批字符,并放入字符数组cbuf中
    
    //文件字符输入流
    FileReader(File file) // 读取源是一个文件
    FileReader(String fileName) // 读取源是一个路径
    

2.OutputStream & Writer

  • OutputStream

    • void write(int b) 将指定的字节写入此输出流。 write 的常规协定是:向输出流写入一个字节。 要写入的字节是参数 b 的八个低位。 b 的 24 个高位将被忽略。 即写入0~255范围的。
    • void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。 write(b) 的常规协定是:应该与调用 write(b, 0, b.length) 的效果完全相同。
    • void write(byte[] b,int off,int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。
    • public void flush()throws IOException 刷新此输出流并强制写出所有缓冲的输出字节, 调用此方法指示应将这些字节立即写入它们预期的目标。
    • public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。
    //字节输出流
    .close() // 关闭此流并释放与此流相关的所有系统资源
    .flush() // 刷新此流并强制所有缓冲的输出字节被写出
    .write(byte[] b) // 将b.length长度的字节数组写入到输出流
    .write(byte b[], int off, int len) // 从指定的字节数组b,从off偏移量开始,写入len长度的字节
    .write(int b) // 将指定的字节输出
    
    //文件字节输出流
    FileOutputStream(File file) // 输出的目的地是一个文件
    FileOutputStream(String name) // 输出的目的地是一个路径
    FileOutputStream(File file, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
    FileOutputStream(String name, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
    
  • Writer

    • void write(int c) 写入单个字符。 要写入的字符包含在给定整数值的 16 个低位中, 16 高位被忽略。 即写入0 到 65535 之间的Unicode码。
    • void write(char[] cbuf) 写入字符数组。
    • void write(char[] cbuf,int off,int len) 写入字符数组的某一部分。 从off开始, 写入len个字符
    • void write(String str) 写入字符串。
    • void write(String str,int off,int len) 写入字符串的某一部分。
    • void flush() 刷新该流的缓冲, 则立即将它们写入预期目标。
    • public void close() throws IOException 关闭此输出流并释放与该流关联的所有系统资源。
    //字符输出流
    .close() // 刷新并关闭此流
    .flush() // 刷新此流并强制所有缓冲的字符被写出
    .write(int c) // 写出一个字符
    .write(char[] cbuf) // 将指定的 cbuf.length长度的字符数组写到此输出流
    .write(char[] b, int off, int len) // 从指定的字符数组b,从off偏移量开始,写入len长度的字节
    .write(String str) // 写出一个字符串
    .write(String str, int off, int len) // 写入字符串的某一部分
    
    //文件字符输出流
    FileWriter(File file) // 输出源是一个文件
    FileWriter(String fileName) // 输出源是一个路径
    FileWriter(File file, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
    FileWriter(String fileName, boolean append) // boolean值代表是否需要续写,true为可续写,不会覆盖之前的文件,会往文件的结尾继续写数据,false为不可续写,文件名相同,会创建一个新的空白文件覆盖之前的文件
    

    关闭和刷新的区别

    flush :刷新缓冲区,把缓冲区中的数据刷新到文件,流对象可以继续使用。
    close :关闭流,释放系统资源。关闭前会刷新缓冲区。把缓冲区中的数据刷新到文件,关闭之后流对象就不能使用了
        记得关流,不然会一直占用
    
public class FileDemo2 {
   @Test
    public void test1(){
        try{//一个字符一个字符的读取
            FileReader reader = new FileReader("a.txt");
            //读取一个字符
            char c = (char) reader.read();
            System.out.println(c);
            int charInt = -1;//字符
            //读取一个字符,如果返回-1表示到达文件末尾
            while ((charInt = reader.read()) != -1){
                System.out.println((char)charInt);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    public void test2(){
       try {//多个字符多个字符的读取
           FileReader reader = new FileReader("a.txt");
           int length = -1;//读取的长度
           char[] buffer = new char[5];//读取5个字符
//           length = reader.read(buffer);
//           System.out.println(buffer);

           while ((length = reader.read(buffer)) != -1){
               System.out.println(new String(buffer, 0, length));
           }
       } catch (FileNotFoundException e) {
           e.printStackTrace();
       } catch (IOException e) {
           e.printStackTrace();
       }
    }
}
public class WriteDemo1 {
    @Test
    public void test1(){
        FileWriter out = null;
        try{
            out = new FileWriter("a.txt");
            out.write(97);
            out.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
    @Test
    public void test2(){
        FileReader in = null;
        FileWriter out = null;
        try {
            in = new FileReader("a.txt");
            out = new FileWriter("a.txt");
            int length = -1;
            char[] buffer = new char[5];
            while ((length = in.read(buffer)) != -1){
                out.write(buffer, 0, length);
            }
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
            }catch (IOException e){
                throw new RuntimeException(e);
            }
        }
    }
    @Test
    public void test3(){
        FileReader in =null;
        FileWriter out = null;
        try {
            in = new FileReader("a.jpg" );
            out = new FileWriter("a1.jpg");
            int length = -1;
            char[] buffer = new char[5];
            while ((length = in.read(buffer)) != -1){
                out.write(buffer, 0, length);
            }
            out.flush();
        } catch (IOException e) {
           e.printStackTrace();
        } finally {
            try {
                out.close();
            }catch (IOException e){
                throw new RuntimeException(e);
            }
        }
    }
}

4.缓冲流

  • 缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:

    • BufferedInputStream 和 BufferedOutputStream
    • BufferedReader 和 BufferedWriter
//字节缓冲流
BufferedInputStream(InputStream in) //创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
BufferedInputStream(InputStream in int size)// 创建具有指定缓冲区大小的 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
BufferedOutputStream(OutputStream out)//创建一个新的缓冲输出流,以将数据写入指定的底层输出流
BufferedOutputStream(OutputStream out, int size)//创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流
//字符缓冲流
//构造方法
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("a.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
//特有方法
BufferedReaderpublic String readLine(); //读一行文字。
BufferedWriterpublic void newLine(); //写一行行分隔符,由系统属性定义符号。
  • 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区

  • 非缓冲流

image.png

  • 缓冲流

image.png

public class BufferCopy {

    /**
     * 使用非缓冲流拷贝
     * @param from
     * @param to
     */
    public static void copyNoBuffer(String from, String to) {//把一个文件从文件夹中拷贝到另一个文件夹中
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
             //1k、1k的传输
            in = new FileInputStream(from);
            out = new FileOutputStream(to);

            int length = -1;
            byte[] buffer = new byte[1024];
            while ((length = in.read(buffer)) != -1) {
                out.write(buffer, 0, length);
            }
//            out.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                out.close(); //close会自动执行flush
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 使用缓冲流拷贝
     * @param from
     * @param to
     */
    public static void copyWithBuffer(String from, String to) {
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        try {  //默认值为8k
            in = new BufferedInputStream(new FileInputStream(from,) 1024 * 1024);
            out = new BufferedOutputStream(new FileOutputStream(to,) 1024 * 1024);

            int length = -1;
            byte[] buffer = new byte[1024];
            while ((length = in.read(buffer)) != -1) {
                out.write(buffer, 0, length);
            }
//            out.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                out.close(); //close会自动执行flush
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Test
    public void test1() {
        Long t1 = System.currentTimeMillis();
//        copyNoBuffer("d:\\a.mkv", "d:\\a1.mkv"); 20S
        copyWithBuffer("d:\\a.mkv", "d:\\a1.mkv"); 4S
        Long t2 = System.currentTimeMillis();
        System.out.println((t2 - t1) / 1000 );
    }


    /**
     * 字符缓冲流
     * @throws Exception
     */
    @Test
    public void test2() throws Exception {
        BufferedReader in = new BufferedReader(new FileReader("BufferCopy.txt"));
        BufferedWriter out = new BufferedWriter(new FileWriter("BufferCopy2.txt"));

        String line = null;
        //readLine():一行一行的读取
        while ((line = in.readLine()) != null) {
            out.write(line);
            out.newLine();
        }
        in.close();
        out.close();
    }

}

5.转换流

  • InputStreamReader

    • 实现将字节的输入流按指定字符集转换为字符的输入流。
    • 需要和InputStream“套接”。
    • 构造器
      • public InputStreamReader(InputStream in)
      • public InputSreamReader(InputStream in,String charsetName) 如: Reader isr = new InputStreamReader(System.in,”gbk”);
  • OutputStreamWriter

    • 实现将字符的输出流按指定字符集转换为字节的输出流。
    • 需要和OutputStream“套接”。
    • 构造器
      • public OutputStreamWriter(OutputStream out)
      • public OutputSreamWriter(OutputStream out,String charsetName)

转换流分类

InputStreamReader:将一个字节的输入流转换为字符的输入流
//构造方法
public inputStreamReader(inputStream in);//创建一个使用默认的字符集的字符流
public inputStreamReader(inputStream in,String charsetName);//创建一个指定字符集的字符流
OutputStreamWriter:将一个字符的输出流转换为字节的输出流
public OutputStreamWriter(OutputStream out);//创建一个使用平台默认的字符集的字符流
public OutputStreamWriter(OutputStream out,String charsetName);//创建一个指定的字符集的字符流
    @Test
    public void test1() throws Exception {
        //默认为UTF-8读取
        InputStream in = new FileInputStream("utf8.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        System.out.println(reader.readLine());

        //如果是GBK形式,需要指定一下字符集
        InputStream in = new FileInputStream("gbk.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(in, "gbk"));
        System.out.println(reader.readLine());

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值