Java教程

JavaSE第八章.IO

本文主要是介绍JavaSE第八章.IO,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

  • IO流
      • 分类
      • 特性
  • 非流式
      • File类
  • 流式
      • 字节流
            • 缓冲数组
            • 高效缓冲流
      • 字符流
      • Print流
      • 对象输入输出流
            • 常用类
            • 自定义类

IO流

分类

在这里插入图片描述

  • 根据处理数据类型的不同分为:字符流和字节流
  • 根据数据流向不同分为:输入流和输出流
  • 按数据来源(去向)分类:
    • File(文件): FileInputStream, FileOutputStream, FileReader, FileWriter
    • byte[]:ByteArrayInputStream, ByteArrayOutputStream
    • Char[]: CharArrayReader,CharArrayWriter
    • String : StringBufferInputStream, StringReader, StringWriter
    • 网络数据流:InputStream,OutputStream, Reader, Writer

字符流和字节流
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:

  • 字节流:数据流中最小的数据单元是字节
  • 字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。

字符流的由来: Java中字符是采用Unicode标准,一个字符是16位,即一个字符使用两个字节来表示。为此,JAVA中引入了处理字符的流。因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。

输入流和输出流
根据数据的输入、输出方向的不同对而将流分为输入流和输出流。

  • 输入流
    程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道

  • 输出流
    程序向输出流写入数据。将程序中的数据输出到外界(显示器、打印机、文件、网络…)的通信通道

特性

相对于程序来说,输出流是往存储介质或数据通道写入数据,而输入流是从存储介质或数据通道中读取数据,一般来说关于流的特性有下面几点:

  • 先进先出,最先写入输出流的数据最先被输入流读取到。
  • 顺序存取,可以一个接一个地往流中写入一串字节,读出时也将按写入顺序读取一串字节,不能随机访问中间的数据。(RandomAccessFile可以从文件的任意位置进行存取(输入输出)操作)
  • 只读或只写,每个流只能是输入流或输出流的一种,不能同时具备两个功能,输入流只能进行读操作,对输出流只能进行写操作。在一个数据传输通道中,如果既要写入数据,又要读取数据,则要分别提供两个流。

非流式

File类

  • 一个File类对象可以代表一个文件或目录
  • File对象可以对文件或目录的属性进行操作,如:文件名、最后修改日期、文件大小等
  • File对象无法操作文件的具体数据,即不能直接对文件进行读/写操作
//构造方法
File(String pathname) 
通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。 

File(File parent, String child) 
从父抽象路径名和子路径名字符串创建新的 File实例。  

        File file1 = new File("S:/demo1.txt");  //前提文件目录存在
        
        File parent = new File("S:/");
        File file2 = new File(parent,"demo2.txt");
//常用
boolean exists() 测试此抽象路径名表示的文件或目录是否存在。  
boolean canExecute() 是否可执行  
boolean canRead() 是否可读
boolean canWrite() 是否可写
int compareTo(File pathname) 比较两个抽象的路径名字典。 
long length() 返回由此抽象路径名表示的文件的长度。  
boolean delete() 删除由此抽象路径名表示的文件或目录。  
File getAbsoluteFile() 返回此抽象路径名的绝对形式。  
String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串。 
String toString() 返回此抽象路径名的路径名字符串。 
String getName() 返回由此抽象路径名表示的文件或目录的名称。  
String getParent() 返回此抽象路径名的父 null的路径名字符串,如果此路径名未命名为父目录,则返回null。 boolean isDirectory() 测试此抽象路径名表示的文件是否为目录。  

//创建文件
boolean createNewFile() 
当且仅当具有该名称的文件尚不存在时,原子地创建一个由该抽象路径名命名的新的空文件。  
static File createTempFile(String prefix, String suffix) 
在默认临时文件目录中创建一个空文件,使用给定的前缀和后缀生成其名称。  
static File createTempFile(String prefix, String suffix, File directory) 
在指定的目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。 

//创建文件夹
boolean mkdir() 创建单级文件夹(目录)
boolean mkdirs() 多级文件夹
//子文件
String[] list() 
返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录。  
String[] list(FilenameFilter filter) 
返回一个字符串数组,命名由此抽象路径名表示的目录中满足指定过滤器的文件和目录。  
File[] listFiles() 
返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件。  
File[] listFiles(FileFilter filter) 
返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。  
File[] listFiles(FilenameFilter filter) 
返回一个抽象路径名数组,表示由此抽象路径名表示的满足指定过滤器的目录中的文件和目录。  
static File[] listRoots() 
列出可用的文件系统根。


void deleteOnExit() 
请求在虚拟机终止时删除由此抽象路径名表示的文件或目录。  
boolean equals(Object obj) 
测试此抽象路径名与给定对象的相等性。   
File getCanonicalFile() 
返回此抽象路径名的规范形式。  
String getCanonicalPath() 
返回此抽象路径名的规范路径名字符串。  
long getFreeSpace() 
返回分区未分配的字节数 named此抽象路径名。  
File getParentFile() 
返回此抽象路径名的父,或抽象路径名 null如果此路径名没有指定父目录。  
String getPath() 
将此抽象路径名转换为路径名字符串。  
long getTotalSpace() 
通过此抽象路径名返回分区 named的大小。  
long getUsableSpace() 
返回上的分区提供给该虚拟机的字节数 named此抽象路径名。  
int hashCode() 
计算此抽象路径名的哈希码。  
boolean isAbsolute() 
测试这个抽象路径名是否是绝对的。  
boolean isFile() 
测试此抽象路径名表示的文件是否为普通文件。  
boolean isHidden() 
测试此抽象路径名命名的文件是否为隐藏文件。  
long lastModified() 
返回此抽象路径名表示的文件上次修改的时间。  
boolean renameTo(File dest) 
重命名由此抽象路径名表示的文件。  
boolean setExecutable(boolean executable) 
为此抽象路径名设置所有者的执行权限的便利方法。  
boolean setExecutable(boolean executable, boolean ownerOnly) 
设置该抽象路径名的所有者或每个人的执行权限。  
boolean setLastModified(long time) 
设置由此抽象路径名命名的文件或目录的最后修改时间。  
boolean setReadable(boolean readable) 
一种方便的方法来设置所有者对此抽象路径名的读取权限。  
boolean setReadable(boolean readable, boolean ownerOnly) 
设置此抽象路径名的所有者或每个人的读取权限。  
boolean setReadOnly() 
标记由此抽象路径名命名的文件或目录,以便只允许读取操作。  
boolean setWritable(boolean writable) 
一种方便的方法来设置所有者对此抽象路径名的写入权限。  
boolean setWritable(boolean writable, boolean ownerOnly) 
设置此抽象路径名的所有者或每个人的写入权限。  
Path toPath() 
返回从此抽象路径构造的java.nio.file.Path对象。   
URI toURI() 
构造一个表示此抽象路径名的 file: URI。  
  • 创建文件

            File file3 = new File("S:/demo3.docx");
            if (!file3.exists()){ //判断是否不存在
                try {
                    file3.createNewFile();//io异常,防止文件路径找不到
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
  • //遍历子文件
    File file1 = new File("E:/api");
    String [] fileNames = file1.list();//获得当前目录下的所有文件名和目录名(以字符串形式返回)
    for(String s : fileNames){
    	System.out.println(s);
    }
    
    File[] files = file1.listFiles();//获得当前目录下的所有文件名和目录名(返回的是文件对象)
    for(File f : files){
    	System.out.println(f);//重写了toString(),也输出字符串
    }
    
    //条件遍历
            File[] files = file1.listFiles(new FileFilter() {//把满足条件的放到file[]里
                @Override
                public boolean accept(File pathname) {
                    return pathname.getName().endsWith("chm");//自定义的文件过滤条件
                }
            });
            for(File f : files){
                System.out.println(f);
            }
    

流式

字节流

节点流 : 封装的是某种特定的数据源,如文件、字符串、字符串数组等

//把一个文件的内容读取并写入其他文件
		public static void main(String[] args) {

        //建立输入输出流管道
        FileInputStream in = null;//告诉java输入流,去读取计算机上的哪个文件
        FileOutputStream out = null;//告诉java输出流,输出到哪个文件
        try {
            in = new FileInputStream("S:/demo1.txt");
            out = new FileOutputStream("E:/demo2.txt");
            //循环读写
            //in.read();    每次读取一个字节并返回,当文件内容读完之后,会返回一个-1
            //out.write();  一次向外输出(写)一个字节
            int b;
            while ((b = in.read()) != -1) {
                out.write(b);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.out.println("文件未找到");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("读写错误");
        } finally {
            //关闭流通过,解除文件占用
            try {
                if (in != null) {
                    in.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
缓冲数组

每次只能读或写一个字节 , 效率低 , 所以一次读多个字节存到byte[]中,放满之后写byte[]

byte[] b = new byte[1024];//数组长1024,每次读1024个字节
int length = 0;//用length来获取数组的实际字节长度,防止多输出null
while ((length = in.read(b)) != -1) {
//read(byte[] b)每次最多读byte数组长度个字节,返回数组中实际装入的字节个数,读完返回-1
	out.write(b, 0, length);
//每次向外写一个byte个字节,从指定位置开始(一般情况从0开始),向外写length个长度
}
高效缓冲流

处理流 : 封装的是其它流对象

对节点流进行包装

  • BufferedInputStream 有一个缓存数组(默认8k,可自定义),用来存放read()进去的byte[]或字节,存满之后write()
  • 自己定义的byte[]长度需要小于BufferedOutputStream内的缓存数组长度才能提高效率
    public static void main(String[] args) {
        //用带缓冲区的高级管道包装一下
        try{
            FileInputStream in = new FileInputStream("S:/demo1.txt");
            BufferedInputStream bin = new BufferedInputStream(in);
            FileOutputStream out = new FileOutputStream("E:/demo2.txt");
            BufferedOutputStream bout = new BufferedOutputStream(out);

            byte[] b = new byte[1024];
            int length;
            while ((length=bin.read())!=-1){
                bout.write(b,0,length);
            }
            bin.close();
            bout.flush();//刷新缓冲区
            bout.close();

        } catch (IOException e){
            e.printStackTrace();
        }
    }

字符流

    public static void main(String[] args) throws IOException {

        FileReader fileReader = new FileReader("S:/demo.txt");
        BufferedReader bufferedReader  = new BufferedReader(fileReader);

        FileWriter fileWriter = new FileWriter("E:/demo.txt",true);//ture:追加
        BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
                  String line = null; //一次读入一行数据
                  while((line=bufferedReader.readLine())!=null){
                          bufferedWriter.write(line);//一次写出一行数据
                          bufferedWriter.newLine();//换行
                  }

                  bufferedReader.close();
                  bufferedWriter.close();
    }

Print流

打印:只做输出,没有输入
从程序中向外输出(访问网页–>服务器就会将网页内容以流的形式响应到浏览器)

    public static void main(String[] args) throws FileNotFoundException {

        PrintWriter out =new PrintWriter("S:/printWriterDemo.html");
        out.println("<h1>我是服务器传来的信息<h1>");
        out.println("<h1>我是服务器传来的信息<h1>");

        out.close();
    }

对象输入输出流

处理流

  • 对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息。 对象信息一旦写到文件上那么对象的信息就可以做到持久化了

对象的输出流: ObjectOutputStream

对象的输入流: ObjectInputStream

  • 要将序列化之后的对象保存下来,需要通过对象输出流(ObjectOutputStream)将对象状态保存,之后再通过对象输入流(ObjectInputStream)将对象状态恢复。

在ObjectInputStream 中用readObject()方法可以直接读取一个对象,

ObjectOutputStream中用writeObject()方法可以直接将对象保存到输出流中。

常用类
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //将程序运行的时间存储到文件中(直接将对象的信息存起来,对象序列化)
        Date date = new Date();     //Date类型
        FileOutputStream out = new FileOutputStream("S:/ObjectInputStream.txt");
        ObjectOutputStream objOut = new ObjectOutputStream(out);//处理流包装
        objOut.writeObject(date);//存储
        objOut.close();
        
        //将信息从文件中输入到程序中,这个过程称为反序列化
        FileInputStream in = new FileInputStream("S:/ObjectInputStream.txt");
        ObjectInputStream objIn = new ObjectInputStream(in);
        Object obj = objIn.readObject();
        if (obj instanceof Date){//判断object中包含的是否是Date类型
            Date date1 =(Date)obj;
            System.out.println(date1);
        }
    }
自定义类
  • 如果将一个类的对象信息序列化到文件中,此类需要生成一个序列化id号(版本号)

  • implements Serializable接口会自动生成一个版本号,一旦类中的内容改变,版本号就会自动变化

    也可以显示版本号,类修改是版本号不会改变

  • 生成版本号 : setting–>serialization issues–>serializable class without 'serialVersionUID’打钩

/*
  如果将一个类的对象信息序列化到文件中,此类需要生成一个序列化id号(版本号)
  implements Serializable接口会自动生成一个版本号,一旦类中的内容改变,版本号就会自动变化
  */
public class Student implements Serializable {
    //生成版本号//setting-->serialization issues-->serializable class without 'serialVersionUID'打钩
    private static final long serialVersionUID = -6839779773264328401L;//显示版本号,类修改是版本号不会改变
    private String name;
    private transient int age;//在对象序列化时,忽略此属性

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}



//将学生信息在文件中存取
public class ObjectStreamDemo{

    public static void main(String[] args) throws IOException, ClassNotFoundException{
        Student student1 = new Student("张三1",18);
        Student student2 = new Student("张三2",19);

        FileOutputStream out = new FileOutputStream("S:/StudentMassage.txt");
        ObjectOutputStream objOut = new ObjectOutputStream(out);
        objOut.writeObject(student1);
        objOut.writeObject(student2);
        objOut.close();

        FileInputStream in = new FileInputStream("S:/StudentMassage.txt");
        ObjectInputStream objIn =new ObjectInputStream(in);
        Student student3 =(Student) objIn.readObject();
        Student student4 =(Student) objIn.readObject();
        System.out.println(student3);
        System.out.println(student4);
    }
}

-------------------------------------
Student{name='张三1', age=0}
Student{name='张三2', age=0}
这篇关于JavaSE第八章.IO的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!