liujijiang

java学习笔记 --18-- javaI/O系统

2020.04.03

File

File:可以是文件,也可以是目录

读取文件并过滤

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException {
        File path = new File("/Users/joker/Pictures/图片/个人");
        
        String [] pictureList = path.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.substring(name.lastIndexOf("."),name.length()).equals(".JPG")?true:false;
            }
        });

        for(String str : pictureList){
            System.out.println(str);
        }

    }

.list方法返回目录下文件名的数组,可以加一个过滤参数进行过滤
list会为每一个文件名调用accept方法

File的一些方法

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        File path = new File("/Users/joker/Pictures/景色2");

        Random random = new Random(1);

        File newPath = new File(path.getParentFile().toString() + "/景色3");
        newPath.mkdirs();

        File [] files = path.listFiles();

        for(File file : files){
            System.out.println(file.getName());
            System.out.println(file.getAbsoluteFile());
            System.out.println(file.getAbsolutePath());
            System.out.println(file.getCanonicalFile());
            System.out.println(file.getFreeSpace());
            System.out.println(file.getParent());
            System.out.println(file.getParentFile());
            System.out.println(file.getPath());
            System.out.println(file.getTotalSpace());
            System.out.println(file.getUsableSpace());
            System.out.println(file.createNewFile());
            System.out.println(file.toURI());
            System.out.println(file.isFile());
            System.out.println(file.isDirectory());
            System.out.println(file.isHidden());
            System.out.println(file.canRead());
            System.out.println(file.canWrite());
            System.out.println(file.canExecute());

            file.renameTo(new File(newPath.getPath().toString()  +"/景色" + random.nextInt(100000) +".jpg"));

            System.out.println("**************************************");
        }
    }

file的一些操作

输入和输出

流:能产出数据的数据源对象,能接受数据的接收端对象
javaI/O分为输入和输出两个部分
任何Inputstream和Reader派生出的类都有read方法读取单个字节或字节数组
任何Outputstream和Writer派生出的类都有write方法写单个字节或字节数组

通常不会用到这些类,他们存在的意义就是被其他类使用

InputStream

把不同的产出数据的数据源当做InputStream

  • ByteArrayInputStream:将内存缓冲区当inputstream使用
  • StringBufferInputStream:将String作为inputStream
  • FileInputStream:将文件作为inputStream
  • PipedInputStream:实现管道化概念,多线程中数据源
  • SequenceInputStream:两个InputStream合到一起

所有的这些inputStream可以结合FilterInputStream使用效果更好

OutputStream

OutputStream决定了输出所要去往的目标

  • ByteArrayOutputStream:在内存中创建缓冲区,文件的数据送到缓冲区中
  • FileOutputStream:输送到文件中
  • PipedOutputStream:实现管道化概念,多线程中数据源

所有的OutputStream都可以结合FilterOutputStream使用效果更好

添加属性和有用的接口

FilterInputStream和FilterOutputStream提供了修饰器类接口以及控制输入和输出

通过FilterInputStream从InputStream中读取数据

几乎每次对输入都要进行缓冲,所以java把没有缓冲视为特殊情况
FilterInputStream类型:

  • DataInputStream:配合DataOutputStream使用,可以读取基本数据类型
  • BufferedInputStream:使用缓冲区,可以指定缓冲区大小

DataInputStream可以读取基本数据类型以及String,方法都是read开头

通过FilterOutputStream向OutputStream写入数据

与DataInputStream对应的DataOutputStream可以写入基本数据类型以及String,方法都是write开头
PrintStream是打印基本数据类型以及String,两个重要的方法:print和println
BufferedOutputStream每次写入都是使用缓冲区,而不是每次都进行实际的物理写作

  • DataOutputStream
  • PrintStream
  • BufferedOutputStream

Reader和Writer

java1.1加入Reader和Writer不是取代InputStream和OutputStream,而是为了更好的处理16位的Unicode字符,Unicode用于国际化,而且java的char也使用的是Unicode
InputStream和OutputStream是面向8位字节的
Reader和Writer是面向16位字符的
尽量使用Reader和Writer,如果编译报错,就可能使用8位字节操作的InputStream和OutputStream


字节和字符:字节是存储容量的基本单位,1字节=8个二进制位。 字符是指字母、数字、汉字和各种符号。
java采用Unicode,俩个字节表示一个字符,char是一个字符就是两个字节
中文一个汉字是3个字节,英文一个字母是2个字节

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        String str = "你好hello";
        System.out.println(str.getBytes().length);
        
    }

11个字节


字节和字符装换

  • InputStream--Reader
  • OutputStream--Writer
  • FileInputStream--FileReader
  • FileOutputStream--FileWriter
  • ByteArrayInputStream--CharReader
  • ByteArrayOutputStream--CharWriter
  • PipedInputStream--PipedReader
  • PipedOutputStream--PipedWriter

字符还有StringReader和StringWriter

适配器的转换

  • FilterInputStream--FilterReader
  • FilterOutputStream--FilterWriter
  • BufferedInputStream--BufferedReader
  • BufferedOutputStream--BufferedWriter
  • PringStream--PrintWriter

应该使用BufferedReader的readLine

自我独立的类

RandomAccessFile
从Object继承来的独立的类,可以在一个文件中前后移动

  • getFilePointer:当前所处文件位置
  • seek:移动到文件中新的位置
  • length:文件最大的尺寸

第二个参数指示随机读(r)还是又读又写(rw)

典型的I/O流使用方式

组合很多,但可能只会用到几种

缓冲输入文件

打开文件用于字符输入的FileReader,参数可以是String或File
提高速度使用缓冲,并且提供readLine方法,使用BufferedReader构造器

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        BufferedReader in = new BufferedReader(new FileReader("/Users/joker/扩展程序/banner.txt"));
        String s;
        StringBuilder sb = new StringBuilder();
        while ((s = in.readLine())!=null)
            sb.append(s + "\n");
        in.close();
        System.out.println(sb);
    }

需要添加换行,因为readLine不会加上换行,需要显示关闭流

基本的文件输出

FileWriter可以向文件写入数据
创建一个与指定文件链接的FileWriter
用BufferedWriter将其包装使用缓冲

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        BufferedWriter out = new BufferedWriter(new FileWriter("test_file"));
        out.write("jjboy");
        out.close();
    }

显示关闭流

读写随机访问文件

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        RandomAccessFile file = new RandomAccessFile("test_file","rw");
        System.out.println(file.readLine());
        
        for (int i=0;i<10;i++){
            System.out.println(file.readLine());
        }


        file.close();
    }

实现对一个文件的读写(不好用)

标准I/O

程序使用单一信息流
实现程序之间的通信,把程序串联起来

从标准输入中读取

java提供了System .in,System.out,System.err
默认已经使用PringStream包装了System.out和System.err,所以我们可以直接使用
但是System .in没有任何包装,所以使用之前需要包装

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        BufferedReader in = new BufferedReader(
                new InputStreamReader(System.in)
        );

        String str;
        while ((str = in.readLine())!= null && str.length() != 0){
            System.out.println(str);
        }
    }

首先使用InputStreamReader转换System .in,然后使用BufferedReader强化输入

标准I/O重定向

  • setIn(InputStream)
  • setOut(PrintStream)
  • setErr(PrintStream)
    I/O重定向操作的是字节流

新I/O

缓冲器:可以放数据的在通道中行驶的车,可以定义一车能放多少数据
通道:运送车,write和read方法操作的都是车
唯一与通道交互的缓冲器:ByteBuffer
对字节操作的FileInputStream,FileOutputStream和RandomAccessFile可以产生FileChannel

private static final int SIZE = 1024;
    public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {



        FileChannel in = new FileInputStream("test_file").getChannel();
        FileChannel out = new FileOutputStream("test_file").getChannel();
        FileChannel randomAccess = new RandomAccessFile("test_file","rw").getChannel();

        out.write(ByteBuffer.wrap("some text".getBytes()));
        out.close();

        ByteBuffer buffer = ByteBuffer.allocate(SIZE);
        in.read(buffer);
        buffer.flip();
        while (buffer.hasRemaining()){
            System.out.println((char)buffer.get());
        }
        in.close();

    }

使用getChannel方法返回一个FileChannel
wrap方法往车里放数据
buffer.hasRemaining:车里面有数据
flip:车随时准备接受数据

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        FileChannel out = new FileOutputStream("test_file").getChannel();
        BufferedReader in = new BufferedReader(new FileReader("test_file"));

        out.write(ByteBuffer.wrap("abcd\nefgh\nigklmno\npqrst".getBytes()));
        out.close();

        String s ;
        StringBuilder sb = new StringBuilder();
        while ((s = in.readLine())!=null)
            sb.append(s + "\n");
        in.close();

        System.out.println(sb);

    }

uio写数据,Reader读数据

private static final int SIZE = 1024;
    public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        FileChannel in = new FileInputStream(args[0]).getChannel(),
                out = new FileOutputStream(args[1]).getChannel();
        
        ByteBuffer buffer = ByteBuffer.allocate(SIZE);
        
        while (in.read(buffer) != -1){
            buffer.flip();
            out.write(buffer);
            buffer.clear();
        }
        
        in.close();
        out.close();

    }

文件内容复制
clear:清空车,以便能够再次装数据

private static final int SIZE = 1024;
    public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        FileChannel in = new FileInputStream(args[0]).getChannel(),
                out = new FileOutputStream(args[1]).getChannel();

        ByteBuffer buffer = ByteBuffer.allocate(SIZE);

        in.transferTo(0,in.size(),out);
        
        //out.transferFrom(in,0,in.size());
        

    }

使用transferTo或者transferFrom能将两个管道连接起来

文件加锁

文件锁对操作系统中的其他进程是可见的

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        FileChannel in = new FileInputStream(args[0]).getChannel();
        FileLock fl = in.tryLock();
        
        fl.release();
    }

对FileChannel调用lock或者tryLock方法返回文件锁
tryLock:非阻塞式的,如果当前文件已经被锁住,马上退出方法
lock:阻塞式IDE,如果当前文件已经被锁着,就会等待,直到可以获得文件锁
release:释放锁

压缩

压缩是按字节方式操作的
压缩类是从InputStream和OutputStream继承来的

常用的压缩类:

  • ZipInputStream
  • ZipOutputStream
  • GZipInputStream
  • GZipOutputStream

将文件压缩成Zip格式或GZip格式

GZip

Gzip接口简单,对单个数据流使用Gzip比较合适

public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        BufferedReader in = new BufferedReader(new FileReader("test_file"));
        BufferedOutputStream out = new BufferedOutputStream(
                new GZIPOutputStream(
                        new FileOutputStream("file.gz")
                )
        );
        String s;
        while ((s = in.readLine())!=null){
            out.write(s.getBytes());
        }

        in.close();
        out.close();

        BufferedReader reader = new BufferedReader(
                new InputStreamReader(
                        new GZIPInputStream(
                                new FileInputStream("file.gz")
                        )
                )
        );
        StringBuilder sb = new StringBuilder();
        while ((s = reader.readLine())!=null){
            sb.append(s + "\n");
        }

        System.out.println(sb);

        reader.close();

    }

使用Gzip封装写入字节流对文件进行压缩
使用Gzip封装读取字符流读取压缩文件
可以字符流读压缩文件,只能字节流写压缩文件

Zip

Zip支持的操作更全面一点
两种校验类型(Checksum):

  • Adler32:快
  • CRC32:慢一点,但是准确
public static void main(String [] args) throws NoSuchFieldException, IllegalAccessException, IOException {
        ZipOutputStream zip = new ZipOutputStream(new CheckedOutputStream(new FileOutputStream("file.zip"),new Adler32()));

        BufferedOutputStream out = new BufferedOutputStream(zip);

        BufferedReader in = new BufferedReader(
                new FileReader("test_file")
        );

        Random random = new Random(1);

        zip.setComment("zip_test");
        String s;
        while ((s = in.readLine()) != null){
            zip.putNextEntry(new ZipEntry(String.valueOf(random.nextInt(100))));
            out.write(s.getBytes());
            out.flush();
        }

        in.close();
        out.close();

    }

使用Zip对多文件进行压缩
setComment:写注释
压缩没一个文件之前都需要putNextEntry
CheckedOutputStream:设置校验方式

GZip和Zip可以压缩任何东西,不限于文件,可以是通过网络发送的数据

java档案文件

Zip也被应用于JAR(java档案文件)
JDK自带的jar程序可以自动压缩文件
典型方法:
jar cf myJarFile.jar *.class

创建了一个名为myJarFile的jar文件并包含了当前目录下多有的class文件

对象序列化

java对象序列化:实现了Serializeable接口的对象可以转换成一个字节序列,并且可以从这个字节序列可以完全恢复成原来的对象
序列可以通过网络传输,从Windows电脑到Unix电脑
两个特性:

  • 使得存在其他电脑上的对象完全可以被自己使用
  • 向远程对象发消息时使用序列化参数和返回值

对象序列化是基于字节的
序列化:创建对象的OutputStream,用ObjectOutputStream封装,然后调用writeObject方法
反序列化:创建对象的InputStream,用ObjectInputStream封装,调用readObject方法
序列化把对象中的别的对象的引用也保存了,依次类推形成对象网