编程的蜗牛

颓废,始于首次的懒惰与原谅。

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

Java基础-IO流(1)

一、IO流概述

IO(Input And Output)在编程中是一个很常见的需求,IO即意味着我们的java程序需要和"外部"进行通信。

这个"外部"可以是很多介质:

1) 本地磁盘文件、远程磁盘文件
2) 数据库连接
3) TCP、UDP、HTTP网络通信
4) 进程间通信
5) 硬件设备(键盘、串口等)
...

  IO是我们的目的,而要达到这一目的,我们需要一种机制来帮助我们完全,这种机制就是"流"、或者叫"数据流"。

  数据流是一串连续不断的数据的集合,就象水管里的水流,在水管的一端一点一点地供水,而在水管的另一端看到的是一股连续不断的水流。数据写入程序可以是一段、一段地向数据流管道中写入数据,这些数据段会按先后顺序形成一个长的数据流。对数据读取程序来说,看不到数据流在写入时的分段情况,每次可以读取其中的任意长度的数据,但只能先读取前面的数据后,再读取后面的数据。不管写入时是将数据分多次写入,还是作为一个整体一次写入,读取时的效果都是完全一样的。

  Java的IO模型设计非常优秀,它使用Decorator模式,按功能划分Stream,记住这句话对我们在编程中选择合适的类库很重要,Java中按照功能提供不同类别的流。

  当需要把内存中的数据存储到持久化设备上这个动作称为输出(写)Output操作。

  当把持久设备上的数据读取到内存中的这个动作称为输入(读)Input操作。

  因此我们把这种输入和输出动作称为IO操作。

  按照“流”的数据流向,可以将其化分为:输入流输出流

  按照“流”中处理数据的单位,可以将其区分为:字节流字符流。在java中,字节是占1个Byte,即8位;而字符是占2个Byte,即16位。而且,需要注意的是,java的字节是有符号类型,而字符是无符号类型!

  字节流的抽象基类:

  InputStream,OutputStream

  字符流的抽象基类:

  Reader,Writer

  负责各种方式的输入、输出的类,都被放在java.io包中。所有输入流都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。

 

二、File类

  (参考博客:https://blog.csdn.net/zengkaiqiang562/article/details/83309700

  java.io.File代表与平台无关的文件或目录。也就是说可以通过File类在Java程序中操作文件或目录。
  File类只能用来操作文件或目录(包括新建、删除、重命名文件和目录等操作),但不能用来访问文件中的内容。
  如果需要访问文件中的内容,则需要使用输入/输出流。

  1. File类常用构造方法:

复制代码
//通过构造方法创建File对象的三种方式
public class FileDemo {
    public static void main(String[] args) {
        //File构造函数演示
        String pathName = "e:\\java_code\\day22e\\hello.java";
        File f1 = new File(pathName);//将Test22文件封装成File对象。注意;有可以封装不存在文件或者文件夹,变成对象。
        System.out.println(f1);
        
        File f2 = new File("e:\\java_code\\day22e","hello.java");
        System.out.println(f2);
        
        //将parent封装成file对象。
        File dir = new File("e:\\java_code\\day22e");
        File f3 = new File(dir,"hello.java");
        System.out.println(f3);
    }
}
复制代码

  2. File类的其他成员方法

  1)文件或目录检测相关的方法

public boolean exists(): 判断此File对象表示的文件或目录是否存在
public boolean canWrite():判断此File对象表示的文件或目录是否可写
public boolean canRead():判断此File对象表示的文件或目录是否可读
public boolean isFile():判断此File对象是否是表示文件,而非目录
public boolean isDirectory():判断此File对象是否是表示目录,而非文件
public boolean isAbsolute():判断此File对象的构造方法传入的路径是否是绝对路径

  2) 访问文件或目录的名称和路径的方法

public String getName(): 返回File构造方法中传入路径表示的文件名或目录名(如果是目录名则是最后一级子目录名)
public String getPath(): 返回File构造方法中传入的路径名
public String getParent():返回File构造方法中传入文件或目录路径的父目录,如果传入路径没有父目录,则返回null
public String getAbsolutePath(): 返回File对象表示的文件或目录的绝对路径名
public File getAbsoluteFile(): 返回一个通过此File对象表示的文件或目录的绝对路径名
public boolean renameTo(File dest): 重命名此File对象表示的文件或目录,重命名成功返回true,失败返回false。

  3) 获取常规文件信息的方法

public long lastModified():返回文件的最后修改时间
public long length():返回文件内容的长度

  4) 文件或目录操作相关的方法

复制代码
public boolean createNewFile():创建一个此File对象所表示的文件,返回true则创建成功,false则失败。
如果此File对象表示的文件存在,则创建失败;
如果此File对象表示的是一个存在的目录,则创建失败;
如果此File对象构造方法传入路径表示的文件不存在,则创建成功。即使此路径是一个不带文件后缀扩展名的目录路径,只要此路径目录不存在,也能创建成功,新建的文件名就是路径最后一级子目录名
public boolean mkdir():创建一个此File对象表示的目录,返回true则创建成功,false则失败。 如果此File对象表示的是一个存在的目录,则创建失败; 如果表示的是一个存在的文件,则也创建失败; 如果此File对象传入路径表示的目录不存在,则创建成功(其中如果传入路径包含父目录,则要保证父目录存在,否则也会创建失败)。另外,即使传入路径是一个带文件后缀名的文件路径,只要此路径文件不存在,也能创建成功,新建目录的最后一级子目录名就是包含后缀名的文件名。
public boolean mkdirs():创建一个此File对象表示的目录,如果File对象构造方法的传入路径包括父目录,则当父目录不存在时,也会自动创建不存在的父目录。返回true创建成功,false则失败。 如果此File对象表示一个存在的文件或目录,则创建失败; 如果此File对象构造方法的传入路径只是一级目录路径(即不包含父目录),并且此路径表示的目录不存在,则也能创建成功; 与mkdir方法相比较,只是多了一个当传入路径包含父目录,且此父目录不存在时,会自动创建父目录的功能。
public boolean delete():删除此File对象表示的文件或目录,返回true则删除成功,false则失败。 如果此File对象表示的文件或目录不存在,则删除失败; 如果此File对象表示的是一个目录,则当此目录下存在子目录或文件时,需把此目录下的所有子目录和文件都删除后,才能将此目录删除成功。 Java程序的删除不走回收站!
public void deleteOnExit():注册一个删除钩子,指定当Java虚拟机退出时,删除此File对象表示的文件或目录。 public static File createTempFile(String prefix, String suffix): 在默认的临时文件目录中创建一个临时的空文件,使用给定的前缀、系统生成的随机数、给定的后缀作为文件名。 这是一个静态方法,可以直接通过File类来调用; prefix字符串长度必须不少于3个字节,否则会报java.lang.IllegalArgumentException: Prefix string too short异常; suffix参数可以为null,此时将使用默认的后缀".tmp"
public static File createTempFile(String prefix, String suffix, File directory):在directory指定的父目录中创建一个临时的空文件。
复制代码

  5)  遍历文件或目录的方法

public String[] list():
若此File对象表示已存在的目录,则返回此目录下的所有文件名(不包括子目录中的文件)和一级子目录名的字符串数组;若此目录为空,则返回一个空数组;
若此File对象表示已存在的文件,则返回null;
若此File对象表示的目录或文件不存在,则返回null。
public File[] listFiles():作用同list()方法类似,只不过返回的数组元素是表示文件或目录的File对象。 public static File[] listRoots():返回系统所有的根路径的File对象。Windows中返回的就是盘符。

  6) 文件过滤器相关方法

public File[] listFiles(FilenameFilter filter):返回此File对象下通过FilenameFilter过滤器过滤后的所有文件和一级子目录

public File[] listFiles(FileFilter filter):返回此File对象下通过FileFilter过滤器过滤后的所有文件和一级子目录

三、字节流

  字节流的基本操作和字符流类相同,但它不仅可以操作字符,还可以操作其他媒体文件。

  1. InputStream字节输入流

  InputStream类是字节输入流的抽象类,是所有字节输入流的父类,InputStream类具有层次结构如下图所示:

复制代码
//InputStream常用方法
int available​() 从下一次调用此输入流的方法返回可从该输入流读取(或跳过)的字节数,而不会阻塞。 
void close​() 关闭此输入流并释放与流相关联的任何系统资源。 
void mark​(int readlimit) 标记此输入流中的当前位置。 
boolean markSupported​() 测试此输入流是否支持 mark和 reset方法。 
abstract int read​() 从输入流读取数据的下一个字节。 
int read​(byte[] b) 从输入流中读取一些字节数,并将它们存储到缓冲器阵列 b 。 
int read​(byte[] b, int off, int len) 从输入流读取最多 len个字节的数据到字节数组。 
byte[] readAllBytes​() 从输入流读取所有剩余字节。 
int readNBytes​(byte[] b, int off, int len) 将所请求的字节数从输入流读入给定的字节数组。 
void reset​() 将此流重新定位到最后在此输入流上调用 mark方法时的位置。 
long skip​(long n) 跳过并丢弃来自此输入流的 n字节的数据。 
long transferTo​(OutputStream out) 从该输入流中读取所有字节,并按读取的顺序将字节写入给定的输出流。 
复制代码

  1)FileInputStream介绍

  构造方法:

FileInputStream​(File file) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的 File对象 file命名。 
FileInputStream​(FileDescriptor fdObj) 通过使用文件描述符 fdObj创建 FileInputStream ,该文件描述符表示与文件系统中的实际文件的现有连接。 
FileInputStream​(String name) 通过打开与实际文件的连接来创建一个 FileInputStream ,该文件由文件系统中的路径名 name命名。 

  常用方法:

复制代码
int available​() 返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。 
void close​() 关闭此文件输入流并释放与流相关联的任何系统资源。  
FileChannel getChannel​() 返回与此文件输入流相关联的唯一的FileChannel对象。 
FileDescriptor getFD​() 返回表示与此 FileInputStream正在使用的文件系统中的实际文件的连接的 FileDescriptor对象。 
int read​() 从该输入流读取一个字节的数据。 
int read​(byte[] b) 从该输入流读取最多 b.length个字节的数据到一个字节数组。 
int read​(byte[] b, int off, int len) 从该输入流读取最多 len个字节的数据到字节数组。 
long skip​(long n) 跳过并从输入流中丢弃 n字节的数据。 
复制代码

  2)FileInputStream具体使用

复制代码
import java.io.*;
class  FileStream{
    public static void main(String[] args) throws IOException{
        readFile_3();
    }
 
    //打开文件,一次读取刚刚好内容的字节
    public static void readFile_3()throws IOException{
        FileInputStream fis = new FileInputStream("fos.txt");
        //available()返回从此输入流中可以读取(或跳过)的剩余字节数的估计值,而不会被下一次调用此输入流的方法阻塞。
        byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。
        fis.read(buf);
        System.out.println(new String(buf));
        fis.close();
    }
 
    //打开文件,一次读取多个字节
    public static void readFile_2()throws IOException
    {
        FileInputStream fis = new FileInputStream("fos.txt");
 
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=fis.read(buf))!=-1)
        {
            System.out.println(new String(buf,0,len));
        }
        fis.close();
    }
    //打开文件,一次读取一个字节
    public static void readFile_1()throws IOException{
        FileInputStream fis = new FileInputStream("fos.txt");
        int ch = 0;
        while((ch=fis.read())!=-1)
        {
            System.out.println((char)ch);
        }
        fis.close();
    }
}
复制代码

  2. OutputStream字节输出流

  OutputStream类是字节输出流的抽象类,是所有字节输出流的父类,OutputStream类具有层次结构如下图所示:

//字节输出流常用方法
void close​() 关闭此输出流并释放与此流相关联的任何系统资源。 
void flush​() 刷新此输出流并强制任何缓冲的输出字节被写出。 
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此输出流。 
void write​(byte[] b, int off, int len) 从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 
abstract void write​(int b) 将指定的字节写入此输出流。 

  1)FileOutPutStream介绍

  构造方法:

FileOutputStream​(File file) 创建文件输出流以写入由指定的 File对象表示的文件。 
FileOutputStream​(FileDescriptor fdObj) 创建文件输出流以写入指定的文件描述符,表示与文件系统中实际文件的现有连接。 
FileOutputStream​(File file, boolean append) 创建文件输出流以写入由指定的 File对象表示的文件。 
FileOutputStream​(String name) 创建文件输出流以指定的名称写入文件。 
FileOutputStream​(String name, boolean append) 创建文件输出流以指定的名称写入文件。 

  常用方法:

void close​() 关闭此文件输出流并释放与此流相关联的任何系统资源。 
FileDescriptor getFD​() 返回与此流相关联的文件描述符。 
void write​(byte[] b) 将 b.length字节从指定的字节数组写入此文件输出流。 
void write​(byte[] b, int off, int len) 将 len字节从指定的字节数组开始,从偏移量 off开始写入此文件输出流。 
void write​(int b) 将指定的字节写入此文件输出流。 

  2)FileOutPutStream具体应用

复制代码
import java.io.*;
public class FileStreamTest {
    private static final String FileName = "file.txt";
    public static void main(String[] args) {
        testWrite();
    }
    /**
     * FileOutputStream 演示函数
     * 运行结果:
     * 在源码所在目录生成文件"file.txt",文件内容是“abcdefghijklmnopqrstuvwxyz0123456789”
     * 加入,我们将 FileOutputStream fileOut2 = new FileOutputStream(file, true);
     *       修改为 FileOutputStream fileOut2 = new FileOutputStream(file, false);
     * 然后再执行程序,“file.txt”的内容变成"0123456789"。
     * 原因是:
     * (01) FileOutputStream fileOut2 = new FileOutputStream(file, true);
     *      它是以“追加模式”将内容写入文件的。即写入的内容,追加到原始的内容之后。
     * (02) FileOutputStream fileOut2 = new FileOutputStream(file, false);
     *      它是以“新建模式”将内容写入文件的。即删除文件原始的内容之后,再重新写入。
     */
    public static void testWrite() {
        try {
            // 创建文件“file.txt”对应File对象
            File file = new File(FileName);
            // 创建文件“file.txt”对应的FileOutputStream对象,默认是关闭“追加模式”
            FileOutputStream fileOut1 = new FileOutputStream(file);
            // 创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利
            PrintStream out1 = new PrintStream(fileOut1);
            // 向“文件中”写入26个字母
            out1.print("abcdefghijklmnopqrstuvwxyz");
            out1.close();
 
            // 创建文件“file.txt”对应的FileOutputStream对象,打开“追加模式”
            FileOutputStream fileOut2 = new FileOutputStream(file, true);
            // 创建FileOutputStream对应的PrintStream,方便操作。PrintStream的写入接口更便利
            PrintStream out2 = new PrintStream(fileOut2);
            // 向“文件中”写入"0123456789"+换行符
            out2.println("0123456789");
            out2.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }  
}
复制代码

四、字符流

  在操作过程中字节流可以操作所有数据,可是当我们操作的文件中有中文字符,并且需要对中文字符做出处理。

  1. Reader字符输入流

复制代码
//字符输入流常用方法
abstract void close​() 关闭流并释放与之相关联的任何系统资源。 
void mark​(int readAheadLimit) 标记流中的当前位置。 
boolean markSupported​() 告诉这个流是否支持mark()操作。 
int read​() 读一个字符 
int read​(char[] cbuf) 将字符读入数组。 
abstract int read​(char[] cbuf, int off, int len) 将字符读入数组的一部分。 
int read​(CharBuffer target) 尝试将字符读入指定的字符缓冲区。 
boolean ready​() 告诉这个流是否准备好被读取。 
void reset​() 重置流。 
long skip​(long n) 跳过字符 
复制代码

  1)FileReader介绍

  构造方法:

FileReader​(File file) 创建一个新的 FileReader ,给出 File读取。 
FileReader​(FileDescriptor fd) 创建一个新的 FileReader ,给予 FileDescriptor从中读取。 
FileReader​(String fileName) 创建一个新的 FileReader ,给定要读取的文件的名称。 

  2)具体操作

复制代码
import java.io.*;
 
class  FileReaderDemo{
    public static void main(String[] args) throws IOException{
        //创建一个文件读取流对象,和指定名称的文件相关联。
        //要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
        FileReader fr = new FileReader("demo.txt");
        //调用读取流对象的read方法。
        //read():一次读一个字符。而且会自动往下读。         
        int ch = 0;
        while((ch=fr.read())!=-1){
            System.out.println("ch="+(char)ch);
        }
        //关闭流
        fr.close();
    }
}

/*
第二种方式:通过字符数组进行读取。
*/
import java.io.*;
class FileReaderDemo2{
    public static void main(String[] args) throws IOException{
        FileReader fr = new FileReader("demo.txt");
        //定义一个字符数组。用于存储读到字符。
        //该read(char[])返回的是读到字符个数。
        char[] buf = new char[1024];
        int num = 0;
        while((num=fr.read(buf))!=-1){
            System.out.println(new String(buf,0,num));
        }
        fr.close();
    }
}
复制代码

  2. Writer字符输出流

复制代码
//字符输出流常用方法
Writer append​(char c) 将指定的字符附加到此作者
Writer append​(CharSequence csq) 将指定的字符序列附加到此作者
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者 
abstract void close​() 关闭流,先刷新
abstract void flush​() 刷新流 
void write​(char[] cbuf) 写入一个字符数组。 
abstract void write​(char[] cbuf, int off, int len) 写入字符数组的一部分 
void write​(int c) 写一个字符 
void write​(String str) 写一个字符串 
void write​(String str, int off, int len) 写一个字符串的一部分
复制代码

  1)FileWriter简介

构造方法:

OutputStreamWriter​(OutputStream out) 创建一个使用默认字符编码的OutputStreamWriter
OutputStreamWriter​(OutputStream out, String charsetName) 创建一个使用命名字符集的OutputStreamWriter
OutputStreamWriter​(OutputStream out, Charset cs) 创建一个使用给定字符集的OutputStreamWriter
OutputStreamWriter​(OutputStream out, CharsetEncoder enc) 创建一个使用给定字符集编码器的OutputStreamWriter 

  常用方法:

复制代码
Writer append​(CharSequence csq) 将指定的字符序列附加到此作者。 
Writer append​(CharSequence csq, int start, int end) 将指定字符序列的子序列附加到此作者。 
void close​() 关闭流,先刷新。 
void flush​() 刷新流。 
String getEncoding​() 返回此流使用的字符编码的名称。 
void write​(char[] cbuf, int off, int len) 写入字符数组的一部分。 
void write​(int c) 写一个字符 
void write​(String str, int off, int len) 写一个字符串的一部分。 
复制代码

  2)FileWriter具体操作

复制代码
import java.io.*;
class  FileWriterDemo{
    public static void main(String[] args) throws IOException{
        //创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
        //而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
        //其实该步就是在明确数据要存放的目的地。
        FileWriter fw = new FileWriter("demo.txt");
        //调用write方法,将字符串写入到流中。
        fw.write("abcde");
        //刷新流对象中的缓冲中的数据。
        //将数据刷到目的地中。
        //fw.flush();
        //关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
        //将数据刷到目的地中。
        //和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
        fw.close();
    }
}
复制代码

 

posted on   粼溪  阅读(51)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示