I/O操作

JavaIO 类和接口存在于java.IO包中

 

总结:重点掌控:

1):   文件流 :字节/字符,读取/写入流. File开头的四个类

2):   缓冲流: 字节/字符,缓冲读取/写入流.Buffered开头的四个类

3):   对象流-序列化和反序列化(重点了解):  ObjectOutputStream  /  ObjectInputStream

4):   打印流:       printStream  /  printWriter

5):   转换流(字节转换成字符)InputStreamReader/OutputStreamWriter

Java1.7开始使用Files.copy(Path source, OutputStream out);将文件中的所有字节复制到目标文件

 

File类(文件)

 

介绍和路径分隔符:

File类是IO包中唯一表示磁盘文件磁盘目录的对象的路径

该类包含了创建、删除文件、重命名文件、判断文件读写权限以及文件是否存在,查询等功能方法。

只能设置和获取文件本身的信息,不能设置和获取文件的内容。

路径分隔符、属性分隔符

Unix:     使用“/”来分割目录路径。  使用“:”来分割属性
windows:使用“”来分割目录路径。也支持“/”。  使用“;”来分割属性
---------------------------------------------

File提供了两类常亮分别来提供路径分割符、属性分隔符。

1):路径分隔符

2):属性分隔符

表示文件路径:

操作File的路径和名称

 

 

      File getAbsoluteFile()  返回绝对路径名。

      String getAbsolutePath()  返回绝对路径名。

      String getPath() 返回文件路径。

      String getName() 返回由文件的名称。

      String getParent() 返回上级目录文件。

      File getParentFile() 返回此上级目录路径。

 

  

public static void test1(){

      // 创建对象

      File file = new File("F:/Eclipse/eclipse/tset.java");

   System.out.println(file.getAbsoluteFile());//F:Eclipseeclipse set.java

   System.out.println(file.getAbsolutePath());//F:Eclipseeclipse set.java

      System.out.println(file.getName());//tset.java

      System.out.println(file.getPath());//F:Eclipseeclipse set.java

      System.out.println(file.getParent());//F:Eclipseeclipse

      System.out.println(file.getParentFile());////F:Eclipseeclipse

   }

检测File状态的方法

 

      boolean canExecute() 测试应用程序是否可以执行的文件。

      boolean canRead() 测试应用程序是否可以读取的文件。

      boolean canWrite() 测试应用程序是否可以修改的文件。

      boolean isHidden() 测试文件是否是一个隐藏文件。

       long lastModified()  返回此文件最后一次被修改的时间(单位:毫秒)。

      long length() 返回文件的长度大小(单位:字节)。

    

   private static void test2() {

      File file = new File("F:/Eclipse/eclipse/eclipse.exe");

      System.out.println(file.canExecute());//true

      System.out.println(file.canRead());//true

      System.out.println(file.canWrite());//true

      System.out.println(file.isHidden());//false

      System.out.println(file.lastModified());//1475816570000

      System.out.println(new Date(file.lastModified()).toLocaleString());

      System.out.println(file.length());//319984

   }

 

File类中方法:文件操作

boolean isFile() 是否是文件。

boolean createNewFile() 创建一个新的空文件。

static File createTempFile(String prefix, String suffix,File directory)  创建临时文件.

boolean delete() 删除文件 .

void deleteOnExit() 在JVM终止时,删除文件。

boolean exists() 判断文件是否存在。

boolean renameTo(File dest)  重新命名文件。 

   private static void test3() {

      File file = new File("D:/搜狗高速下载/123456.txt");

      System.out.println(file.isFile());//true

      try {

          new File("D:/搜狗高速下载/123456.java").createNewFile();//创建一个新的文件

      } catch (IOException e) {

          e.printStackTrace();

      }

      //file.renameTo(new File("D:/搜狗高速下载/456.txt"));

      file.delete();

     

      //创建临时文件static File createTempFile(String prefix, String suffix,File directory)

      //(perfix临时文件前缀)( suffix临时文件后缀)(directory临时文件保存位置)

      try {

          File.createTempFile("apple", ".rar", new File("D:/搜狗高速下载"));

      } catch (IOException e) {

         

          e.printStackTrace();

      }

   }

File类中方法:目录操作

boolean isDirectory(); 判断是否是目录。
boolean mkdir();  创建目录。 
boolean mkdirs()  创建当前目录和上级目录.
String [] list(); 列出所有的文件名
File [] listFiles(); 列出所有文件对象
Static File[] listRoots();列出系统盘符.
boolean delete() 删除目录/文件 .
oid deleteOnExit() 在JVM终止时,删除目录/文件。 
boolean exists() 判断文件/目录是否存在。
boolean renameTo(File dest)  重新命名目录/文件名。

public static void test4(){

      File file = new File("D:");

      File file1 = new File("D:/搜狗高速下载");

      System.out.println(file.isDirectory());//false

      System.out.println(file1.isDirectory());//true

      file1.delete(); // 删除目录

      file1.mkdir();//创建多级目录建议使用mkdirs();

      String str[] = file1.list();//列出所有文件名

      for (String string : str) {

          System.out.println(string + " ");

      }

      File file2[];

      file2 = File.listRoots();//列出系统盘符

      for (File string : file2) {

          System.out.println(string + " ");

      }

      file2 = file.listFiles();//列出虽有文件夹名和文件名

      for (File string : file2) {

          System.out.println(string + " ");

      }

}
 

输入和输出(IO)

 

为什么程序需要IO?

 

案例一: 打游戏操作,得分比较高,储存游戏的信息(XXX-888分).

此时需要把游戏中的数据储存起来,只能储存在文件中.

案例二:打游戏操作,查看游戏排行榜.排行榜的数据储存在一个文件中的.

此时游戏程序需要去读取文件中的数据,并显示在游戏中.

案例三:上传和下载操作.

-----------------------------

IO操作是一个相对的过程.一般的我们站在程序角度思考(程序的内存)

程序需要数据:把数据流入到程序中,输入

程序需要保存数据,在把数据传递

O流的分类和操作模板:

IO流的分类:站在不同的角度,分流方式是不一样的

1):根据流向划分:  输入流和输出流.

2):根据数据的单位划分:      字节流和字符流.

3):根据功能不同的划分:      节点流和包装流.

---------------------------------------------------------------

四大基流(字节输出流(Writer),字节输入流(Reader),字符输出流(OutputStream).字符输入流(InputStream))

四大基流都是抽象类:其他流都是继承与这四大基流.

我们不能创建四大基流的对象,只能创建其子类对象

无论是什么流,都有close方法,用来关闭资源

如果操作文件,就得开通一个流对象关联我们的磁盘文件,如果不关闭资源,那么磁盘的文件一直被程序所引用.

 

操作IO流的模板:

1):创建源或者目标对象(挖井)

拿文件流距离

输入操作:把文件中的数据流向到程序中,此时文件是源,程序是目标

输出操作:把程序中的数据流向到文件中,此时程序是源,文件是目标.

2):创建IO流对象(接水管)

输入操作:创建输入流对象

输出操作:创建输出流对象;

3):具体的IO操作(传输):

输入操作:输入流对象的read 方法

输出操作:输出流对象的write方法

4):关闭资源(关闭):

输入操作:输入流对象的close方法

输出操作:输出流对象的close方法

操作IO流的六字箴言:

读进来,写出去.

读进来:进来强调的是输入,说明是read()方法

写出去:出去强调的是输出,说明是write方法

文件流

程序跟文件打交道

 

此时的文件指的是纯文本文件.txt(笔记本那种,不要使用Word Excel)

-----------------------------------------------

FileInputStream 文件的字节读取流:

import java.io.File;

import java.io.FileOutputStream;

/**
* 文件的写入流
* @author Mr.Bai
*
*/
public class FileOutputStreamDemo {

public static void main(String[] args) throws Exception {
//1:创建目标对象
File file = new File("Ceshi/abc.txt");
//创建文件字节输出流对象
FileOutputStream stream = new FileOutputStream(file,true);
/*具体的输出操作
void write(int b) 将指定字节写入此文件输出流。
void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
(常用)void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
*/
stream.write(68);
byte [] a = "ABCDEFGHIJKLMN".getBytes();
stream.write(a);//添加一个char字符的数组.
stream.write(a, 3, 6);//添加字符串的指定位置(不含)开始一定长度的字符

//关闭资源对象
stream.close();
}

}

FileOutputStream  文件的字节写入流

import java.io.File;
import java.io.FileOutputStream;

/**
* 文件的写入流
* @author Mr.Bai
*
*/
public class FileOutputStreamDemo {

public static void main(String[] args) throws Exception {
//1:创建目标对象
File file = new File("Ceshi/abc.txt");
//创建文件字节输出流对象
FileOutputStream stream = new FileOutputStream(file,true);
/*具体的输出操作
void write(int b) 将指定字节写入此文件输出流。
void write(byte[] b) 将 b.length 个字节从指定 byte 数组写入此文件输出流中。
(常用)void write(byte[] b, int off, int len) 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
*/
stream.write(68);
byte [] a = "ABCDEFGHIJKLMN".getBytes();
stream.write(a);//添加一个char字符的数组.
stream.write(a, 3, 6);//添加字符串的指定位置(不含)开始一定长度的字符

//关闭资源对象
stream.close();
}

}

利用字节流完成文件的拷贝操作:

正确关闭资源和处理异常的代码:

 

Java 1.7以前:

java1.7(含)以后  自动资源关闭(推荐)

获取进程数据,编译和运行java代码

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;

/**
* 获取进程数据,编译和运行java代码
* @author Mr.Bai
*
*/
public class Precessemo {
public static void main(String[] args) {
String arr = "System.out.println("我的世界我做主!")";
//System.out.println(arr);
try {
eval(arr);
} catch (Exception e) {
e.printStackTrace();
}
}
//运行该方法后,要求控制台输出--我的世界我做主!
private static void eval(String arr) throws Exception {
//1: 使用StringBuider拼接出一个完整的Word程序的字符串
StringBuilder str = new StringBuilder(50);
str.append("public class Word{");
str.append("public static void main(String [] args){");
str.append(arr+";");
str.append("}");
str.append("}");
//System.out.println(str);
//2:添加到Word.java的文件中去
FileOutputStream out = new FileOutputStream("F:Word.java");
out.write((str.toString().getBytes()));
out.close();
//3:调用javac进程来编译Word.java
Process ard =Runtime.getRuntime().exec("javac Word.java");
//读取javac进程中的错误信息
InputStream err = ard.getInputStream();
//读取流中的数据
byte [] buf = new byte[1024];
int len = 0;
while((len = err.read(buf)) > 0){
String string = new String(buf, 0, len);
System.out.println(string);
}
err.close();
//调用java进程来运行Word.class
ard =Runtime.getRuntime().exec("javac Word");
//读取进行中的流信息
InputStream io = ard.getInputStream();
//读取流中的数据
byte [] buy = new byte[1024];
while((len = io.read(buy)) > 0){
String string = new String(buf, 0, len);
System.out.println(string);
}
io.close();
//删除java和class文件
new File("Word.java").delete();
new File("Word.class").delete();
}
}

文件字符流

FileReader       文件的字符读取流

import java.io.File;
import java.io.FileReader;

/**
* 文件字符读取流
* @author Mr.Bai
* 实例 java 1.7后 资源自动关闭
*/
public class FileReaderDemo {

public static void main(String[] args) {
File file = new File("Ceshi/abcdef.txt");

try ( //创建读取流对象
FileReader read = new FileReader(file);) {
//读取操作
//int read(char[] cbuf);将字符读入数组。读取的字符数,如果已到达流的末尾,则返回 -1
char[] sd = new char[5];
int len = 0;
while ((len = read.read(sd)) > 0) {
String str = new String(sd, 0, len);
System.out.println(str);
}
} catch (Exception e) {
e.printStackTrace();
}
//资源自动关闭
}

}

FileWriter         文件的字符写入流

import java.io.File;
import java.io.FileWriter;

/**
* 文件字符流写入操作
* @author Mr.Bai
*
*/
public class FileStreamDemo {

public static void main(String[] args) {
//创建目录
File file = new File("Ceshi/新写入的文件.txt");
try (//创建写入源对象
FileWriter out = new FileWriter(file,true);){
//写入操作
/* 创建需要写入的字符String类型
* 第一种: 通过 void write(String str)写入字符串。
* 第二种: 讲写好的字符串转换成char数组(char [] toCharArray()方法),再将char数组录入到指定目录中
*/
String str = "我爱中国!我爱我家!";
out.write(str);
out.write(str.toCharArray());
}catch (Exception e) {
e.printStackTrace();
}
}

}

文件拷贝

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

/**
* 文件字符流的拷贝操作
* @author Mr.Bai
*
*/
public class DocumentCopyDome {
public static void main(String[] args) {
//创建源
File file = new File("Ceshi/新写入的文件.txt");
//创建目标
File outFile = new File("Ceshi/复制的文件.txt");
try( //创建流对象
//创建源读取流
FileReader reader = new FileReader(file);
//创建目录写入流
FileWriter writer = new FileWriter(outFile);
){
//读取操作
char [] sd = new char[1024];
int len = -1;
//循环读取到char数组中
while((len = reader.read(sd)) > 0){
//循环录入到char数组中
writer.write(sd);
}
}catch (Exception e) {
e.printStackTrace();
}
}
}

使用字节流操作汉子或特殊符号的时候,容易乱码,建议使用字符流

先有字节流,后又字符流,字符流是对字节流的补充

二进制文件:使用记事本打开某个文件,可以看到内容的就是文本文件,否则可以理解为二进制.

一般的操作,二进制文件必须使用字节流.

一般的,操作文本文件,使用字符流.

字符的解码和编码操作

编码: 把字符串转换成byte数组

 

解码: byte数组转换成字符串

 

一定要保证编码和解码的字符相同,否则乱码

包装流和缓冲流

处理流/包装流(相对于节点流更高级):

1:隐藏了底层的节点流的差异,并对外提供了更方便的输入/输出功能,让我们只关心高级流的操作.

2:使用处理流包装了节点流,程序直接操作处理流,让节点流雨底层的设备做IO操作.

3.只需要关闭处理流即可.

包装流如何区分:写代码的时候,发现创建对象的时候,需要创建另一个流对象.

new 包装流(流对象);

--------------------------------------------

缓冲流:

定义:是一个包装流,目的是起缓冲作用.

Sun提供的缓冲区:大小是:8192(1024*8),我们一般不用提升大小,使用默认.

BufferedInputStream:

BufferedOutputStream;

BufferedReader;

BufferedWriter;

目的:

操作流的时候,习惯定义一个byte/char数组,该数组其实就是一个缓冲区.

Int read();每次都从磁盘文件中读取一个字节,直接操作磁盘文件,性能极低.

解决方案:定义一个数组作为缓冲区.

Byte/char [] a = new byte/char[1024];该数组其实就是一个缓冲区,一次性从磁盘文件中读取1024个字节,如此一来,操作磁盘文件的次数少了,性能得以提升.

 

实际操作:

 

使用缓冲流跟未使用缓冲流的比较

转换流

转换流:把字节流转换成字符流

InputStreamReader : 把字节输入流转换成字符输入流

OutputStreamWriter : 把字节读取流转成字符读取流

内存流(储存数据)

 

字节内存流(安卓会用到):

字符内存流(基本不用)

字符串流

StringWriter 字符串的写入流

StringReader 字符串的读取流

对象流(序列化和反序列化)-服务器做的

以后对于我们需要共享数据的类也必须实现Serializable接口.

一些属性出于安全考虑,不应该被序列化,如:密码 解决的办法是该属性使用transient修饰.

使用对象流来完成序列化和反序列化操作:

ObjectOutputStream 通过writeObject方法做序列化操作.

ObjectInputStream 通过readObject方法做反序列化操作.

 序列化的细节,序列化的版本:

1);如果某些数据不需要做序列化,那么此时该怎么做?

理论上说:静态的字段和瞬态的字段是不能做序列化操作的.

transient 修饰的成员.

2):序列化的版本问题:

反序列化java对象时,必须提供该对象的class文件,现在问题是:随着项目的升级,系统的class文件也会升级(增加/删除一个字段).

如何保证两个class文件的兼容性? java通过seriaIversionUID(序列版本号)

打印流(写入)

PrintStream  字节打印流

PrintWrite       字符打印流

-对于PrintWrite来说,

 PrintWriter writer = new PrintWriter(new FileOutputStream("add.txt"),true);

启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时便会立马刷新操作.

如果没有开启自动刷新,则需要手动刷新,或者当缓存区满的时候,在自动刷新.

使用打印流作为输出流,此时的输出操作会特别简单,因为在打印流中:

提供了print方法,打印不换行

提供了println方法,打印在换行.

这两个方法支持打印各种数据类型的数据.因为参数为(Object t);

打印流中的格式化输出(printf方法):

二进制文件的读取操作

DataInputStream  读取二进制文件

DataOutputStream 写入二进制文件

 

 

标准的输入输出:

 

在system类中,有两个常量:

InputStream in = System.in; “标准”输入流.

PrintStream out = System.out;

标准流的重定向操作:

重新定制输入的方向不再是键盘,而是一个文件.

 static void setIn(InputStream in)重新分配“标准”输入流。

此后,System.in的=数据的来源就是通过setIn指定的源.

 

Properties类加载文件

配置文件:资源文件(properties作为拓展名的文件)/属性文件:

 

做项目开发,为何要使用配置文件?

把所有的数据储存在代码中,写死了,”硬性编码”;

比如:在java中需要连接数据库,必须拥有数据的账号和密码.

此时我们就得在java代码中编写类似的代码:

String ID = “Admin”;

String password = “asdfghjkl@16,#5”;

代码程序运行OK

但是,以后我们把项目部署在别人电脑/服务器中,别人电脑中的数据库的账号密码可以不再是Admin和asdfghjkl@16,#5,此时我们就得去项目中导出去找使用了行号密码的地方.

部署项目的是实施人员,为了安全操作,不能让其直接修改代码.

此时,我们专门为数据库提供了一个配置文件,里面专门储存数据库连接相关的信息

-------------------------------------------------------------

Db.properties

-------------------------------------------------------

#key = value;

ID = Admin

Password = asdfghjkl@16,#5

..........

---------------------------------------------------------

现在数据库的连接信息在db.properties文件中,java代码需要获取该文件中的信息

 

重心转移:java代码如何加载properties文件,如何获取该文件中的数据

必须使用properties类 Hastable 的子类,Map借口的实现类.

随机访问文件

随机访问文件(RandomAccessFile):表示看在该文件的任何位置写入和读取数据.

管道流(了解)

原文地址:https://www.cnblogs.com/it-xiaoBai/p/8081312.html