JAVA基础课程
第二十二天 I/O流
File类的使用
(1)说明
①java.io.File 类:文件和文件目录路径的抽象表示形式,与平台无关
②File能新建,删除,重命名文件和目录,但File不能访问文件内容本身
③想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是Java程序中的一个File对象,可能没有真实存在的文件或目录。
④File可以作为参数传递给流的构造器
(2)File常用构造器
public File(String pathname) {} //以pathname为路径创建File对象,可以是绝对路径或者是相对路径
public File(String parent, String child) {} //以parent为父路径,child为子路径创建File对象
public File(File parent, String child) {} //根据一个父File对象和子文件路径创建File对象
注意:
①路径分隔符,路径的每级目录都用一个路径分隔符隔开
window和dos默认使用 “\”表示
unix和url使用“/”表示
为了安全隐患,File还提供了一个常量public static final char separatorChar。
②相对路径:相较于某个路径下,指明的路径
绝对路径:包含盘符在内的文件或文件目录的路径
(3)File常用构造器和方法说明
@Test
public void test(){
File file = new File("hello.txt");
File file1 = new File("C:\\Users\\92588\\Documents\\test\\word.txt");
System.out.println(file);
System.out.println(file1);
File file2 = new File("C:\\Users\\92588\\Documents", "test1");
File file3 = new File(file2, "pp.txt");
System.out.println(file2);
System.out.println(file3);
System.out.println("****************1.File类的创建功能**************");
try {
file.createNewFile();//创建文件,如果存在就不创建返回false
} catch (IOException e) {
e.printStackTrace();
}
file1.mkdir();//创建目录,如果文件目录不存在就不创建,如果没有父级目录,也不创建,返回false
file2.mkdirs();//创建文件目录,如果上级目录不存在,一并创建
System.out.println("****************2.File类的删除功能**************");
file2.delete();//删除文件或者目录
System.out.println("****************3.File类的获取功能**************");
//File类的获取功能
System.out.println(file1.getAbsolutePath()); //获取绝对路径
System.out.println(file1.getPath()); //获取路径
System.out.println(file1.getName()); //获取名称
System.out.println(file1.getParent()); //获取上层目录路径
System.out.println(file1.length()); //文件长度
System.out.println(file1.lastModified()); //最后更新时间
//获取目录下所有文件名称
String[] list = file1.list();
for (String s : list) {
System.out.println(s);
}
File[] files = file1.listFiles();
//获取目录下所有文件
for (File file4 : files) {
System.out.println(file4);
}
//File判断功能
System.out.println("****************4.File判断功能**************");
System.out.println(file.isDirectory());//是否是文件目录
System.out.println(file.isFile());//是否是文件
System.out.println(file.exists());//是否存在
System.out.println(file.canRead());//是否可读
System.out.println(file.canWrite());//是否可写
System.out.println(file.isHidden());//是否隐藏
}
(4)练习
IO流原理及流的分类
(1)Java IO原理
①I/O是Input/OutPut,用于处理设备之间的数据传递。如读写文件,网络通讯等
②Java中,对于数据的输入/输出以“流(stream)”的方式进行
③输入:读取外部数据到内存中
④输出:将内存中的数据输出到外部
⑤输入输出都是以内存为中心。
(2)流的分类
按照操作数据的不同,分为:字节流(8 bit),字符流(16bit)
按照数据流的流向不同,分为:输入流,输出流
按照流的角色不同,分为:节点流,处理流
字节流 | 字符流 | |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
(3)IO流体系
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 |
---|---|---|---|---|
抽象基类 | InputStream | OutputStream | Reader | Writer |
访问文件 | FileInputStream | FileOutputStream | FileReader | FileWriter |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter |
访问管道 | PipeInputStream | PipeOutputStream | PipeReader | PipeWriter |
访问字符串 | StringReader | StringWriter | ||
缓冲流 | BufferendInputStream | BufferendOutputStream | BufferendReader | BufferendWriter |
转换流 | InputStreamReader | OutputStreamWriter | ||
对象流 | ObjectInputStream | ObjectOutputStream | ||
FillerInputStream | FillerOutputStream | FillerReader | FillerWriter | |
打印流 | PrintStream | |||
推回输入流 | PushbackInputStream | PushbackReader | ||
特殊流 | DataInputStream | DataOutputStream |
节点流
/***
* 节点流FileWriter和FileReader一块使用
* 对于文本文件,使用字符流处理
*/
@Test
public void test5(){
FileReader fileReader = null;
FileWriter fileWriter = null;
try {
/***
* 读取word.txt文件
*/
fileReader = new FileReader(new File("word.txt"));
/***
* 写到hello.txt
*/
fileWriter = new FileWriter(new File("hello.txt"));
char[] chars = new char[10];
int len;
while ((len = fileReader.read(chars)) != -1){
String s = new String(chars, 0, len);
fileWriter.write(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileReader != null){
fileReader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileWriter != null) {
fileWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 节点流FileInputStream 和FileOutputStream的使用
*/
@Test
public void test() {
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
fileInputStream = new FileInputStream(new File("C:\\Users\\92588\\Desktop\\相关文档\\学习\\ArrayList源码.md"));
fileOutputStream = new FileOutputStream(new File("C:\\Users\\92588\\Desktop\\相关文档\\学习\\ArrayList源码1.md"));
byte[] ch = new byte[1024];
int len;
while ((len = fileInputStream.read(ch)) != -1){
fileOutputStream.write(ch,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(fileInputStream != null){
fileInputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(fileOutputStream != null){
fileOutputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
缓冲流
/***
* 缓冲流
* 提供流的读取和写入熟读,因为内部提供了一个缓冲区
* 处理流,也就是“嵌套”在自己的流的基础上。
*/
@Test
public void test(){
FileInputStream fis = null;
FileOutputStream fos = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
try {
fis = new FileInputStream(new File("C:\\Users\\92588\\Desktop\\相关文档\\学习\\Java基础汇总.md"));
fos = new FileOutputStream(new File("C:\\Users\\92588\\Desktop\\相关文档\\学习\\1.md"));
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
byte[] b = new byte[1024];
int lem;
while ((lem = bis.read(b)) != -1){
bos.write(b,0,lem);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//资源关闭,先关闭外层流的同时,内层流同时关闭
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
/*
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
转换流
package com.test.course.filetest;
import org.junit.Test;
import java.io.*;
/**
* 〈转换流〉 -- 属于字符流
* InputStreamReader:将一个字节的输入流转换为字符的输入流
* OutputStreamWriter:将会一个字符的输入流转换为字节的输出流
* 字节流和字符流之间的转换
*
* @author PitterWang
* @create 2020/5/12
* @since 1.0.0
*/
public class FileTest3 {
@Test
public void test(){
InputStreamReader isr = null;
try {
FileInputStream fis = new FileInputStream(new File("hello.txt"));
isr = new InputStreamReader(fis,"UTF-8");
/* FileOutputStream fos = new FileOutputStream(new File(""));
OutputStreamWriter osw = new OutputStreamWriter(fos);*/
char[] chars = new char[1024];
int len;
while ((len = isr.read(chars)) != -1){
String s = new String(chars, 0, len);
System.out.println(s);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(isr != null){
isr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
字符编码
常见的编码表
ASCII:美国标准信息码表
IOS8859-1:拉丁码表
GB2312:中国编码表
GBK:中国编码表升级
Unicode:国际标准码
UTF-8:边长的编码方式,可用1-4个字节来表示一个字符
标准输入、输出流
(1)System.in和System.out分别代表了系统标准的输入(键盘输入)和输出设备(控制台输出)
(2)System.in的类型是InputStream,System.out类型是PrintStream,其实是OutputStream的子类
(3)重定向:通过System的setIn方法,setOut方法对默认设备进行改变
(4)使用
package com.test.course.filetest;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
/**
* 〈System练习〉
*
* @author PitterWang
* @create 2020/5/13
* @since 1.0.0
*/
public class SystemTest {
//方法1:使用Scanner
//方法2:使用System.in ->转换流 ->BufferedReader的readLine
public static void main(String[] args){
InputStreamReader isr = null;
try {
isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
while (true){
String date = br.readLine();
if("exit".equals(date)){
break;
}
System.out.println(date.toUpperCase());
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if(isr!= null){
try {
isr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
打印流
(1)实现将基本数据类型的数据格式转为字符串
(2)打印流:PrintStream和PrintWriter
①提供了一系列的重载print()和println()方法
②System.out返回的就是PrintStream的实例
package com.test.course.exceptiontest;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
/**
* 〈PrintTest〉
*
* @author PitterWang
* @create 2020/5/13
* @since 1.0.0
*/
public class PrintTest {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("hello.txt");
PrintStream printStream = new PrintStream(fos,true);
if (printStream != null) {
System.setOut(printStream); //修改输出位置到文件
}
for (int i = 0; i < 255; i++) {
System.out.print((char)i);
if(i%50 == 0){
System.out.println();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (fos == null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
数据流
(1)为了方便操作Java中的基本数据类型和String的类型,可以使用数据流
(2)数据流有两个类
DataInputStream和DataOutputStream
package com.test.course.filetest;
import org.junit.Test;
import java.io.*;
/**
* 〈DataXXXStream〉
*
* @author PitterWang
* @create 2020/5/13
* @since 1.0.0
*/
public class DataStreamTest {
public static void main(String[] args) throws FileNotFoundException {
DataOutputStream dos = null;
try {
dos = new DataOutputStream(new FileOutputStream("hello.txt"));
dos.writeUTF("哈哈哈");
dos.flush();
dos.write(12);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dos == null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void test(){
DataInputStream dis = null;
try {
dis = new DataInputStream(new FileInputStream("hello.txt"));
String name = dis.readUTF();
int age = dis.read();
System.out.println(name);
System.out.println(age);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (dis == null) {
try {
dis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
对象流
(1)ObjectInputStream和ObjectOutPutStream
(2)用于存储和读取基本数据类型数据或对象的处理流。他可以把Java中的对象写入数据源中,也可以把对象从数据源中还原回来。
(3)序列化:用ObjectOutputStream类保存基本数据类型或对象的机制
反序列化:用ObjectInputStream类读取基本数据类型数据或对象机制
(4)ObjectInputStream和ObjectOutPutStream不能序列号static和transient修饰的成员变量
*(5)Java序列化机制,允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或通过网络进行传输。其他程序获得到这种二进制流,就可以恢复成原来的Java对象
package com.test.course.filetest;
import org.junit.Test;
import java.io.*;
/**
* 〈ObjectXXXStreamTest〉
*
* @author PitterWang
* @create 2020/5/13
* @since 1.0.0
*/
public class ObjectStreamTest {
/**
* 把实现Serializable的对象写入到object.dat中
*/
@Test
public void test(){
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
oos.writeObject(new Person(1,"nidaye"));
oos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos == null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 读取并转成对应对象
*/
@Test
public void test2(){
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("object.dat"));
Object o = ois.readObject();
Person s = (Person)o;
System.out.println(s.toString());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
try {
if (ois == null) {
ois.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/***
* ①想要序列化,必须实现Serializable
* ②提供一个serialVersionUID变量
* ③内部属性是可序列化的
*/
class Person implements Serializable{
private static final long serialVersionUID = -1L;
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
随机存取文件流
(1)RadomAccessFile类 ,声明在io包下,但是直接继承Object类,并且实现DataInput,DataOutput这两个接口,意味着这个类即可读也可写
(2)RadomAccessFile类 支持随机访问方式,程序可以直接跳到文件的任意地方进行读,写文件
(3)RadomAccessFile包含一个记录指针,用以标示当前读写处位置
long getFilePointer:获取文件记录指针的当前位置
void seek(long pos):将文件记录指针定位到pos位置
(4)构造器
public RandomAccessFile(String name, String mode)
public RandomAccessFile(File file, String mode)
//mode指的是RandomAccessFile访问模式
r:只读
ew:打开以便读取和写入
rwd:打开以便读取和写入,同步文件内容的更新
rws:打开以便读取和写入,同步文件内容和元数据的更新
(5)如果RadomAccessFile作为输出流,写入到文件如果不存在,则执行过程自动创建,如果存在,就对原有文件内容进行覆盖(默认从头覆盖)
package com.test.course.filetest;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
/**
* 〈RadomAccessFileTest〉
*
* @author PitterWang
* @create 2020/5/13
* @since 1.0.0
*/
public class RadomAccessFileTest {
@Test
public void test(){
RandomAccessFile r = null;
RandomAccessFile r1 = null;
try {
r = new RandomAccessFile(new File("word.txt"), "rwd");
r1 = new RandomAccessFile(new File("word1.txt"), "rwd");
byte[] bytes = new byte[1024];
int len;
while ((len = r.read(bytes)) != -1){
r1.write(bytes,0,len);
}
r1.seek(3);//从指针定位到3位置开始替换
r1.write("sadfdsad".getBytes());
} catch (IOException e) {
} finally {
if (r != null) {
try {
r.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (r1 != null) {
try {
r1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}