天天看点

Java学习总结:File类型与IO流File类型 I/O流字节流字符流

File类型

所在包:java.io.File

作用:可以对文件或目录操作,如查看文件或目录的属性信息、创建,删除文件或目录。不能对文件的内容进行访问。如果需要访问文件里的内容,则需要使用输入/输出流

常用构造器:

1. File(String pathname)    通过指定的路径创建一个File对象

File f1=new File("D:"+File.separator+"file1.txt");
           

抽象路径应该尽量使用相对路径,并且目录的层级分隔符尽可能不要直接写"/"或者"\",应该使用File.separator这个常量表示,以避免不同系统带来的差异。

File f2=new File(".\\file2.txt"); //两个反斜杠为转义字符,相当于"\"
           

ile2.txt在当前项目的文件夹中

构造器中指定的路径字符串,如果不是从根路径下开始写的,那么都是相对路径相对于项目名(当前目录.相当于项目名目录)。

2. File(String parent,String child)   通过指定父路径和子路径来创建一个File对象

File f3=new File("D:\\d1","file3.txt");
           

f3绝对路径为 D:\d1\file3.txt

3. File(File parent,String child)   通过指定File对象描述的路径和子路径,创建新File对象

File f4=new File(new File("D:\\d2"),"file4.txt");
           

f4绝对路径为D:\d2\file4.txt

文件和目录操作相关方法

  •  String[]  list()   返回一个字符串数组,命名由此抽象路径名表示的目录中的文件和目录
  •  String[] list(FilenameFilter filter) 过滤文件和目录。true:表示获取的文件和目录;alse:表示要过滤不要的文件和目录。
File f1=new File(".");
	String[] fs1=f1.list(new FilenameFilter() {
		public boolean accept(File dir, String name) {
			return name.startsWith(".");
		}
    });
	for(String s:fs1){
		System.out.println(s);
	}
           

f1获取当前项目目录,过滤获取文件名以"."开头的文件,结果为

.classpath
.project
.settings
           
  • File[]  listFiles()  返回一个抽象路径名数组,表示由该抽象路径名表示的目录中的文件
  • boolean  delete()  删除目录时,必须保证此目录下是空目录

使用递归方法删除非空目录

public static void delDir(String pathname) {
		File file = new File(pathname);
		if(file.exists()) {
			if(file.isDirectory()) {
				File[] fs = file.listFiles();
				if(fs.length!=0) {
					for(File f:fs) {
						delDir(f.getAbsolutePath());
					}
				}
				
			}
			file.delete();
		}else {
			System.out.println("路径不存在!");
		}
	}
           

I/O流

Java中将信息的输入与输出过程抽象为I/O流(Input/Output)

  • 输入:是指数据流入程序,通常我们读取外界数据时使用,所以输入是用来读取(read)数据的。
  • 输出: 是指数据从程序流出,通常我们需要写出数据到外界时使用,所以输出是用来写出(write)数据的

一个流就是一个从数据源向目的地的数据序列,I/O流类一旦被创建就会自动打开通过调用close方法,可以显式关闭任何一个流,如果流对象不再被引用,Java的垃圾回收机制也会隐式地关闭。

I/O流的分类

1.按照流向分:输入流;输出流

2.按照处理数据的单位分:字节流(8位的字节);字符流(16位的字节)

3.按照流的功能分:

  • 节点流(低级流):可以从一个特定的IO设备上读/写数据的流。
  • 处理流(高级流/过滤流):是对一个已经存在的流的连接和封装,通过所封装的流的功能调用实现数据读/写操作。通常处理流的构造器上都会带有一个其他流的参数。
Java学习总结:File类型与IO流File类型 I/O流字节流字符流

字节流

一、字节输出流OutputStream  /  字节输入流 (InputStream——抽象父类)

(1) 字节输出流(OutputStream——抽象父类)

1.write(int b)   将int类型的数据b的低八位二进制写出

如os.write(1025);1025的32位为00000000 00000000 00000100 00000001 ;则只写了一个字节 0000001

2.write(byte[] bs)  将字节数组中的所有字节写出

所以可以把1025的四个字节放入到字节数组bs中,然后.write( bs)。相当于把1025通过4次write(int b)读入

byte[] bs="1025".getBytes();
	os.write(bs);
           

源码为:

public void write(byte b[]) throws IOException {
        write(b, 0, b.length);
}
           
public void write(byte b[], int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                   ((off + len) > b.length) || ((off + len) < 0)) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        for (int i = 0 ; i < len ; i++) {
            write(b[off + i]);
        }
    }
           

(2) 字节输入流 (InputStream——抽象父类)

1. int read()   从流中读取一个字节,存储在一个int类型数据的低八位上。

2. int read(byte[] b)  读取若干个字节,把它们保存到缓冲区b中,返回的整数表示读取的字节数,如果遇到输入流的结尾,返            回-1。

3.int  available()  返回可以从输入流中读取的字节数目,可见读取存在一个指针,如果遇到输入流的结尾,返回0。

通过以下方法可以获得4个字节(若文件内字节数小于4字节则返回真实读取的字节个数):

byte[] bs = new byte[4];
	 int len = is.read(bs);
	 String info = new String(bs);
           

二、文件输出流 FileOutputStream  /  文件输入流  FileInputStream

(1)文件输出流 FileOutputStream

1.重写模式构造器:FileOutputStream(File file)

                                FileOutputStream(String pathname)

2.追加模式构造器:FileOutputStream(File file,boolean append)

                                FileOutputStream(String pathname,boolean append)

(2)文件输入流  FileInputStream

          构造器:FileInputStream(File file)

                        FileInputStream(String pathname)

三、字节缓冲输出流 BufferedOutputStream   /    字节缓冲输如流 BufferedInputStream

(1)字节缓冲输出流 BufferedOutputStream

        字节缓冲输出流内部维护了一个缓冲区(字节数组),当我们使用该流写数据时,会先写入缓冲区,当缓冲区装满时,才会一次性写出到目的地。这样,减少了写出的次数,提高了写出的效率。但是缺乏即时性,因此提供了flush()方法可以清空未满的缓冲区,强制写出。 

        构造器:BufferedOutputStream(OutputStream os)       此构造器内部维护了一个8k大小的缓冲区(字节数组)

                 其实就是调用了下面一个构造器。

public BufferedOutputStream(OutputStream out) {
        this(out, 8192);
    }
           

                BufferedOutputStream(OutputStream os,int size)       此构造器可以自定义缓冲区大小    

   如:

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("io.txt"));
           

   *任何输出流,在关闭操作前,都会将流内的数据写出。

public void close() throws IOException {
        try {
          flush();
        } catch (IOException ignored) {
        }
        out.close();
    }
           

  *当一次性写出的字节数组的长度>=缓冲区,就不使用缓冲区而是直接写出。

public synchronized void write(byte b[], int off, int len) throws IOException {
       if (len >= buf.length) {
           flushBuffer();
           out.write(b, off, len);
           return;
       }
       if (len > buf.length - count) {   //判断需要写出的len字节数是否大于缓冲区中的剩余空闲量
           flushBuffer();
       }
       System.arraycopy(b, off, buf, count, len);
       count += len;
   }
           

(2)字节缓冲输如流 BufferedInputStream

        同样内部维护了一个缓冲区,作用是尽可能的一次性读取更多的字节存到缓冲区,缓冲区默认大小为8k. 我们从缓冲区里读取数据,当缓冲区里的数据被读取完,缓冲区会再次存储新数据。 这样就减少了从硬盘到内存的次数。提高了读取效率。

        构造器: BufferedInputStream(InputStream is)

                        BufferedInputStream(InputStream is,int size)

四、数据流DataOutputStream/DateInputStream

   提供了一些可以直接写出/读取八大基本数据类型的方法,还提供了writeUTF(String s)  /  readUTF();

   构造方法DataOutputStream(OutputStream os)  /  DataInputStream(InputStream is);

  • writeInt(int v)
public final void writeInt(int v) throws IOException {
        out.write((v >>> 24) & 0xFF);
        out.write((v >>> 16) & 0xFF);
        out.write((v >>>  8) & 0xFF);
        out.write((v >>>  0) & 0xFF);
        incCount(4);
    }
           

      底层调用的是OutputStream中的write(int b)方法,这个方法传递的是低八位的int;

      可见writeInt(int v)不过是通过4次的移位,把int类型的4个字节分别移动到低8位(转成byte类型)上传递;

      &0xFF是将8位的数据转化为32位的int类型。

      writeUTF(String s)也是类似的,先判断字符占几个字节,再通过字节数决定移位次数。

五、对象流 ObjectOutputStream /  ObjectInputStream

        对象是存在于内存中的,有的候需要将对象保存到硬盘上,或者将对象传输到另一台计算机上的等等操作。

       序列化:将对象转换成一个字节序列,WriteObject(Object o);

       反序列化:将一个字节序列转换成对应的对象,readObject();

 常用构造器  ObjectOutputStream(OutputStream os)

                       ObjectInputStream(InputStream is)

  • Serializable接口:ObjectOutputStream在进行序列化时需要对象所属的类型必须实现Serializable接口。

                                     此接口内什么都没有,只是作为可序列化的标识。

  • serailVersionUID:实现序列化接口的类需要提供一个常量serialVersionUID,表明该类的版本。

                                      若不显示的声明,在该对象序列化时也会根据当前类的各个方面计算该类的默认serialVersionUID。

                                      但是不同平台的编译器实现有所不同,所以想要跨平台,都应该显示的声明版本号。

                                      如果类的对象序列化存入硬盘上面,之后随着需求的变化更改了类的属性(增加或减少或改名等),

                                      那么当反序列化时,就会出现InvalidClassException,造成了不兼容性的问题。

                                      但当serialVersionUID相同时,就会将不一样的field以type的预设值反序列化,避免了不兼容问题。

  •  transient关键字:使用transient关键字修饰的属性在序列化时其值将被忽略。

字符流

一、字符流  Reader  /  Writer  

        Reader/Writer字符输入/输出流,都是抽象父类

        字符流是以字符(char)为单位读写数据的, 一次处理一个unicode。字符流的底层仍然是基本的字节流;

       字符流只能对纯文本文件进行操作。

二、转换流  OutputStreamWriter  /  InputStreamReader

        可以设置字符集

        常用构造器:OutputStreamWriter(OutputStream out)

                                OutputStreamWriter(OutputStream out,String charsetName)

                                InputStreamReader(InputStream in)

                                InputStreamReader(InputStream in,String charsetName)

三、缓冲字符流  PrintWriter /  BufferedReader

(1)PrintWriter 缓冲字符输出流

         PrintWriter是具有自动行刷新的缓冲字符输出流,其提供了比较丰富的构造方法,通常比BufferedWriter更实用。

常用构造方法  PrintWirter(File file)

                          PrintWriter(String filename)

                          PrintWriter(OutputStream out)

                          PrintWriter(OutputStream out,boolean autoFlush)

                          PrintWriter(Writer writer)

                          PrintWriter(Writer writer,boolean autoFlush)

常用方法:除了write方法,PrintWriter提供了丰富的重载print()和println()方法。

                    println方法在输出目标数据后自动输出一个系统支持的换行符。若该流设置了自动行刷新,那么每当通过println方法               写出的内容都会被实际写出。而不是进行缓存。

(2)  BufferedReader  缓冲字符输入流

      常用构造器 :BufferedReader(Reader reader)

     String  readLine()   该方法连续读取一行字符串,直到读取到换行符位置,返回的字符串中不包含换行符。

四、文件字符流  FileWriter /  FileReader

(1) FileWriter   

     相当于OutputStreamWriter和FileOutputStream合起来的功能。内部也维护着一个缓存区,需要手动调用flush方法进行刷新。

     构造方法   FileWriter(File file)

                        FileWriter(File file,boolean append)

                        FileWriter(String filepath)

                        FileWriter(String filepath,boolean append)

(2) FileReader

      相当于InputStreamReader和FileInputStream合起来的功能,但是不能设置字符集。内部也维护着一个缓存区。

     构造方法  FileReader(File file)

                       FileReader(String filepath)

其他流

System.out:为PrintStream类型,代表标准输出流,默认的数据输出是控制台

    out:是System类的一个静态成员变量

PrintStream ps = System.out;
System.setOut(new PrintStream("out.txt")); //更改输出目的地
           

System.err:为PrintStream类型,代表标准错误输出也流,默认的数据输出是控制台

System.in:为InputStream类型,代表标准输入流,默认的数据源为键盘