IOStream

IO流

向Drunkbaby师傅学习

https://drun1baby.top/2022/05/30/Java-IO%E6%B5%81/

三种创建文件的方式

第一种:new File(String pathname)

File file = new File("D:\111_Javastudy\CreateFile\1.txt");  
file.createNewFile();

第二种:new File(File parent, String child)

File parentFile = new File("D:\111_Javastudy\CreateFile");  
File file = new File(parentFile, "2.txt");  
file.createNewFile(); 

第三种:new File(String parent, String child)

String parentFile = "D:\\111_Javastudy\\CreateFile";
File file = new File(file,"3.txt");
file.createNewFile();

image-20240905185350-hyzm7fa

获取文件信息的方式

package test.IO;  
  
import java.io.File;  
  
public class GetFileInfo {  
    public static void main(String[] args) {  
        getFileContents();  
 }  
  
    public static void getFileContents(){  
        File file = new File("Serialable/src/IOStream/CreateForFile/new1.txt");  
 System.out.println("文件名称为:" + file.getName());  
 System.out.println("文件的绝对路径为:" + file.getAbsolutePath());  
 System.out.println("文件的父级目录为:" + file.getParent());  
 System.out.println("文件的大小(字节)为:" + file.length());  
 System.out.println("这是不是一个文件:" + file.isFile());  
 System.out.println("这是不是一个目录:" + file.isDirectory());  
 }  
}

目录与文件操作

1.文件删除file.delete(文件)

File file = new File("D:\\111_Javastudy\\CreateFile\\3.txt");
System.out.println(file.delete()?"deleted":"failed");

2.目录删除file.delete(目录),这里有个小坑,只有空的目录才可以删除,不然会显示删除失败。

File file = new File("D:\\111_Javastudy\\testdelete");
System.out.println(file.delete()?"deleted":"failed");

3. 创建单级目录file.mkdir()

File file = new File("D:\\111_Javastudy\\testdelete");
System.out.println(file.mkdir()?"made":"failed");

4. 创建多级目录file.mkdirs()

File file = new File("D:\\111_Javastudy\\testdelete\aa\bb");
System.out.println(file.mkdirs()?"made":"failed");

文件流操作

1. Runtime 命令执行操作的 Payload

package test.IO;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

// 使用 Runtime 类进行命令执行
public class RuntimeExec {
    public static void main(String[] args) throws Exception {
        InputStream inputStream = Runtime.getRuntime().exec("whoami").getInputStream();
        byte[] cache = new byte[1024];  // 缓冲区,大小为1024字节,它充当了一个临时缓冲区,用来存储从 inputStream 中读取到的数据。在每次调用 inputStream.read(cache) 时,cache 中会填充最多 1024 字节的数据(除非数据不足 1024 字节)。如果流中的数据多于 1024 字节,那么读取将被分成多次。
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int readLen = 0; // 记录每次读取的字节数
        while ((readLen = inputStream.read(cache))!=-1){   //inputStream.read(cache) 会尝试从 inputStream 中读取数据,并将数据写入到 cache 缓冲区中。每次读取时,inputStream.read() 会返回读取的字节数,将其存储在 readLen 变量中。
            byteArrayOutputStream.write(cache, 0, readLen);  //将 cache 缓冲区中从索引 0 开始的 readLen 字节数据写入到 ByteArrayOutputStream 中。注意,并不是每次都会写入 1024 字节,readLen 决定了实际读取并写入的数据长度。
        }
        System.out.println(byteArrayOutputStream);
    }
}

其中,byte[] cache = new byte[1024]​ 用来缓存数据,我们结合这一串 Payload 来学习 Java IO 流甚好。

2. FileInputStream

read() 方法用来读取数据

read() 方法到底是啥样的呢,我们跳进去看看

read() 
	public int read() throws IOException 
	从此输入流中读取一个数据字节。

	如果没有输入可用,则此方法将阻塞。 

	指定者: 类 InputStream 中的 read 

	返回: 下一个数据字节;如果已到达文件末尾,则返回 -1。 

	抛出: IOException - 如果发生 I/O 错误。

之前我们用 file​ 的一系列操作读取过文件的信息,现在我们用 FileInputStream.read()​ 来读取文件内容。

package src.IOStream;  
  
import java.io.FileInputStream;  
import java.io.IOException;  
  
// 使用 FileInputStream.read 读取文件  
public class FileInputRead {  
    public static void main(String[] args) {  
        readFile();  
 }  
    public static void readFile(){  
        String filePath = "Serialable/src/IOStream/CreateForFile/new1.txt";  
 FileInputStream fileInputStream = null;  
 int readData = 0;  
 try{  
            fileInputStream = new FileInputStream(filePath);  
 while((readData = fileInputStream.read())!=-1){  
                System.out.print((char)readData);  
 }  
        } catch (IOException e){  
            e.printStackTrace();  
 } finally {  
            try{  
                fileInputStream.close();  
 } catch (IOException e){  
                e.printStackTrace();  
 }  
        }  
    }  
}

成功读取到文件内容,这里有个小坑,若我们 sout 的时候进行了换行,则每一个字符都会经过换行。而如果不设置换行,才是正常的输出。

也就是说System.out.print是正常输出,System.out.println会自动换行

image-20240905194619-y4zlv6i

image-20240905194639-oxasbhz

read(byte[] d) 方法用来返回字节数

允许在方法中添加一个字节数组。
这种方式很有意思,当我们设置缓冲区的值为 8 时,若文件中的字符长度超过了 8,则会换行输出。这和上面的换行实际上是异曲同工。

再回到之前我们讲的 Runtime​ 类进行命令执行的 Payload,在那里,我们设置的 Cache 缓冲区的值为 1024.

read(byte[] d) 方法

package src.IOStream;  
  
import java.io.FileInputStream;  
import java.io.IOException;  
  
// read(byte[] d) 方法,允许在方法中添加一个字节数组  
public class FileInputRead02 {  
    public static void main(String[] args) {  
        readFile();  
 }  
    public static void readFile(){  
        String filePath = "Serialable/src/IOStream/CreateForFile/new1.txt";  
 FileInputStream fileInputStream = null;  
 byte[] cache = new byte[8]; // 设置缓冲区,缓冲区大小为 8 字节  
 int readLen = 0;  
 try {  
            fileInputStream = new FileInputStream(filePath);  
 while((readLen = fileInputStream.read(cache)) != -1){  
                System.out.println(new String(cache, 0, readLen));  
 }  
        } catch (IOException e){  
                e.printStackTrace();  
 } finally {  
            try {  
                fileInputStream.close();  
 } catch (IOException e){  
                e.printStackTrace();  
 }  
        }  
    }  
}

这里的 while 会运行三次,会读取文件当中所有的字符。

image-20240907201550-4mdd7yd

3. FileOutputStream

往文件里面写数据
简单的 write(int b) 这里先不提

write(byte[] b) 方法

write(byte[] b)
public void write(byte[] b)
           throws IOException
将 b.length 个字节从指定 byte 数组写入此文件输出流中。
覆盖:
类 OutputStream 中的 write
参数:
b - 数据。
抛出:
IOException - 如果发生 I/O 错误。

我们尝试向文件当中写入数据,这里写代码的时候小心一点,容易踩坑的。

package test.IO;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class WriteFile {
    public static void main(String[] args){
        readFile();

    }
public static void readFile(){
        String filepath = "D:\\111_Javastudy\\CreateFile\\1.txt";
        FileOutputStream fileOutputStream = null;
        String content = "mixian mixian";
        try{
            fileOutputStream = new FileOutputStream(filepath);
//需要将content转换为byte类型
            fileOutputStream.write(content.getBytes());
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
        finally {
            try {
                fileOutputStream.close();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }



}

}

image-20240907202047-ev70r6j

write(byte[] b, int off, int len) 方法

  • 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。

这里的长度一定要与输入的字符相等。

package test.IO;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class WriteFile {
    public static void main(String[] args){
        readFile();

    }
public static void readFile(){
        String filepath = "D:\\111_Javastudy\\CreateFile\\1.txt";
        FileOutputStream fileOutputStream = null;
        String content = "mixian mixian";
        try{
            fileOutputStream = new FileOutputStream(filepath);
            fileOutputStream.write(content.getBytes(),0,10);
        }
        catch(FileNotFoundException e){
            e.printStackTrace();
        }
        catch(IOException e){
            e.printStackTrace();
        }
        finally {
            try {
                fileOutputStream.close();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }



}

}

这里仅输出10字符导致1.txt写入内容不全

image-20240907202238-hvmwrw2

追加写入

如果想要写入的数据不被覆盖,可以设置 FileOutputStream​ 的构造方法 append​ 参数设置为 true

fileOutputStream = new FileOutputStream(filePath);
// 设置追加写入
fileOutputStream = new FileOutputStream(filePath, true);

4. 文件拷贝 ———— input output 结合

利用前文讲的 fileInputStream​ 和 fileOutputStream​ 进行文件拷贝。

原理上来说,先将文件的内容(注意,其实图片当中也是内容,这个内容不光是文字!) 读取出来,再写入新的文件当中。

package test.IO;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {
    public static void main(String[] args) {
        copyFile();
    }

    public static void copyFile() {
        String oldfile = "D:\\111_Javastudy\\CreateFile\\1.txt";
        String newfile = "D:\\111_Javastudy\\CreateFile\\2.txt";
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try{
            fileInputStream = new FileInputStream(oldfile);
            fileOutputStream = new FileOutputStream(newfile);
            byte[] cache = new byte[1024];
            int readLen = 0;
            while((readLen = fileInputStream.read(cache)) != -1){
                fileOutputStream.write(cache,0 ,readLen);
            }
        }
        catch(FileNotFoundException e){e.printStackTrace();}
        catch(IOException e){e.printStackTrace();}

    }
}

image-20240907203416-p5psg0e

5. FileReader

public class FileReader extends InputStreamReader
用来读取字符文件的便捷类。此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。要自己指定这些值,可以先在 FileInputStream 上构造一个 InputStreamReader。
FileReader 用于读取字符流。要读取原始字节流,请考虑使用 FileInputStream。

下方测试代码将会将 Serialable/src/IOStream/CreateForFile/new1.txt​ 中的 new1.tx 文件打印输出至控制台:

package src.IOStream;  
  
import java.io.FileReader;  
import java.io.IOException;  
  
// 读取文件的字符流  
public class FileReaderPrint {  
    public static void main(String[] args) {  
        readFile();  
 }  
    public static void readFile(){  
        String filePath = "Serialable/src/IOStream/CreateForFile/new1.txt";  
 FileReader fileReader = null;  
 try {  
            fileReader = new FileReader(filePath);  
 int readLen = 0;  
 char[] cache = new char[8];  
 while ((readLen = fileReader.read(cache))!=-1){  
                System.out.print(new String(cache, 0, readLen));  
 }  
        } catch (IOException e){  
            e.printStackTrace();  
 } finally {  
            try {  
                fileReader.close();  
 } catch (IOException e){  
                e.printStackTrace();  
 }  
        }  
    }  
}

image-20240907204642-0lt1mimimage-20240907204856-1apb5ev

  • FileReader​ 将会一个一个字符读取,因此可以不乱码输出中文

posted @ 2024-09-07 20:53  m1xian  阅读(34)  评论(0)    收藏  举报