欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java之IO流

程序员文章站 2024-03-05 15:18:07
...

IO流

FILE类

FILE类的一个对象代表一个文件或者一个文件目录

路径分隔符

  • 路径中的每级目录之间用一个路径分隔符隔开
  • 路径分隔符和系统有关:
    • windows和DOS系统默认使用’\’
    • UNIX和URL使用’/’
  • Java支持跨平台运行,因此路径分隔符要慎用
  • 为了解决这个隐患,File类提供了一个常量File.seperator

构造器

@Test
public void test1()
{
    // 构造器1
    File file = new File("Hello.txt");
    File file2 = new File("e:\\STUDY\\java");
    // which equals to
    File file3 = new File("e:"+File.separator+"STUDY"+File.separator+"java");
    
    File file4 = new File("e:\\STUDY\\java","day01.md");
    System.out.println(file4);
	
    File file5 = new File(file3,"day01.md");
    System.out.println(file5);
	
    //e:\STUDY\java\day01.md
    //e:\STUDY\java\day01.md
}

常用功能

获取相关信息

@Test
public void test2()
{
    File file = new File("hello.txt");
    System.out.println(file.getAbsoluteFile());
    System.out.println(file.getPath());
    System.out.println(file.getName());
    System.out.println(file.getParent());
    System.out.println(file.length());
    System.out.println(new Date(file.lastModified()));
//E:\Java\code\JavaSE\senior_java\hello.txt
//hello.txt
//hello.txt
//null 		-- 	只有构造器中是绝对路径的才能看到父目录
//11 		-- 	文件中的字节长度
//Wed Sep 09 15:30:11 CST 2020	--	返回时间戳
}

对文件夹的操作

@Test
public void test3()
{
    File file = new File("E:\\BUPT\\java");
    String[] list = file.list();
    for(String str : list)
    {
        System.out.println(str);
    }
    File[] files = file.listFiles();
    for (File f : files)
    {
        System.out.println(f);
    }
//        day1.md
//        day2.md
//        ...
//        E:\BUPT\java\day1.md
//        E:\BUPT\java\day2.md
//        ...
}

重命名

boolean file1.ranameTo(file2)

注意:file1必须在硬盘中存在,file2必须在硬盘中不存在,否则操作失败,返回false

@Test
public void test4()
{
    File file1 = new File("hello.txt");
    File file2 = new File("hi.txt");
    boolean b = file2.renameTo(file1);
    System.out.println(b);
    // true if hello.txt exists and hi.txt not
}

判断相关信息

  • public boolean isDirectory():判断是否是目录
  • public boolean isFile():判断是否是文件
  • public boolean exists():判断是否存在
  • public boolean canRead():判断是否可读
  • public boolean canWrite():判断是否可写

创建、删除功能

  • public boolean createNewFile():创建新的文件,如果文件存在则不创建,返回false
  • public boolean mkdir():创建文件目录,如果目录存在则不创建,如果上层目录不存在也不创建
  • public boolean mkdirs():创建文件目录,如果上层文件不存在一并创建
  • public boolean delete():删除文件或文件夹。注意:Java删除不走回收站!

IO流原理及流的分类

IO是Input/Output的缩写,用于处理设备之间的数据传输。Java中数据的输入输出以流的方式进行。java.io包下提供了各种 流类和接口,并通过标准的方法输入或输出数据

流的分类

  • 操作数据单位不同分为:字节流(8bit),字符流(16bit)
  • 数据量的流向不同分为:输入流、输出流
  • 按流的角色的不同分为:节点流、处理流
抽象基类 字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

Java之IO流

深色是比较重要的。主要学习访问文件的四个流,具体的操作方法每个流都差不多,剩下的学习功能即可。

文件流

FileReader

首先注意的几点:

  • IO流这些物理上的流JVM无法自行关闭,必须手动关闭!
  • read()的理解:返回读入的一个字符,如果达到文件末尾返回-1
  • 异常的处理:如果使用throws,发现错误就会理解创建异常对象然后结束,此时有可能IO流对象还未被关闭,所以需要使用try-catch-finally来关闭IO流而非使用throws
  • 打开的文件一定要存在,不然会报错
public void test() throws IOException {
    FileReader fr = null;
    try {
        File file = new File("hello.txt");
        fr = new FileReader(file);

        int data;
        while((data = fr.read())!=-1)
        {
            System.out.print((char)data);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fr != null)
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

重载read()方法——一次读多个字符

public void test2() {
    FileReader fr = null;
    try {
        // 1. File类的初始化
        File file = new File("hello.txt");
        // 2. io流类的初始化
        fr = new FileReader(file);
        // 3. 读文件操作
        // 这里使用重载的read(char[] buf)
        int len;
        char[] cbuf = new char[5];
        while ((len = fr.read(cbuf)) != -1) {
//            System.out.println("错误的写法1");
//            for (int i = 0; i < cbuf.length; i++)
//                System.out.print(cbuf[i]);
//            // helloworld123ld
//            
//            System.out.println("\n错误的写法2:");
//            String str = new String(cbuf);
//            System.out.print(cbuf);
//            // helloworld123ld
//            
//            System.out.println("\n正确的写法1");
//            for (int i = 0; i < len; i++)
//                System.out.print(cbuf[i]);
//            // helloworld

            System.out.println("\n正确的写法2");
            String str2 = new String(cbuf, 0, len);
            System.out.print(str2);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 4. 关闭IO流
        if(fr != null)
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }
}

FileWriter

注意:

  • 若文件不存在,则创建该文件
  • 若文件存在,会覆盖该文件
  • FileWriter(File file,boolean append),如果使用该构造器,append为false则覆盖,为true则添加
public void test3(){
    FileWriter fw = null;
    try {
        // 该文件不存在,则会创建文件
        File file = new File("hi.txt");
        fw = new FileWriter(file);

        fw.write("I hava a dream! ");
        fw.write("This is a Test");
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

FileReader和FileWriter实现文件复制

注意:FileReader是字符流形式,不能用于图片、视频的复制,如果想实现后者的复制,必须换成FileOutputStream,FileWriter同理。

结论:对于文本文件(.txt.doc.c.java)用字符流处理,非文本文件用字节流(.jpg.mp4.mp3)处理

@Test
public void test5()
{
    FileReader fr = null;
    FileWriter fw = null;
    try {
        File srcfile = new File("hello.txt");
        File destfile = new File("hello2.txt");

        fr = new FileReader(srcfile);
        fw = new FileWriter(destfile);

        int len;
        char []cbuf = new char[5];
        while((len = fr.read(cbuf))!=-1)
        {
            String str = new String(cbuf,0,len);
            fw.write(str);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(fr!=null)
            try {
                fr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        if(fw !=null)
            try {
                fw.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
    }

缓冲流(处理流的一种)

缓冲流是为了提高读写效率

注意:

  • 新建缓冲流的前提是新建了一个节点流
  • 关闭处理流时,只用关闭外层流,内层流自动关闭
  • 使用缓冲流的速度远大于节点流(原因:内部提供缓冲区,大小为8092,等到缓冲区填满了再flush出去)
@Test
public void test6() {
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {
        // 1.造文件
        File f1 = new File("UI1.png");
        File f2 = new File("UI2.png");

        // 2.造流
        // 2.1 造节点流
        FileInputStream fis = new FileInputStream(f1);
        FileOutputStream fos = new FileOutputStream(f2);
        // 2.2 造处理流
        bis = new BufferedInputStream(fis);
        bos = new BufferedOutputStream(fos);

        // 复制
        int len;
        byte[] bytes = new byte[10];
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (bos != null) {
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (bis != null) {
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

转换流

分辨属于什么流看后缀,转换流属于字符流

  • InputStreamReader:将一个字节的输入流转换为字符的输入流
  • OutputStreamWriter:将一个字符的输出流转换为字节的输出流
  • 作用:提供字节流与字符流之间的转换
  • 解码:字节、字节数组 —>字符数组、字符串
  • 编码:字符数组、字符串 —>字节、字节数组

字符集

  • ASCII:美国标准信息交换码,用一个字节的7位可以表示

  • ISO8859-1:拉丁码表。欧洲码表,用一个字节的8位可以表示

  • GB2312:中国的中文编码表,最多两个字节编码所有字符

  • GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节

  • Unicode:国际校准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码,所有的文字字符都用两个字节表示

  • UTF-8:变长的编码方式,可用1-4个字节来表示一个字符

对象流

序列化机制

允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其他程序获取了这种二进制流,就可以恢复成原来的Java对象。

对象的序列化

用于存储和读取基本数据类型数据或对象的处理流,可以把Java中的对象写入到数据源中也能还原回来。

  • ObjectInputStreamObjectOutputStream
  • 序列化:用ObjectInputStream类保存基本类型数据或对象的机制
  • 反序列化:用ObjectOutputStream类读取基本类型数据或对象的机制

static和transient修饰的成员变量不能被序列化

IO流的框架都是一样的,对象流也差不多

自定义类序列化的注意事项:

  • 注意进行序列化的对象所在的类必须要实现Serializable接口,尤其是自定义类
  • 凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量private static final long serialVersionUID
  • 如果不显式设置这个ID也可,但是系统会隐式给你一个ID,当你修改了类中的变量之后,ID会改变,可能会造成先前序列化后的文件反序列化回来的结果与原来不一致。所以一般自己显示定义一个常量。
  • 自定义类的所有内部属性必须可序列化。(默认情况下,基本数据类型可序列化)
public class ObjectStreamTest {
    // 序列化
    @Test
    public void test2()
    {
        ObjectOutputStream oos = null;
        try {
            File file = new File("object.dat");
            FileOutputStream fos = new FileOutputStream(file);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(new User(18,"Bill"));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(oos != null)
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
    // 反序列化
    @Test
    public void test1()
    {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));
            Object obj = ois.readObject();
            User user = (User) obj;
            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null)
            {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
       System.out.println(user);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        if(ois != null)
        {
            try {
                ois.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

}


相关标签: JAVA