Java的IO
Java.io 包几乎包含了所有操作输入、输出需要的类。所有这些流类代表了输入源和输出目标。
Java.io 包中的流支持很多种格式,比如:基本类型、对象、本地化字符集等等。
一个流可以理解为一个数据的序列。输入流表示从一个源读取数据,输出流表示向一个目标写数据。
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。
1.java.io.File
文件和目录路径名的抽象表示。
构造方法:
构造器 | 描述 |
---|---|
File(File parent, String child) | 从父抽象路径名和子路径名字符串创建新的 File 实例。 |
File(String pathname) | 通过将给定的路径名字符串转换为抽象路径名来创建新的 File 实例。 |
File(String parent, String child) | 从父路径名字符串和子路径名字符串创建新的 File 实例。 |
主要方法:
变量和类型 | 方法 | 描述 |
---|---|---|
boolean | createNewFile() | 当且仅当具有此名称的文件尚不存在时,以原子方式创建由此抽象路径名命名的新空文件。 |
boolean | delete() | 删除此抽象路径名表示的文件或目录。 |
boolean | equals(Object obj) | 测试此抽象路径名与给定对象的相等性。 |
File | getAbsoluteFile() | 返回此抽象路径名的绝对形式。 |
boolean | isDirectory() | 测试此抽象路径名表示的文件是否为目录。 |
long | lastModified() | 返回上次修改此抽象路径名表示的文件的时间。 |
boolean | mkdir() | 创建此抽象路径名指定的目录。 |
boolean | mkdirs() | 创建此抽象路径名指定的目录,包括任何必需但不存在的父目录。 |
boolean | setWritable(boolean writable) | 一种方便的方法,用于设置此抽象路径名的所有者写入权限。 |
例子:
File haha = new File("G://idea的创建文件临时//1.txt");
boolean flag = haha.createNewFile();
System.out.println(flag?"创建成功":"创建失败");
File dir = new File("G://1.txt");
dir.createNewFile;//创建文件
dir.mkdir();//创建文件夹,只创建最后一个文件夹 mkdirs创建所有文件夹
File dir = new File("H://haha");
dir.mkdir();
File a = new File(dir,"a.txt");
a.createNewFile();
File b = new File("H://haha","b.txt");
b.createNewFile();
a.delete();
b.delete();
System.out.println(File.pathSeparator);//与系统相关的路径分隔符,为方便起见,表示为字符串
System.out.println(File.separator);//系统相关的默认名称分隔符,为方便起见,表示为字符串
2.文件遍历案例
import java.io.File;
import java.io.IOException;
public class Demo2 {
public static void main(String[] args) throws IOException {
File g = new File("G:\\idea的创建文件临时\\文本");
File[] files = g.listFiles();
listFiles(files);
}
public static void listFiles(File[] files){
if(files!=null&&files.length>0){
for (File file:files) {
if(file.isFile()){
if(file.getName().endsWith(".txt")){//endsWith 测试此字符串是否以指定的后缀结尾。
if(file.length()>0)
//file.delete();
System.out.println("找到了一个txt文件"+file.getAbsolutePath());
}
}else {
File[] files2 = file.listFiles();
listFiles(files2);
}
}
}
}
}
3.文件过滤器
import java.io.File;
public class Demo4 {
public static void main(String[] args) {
File e = new File("e://");
File[] files = e.listFiles();
listFile(files);
}
public static void listFile(File[] files){
if(files!=null&&files.length>0){
for (File file:files) {
if(file.isFile()){
if(file.getName().endsWith(".avi")){
if(file.length()>100*1024*1024)//判断大小进行筛选
System.out.println("找到了一个avi文件"+file.getAbsolutePath());
}
}else {
File[] files2 = file.listFiles();
listFile(files2);
}
}
}
}
}
4.相对与绝对路径
//相对路径:以盘符开始 例如c://a.txt
//绝对路径:java中是相对于项目目录路径 例如 a.txt
File file1 = new File("c://a.txt");
File file2 = new File("a.txt");
System.out.println("File1的路径"+file1.getAbsolutePath());
System.out.println("File2的路径"+file2.getAbsolutePath());
5.流概述
IO流:可以把数据传输的操作看作是数据的流动,分为输入Input和输出Output
java的IO操作就是java.io包下的一些常用类的使用,通过这些常用类对数据进行读取和写出
IO流的分类:通过流的方向可以分为:输入流和输出流
按照流动的数据类型分为:字节流 字符流
顶级父类
*字节流:输入流 InputStream 输出流 outputStream
*字符流(也来源于字节流,只是经过处理变为字符流):输入流 Reader 输出流 Write
记住一切皆字节:
计算机中的任何数据(文本,图片,视频,音乐等等)都是以二进制的形式存储的。在数据传输时 也都是以二进制的形式存储的。后续学习的任何流 , 在传输时底层都是二进制。
5.1:java.io.OutputStream
-
此抽象类是表示输出字节流的所有类的超类。输出流接受输出字节并将它们发送到某个接收器。
需要定义
OutputStream
的子类的应用程序必须始终至少提供一个写入一个输出字节的方法。
方法:
变量和类型 | 方法 | 描述 |
---|---|---|
void | close() | 关闭此输出流并释放与此流关联的所有系统资源。 |
void | flush() | 刷新此输出流并强制写出任何缓冲的输出字节。 |
static OutputStream | nullOutputStream() | 返回一个新的 OutputStream ,它丢弃所有字节。 |
void | write(byte[] b) | 将b.length字节从指定的字节数组写入此输出流。 |
void | wtite(byte[] b,int off,int len) | 将从偏移量off开始的指定字节数组中的len字节写入此输出流。 |
abstract void | write(int b) | 将指定的字节写入此输出流。 |
5.2:java.io.FileOutputStream
文件输出流是用于将数据写入File
或FileDescriptor
的输出流。文件是否可用或是否可以创建取决于底层平台。特别是某些平台允许一次仅打开一个文件以供写入FileOutputStream
(或其他文件写入对象)。在这种情况下,如果涉及的文件已经打开,则此类中的构造函数将失败。
FileOutputStream用于写入诸如图像数据的原始字节流。 要编写字符流,请考虑使用FileWriter
。
构造方法:
构造器 | 描述 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File 对象表示的文件。 |
FileOutputStream(String name, boolean append) | 创建文件输出流以写入具有指定名称的文件。 |
public static void main(String[] args) throws IOException {
FileOutputStream fos = new FileOutputStream("G:\\idea的创建文件临时\\文本\\a.txt",true);
byte[] bytes = {65,66};
fos.write(bytes);
byte[] bytes2 = {65,66,67,68,69};
fos.write(bytes2);
byte[] bytes2 = "ABCDEF".getBytes();
fos.write(bytes2,2,2); //从第三个数字开始写入两个数字
fos.close(); //写在哪在哪关闭
System.out.println("已经写出");
}
5.3:java.io.InputStream
此抽象类是表示输入字节流的所有类的超类。需要定义子类InputStream
应用程序必须始终提供返回输入的下一个字节的方法。
方法:
变量和类型 | 方法 | 描述 |
---|---|---|
void | close() | 关闭此输入流并释放与该流关联的所有系统资源 |
void | mark(int readlimit) | 标记此输入流中的当前位置 |
abstract int | read() | 从输入流中读取下一个数据字节 |
int | read(byte[] b) | 从输入流中读取一些字节数并将它们存储到缓冲区数组 b |
int | read(byte[] b, int off, int len) | 从输入流 len 最多 len 字节的数据读入一个字节数组 |
byte[] | readAllBytes() | 从输入流中读取所有剩余字节 |
int | readNBytes(byte[] b, int off, int len) | 从输入流中读取请求的字节数到给定的字节数组中 |
void | reset() | 将此流重新定位到上次在此输入流上调用 mark 方法时的位置 |
long | skip(long n) | 跳过并丢弃此输入流中的 n 字节数据 |
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("G:\\idea的创建文件临时\\文本\\a.txt");
while (true){
byte b = (byte) fis.read();
if (b == -1){
break;
}
System.out.println((char)b);
}
byte b = (byte)fis.read();
System.out.println((char)b);
byte b2 = (byte)fis.read();
System.out.println((char)b2);
b = (byte)fis.read();
System.out.println((char)b);
byte[] bytes = new byte[10];
int len = fis.read(bytes);//10
System.out.println(new String(bytes,0,len));//将字节变为字符串
len = fis.read(bytes);//10
System.out.println(new String(bytes,0,len));
len = fis.read(bytes);//6
System.out.println(new String(bytes,0,len));
len = fis.read(bytes);
System.out.println(len);
fis.close();
}
5.4:java.io.FileInputStream
A FileInputStream
从文件系统中的文件获取输入字节。可用的文件取决于主机环境。FileInputStream
用于读取诸如图像数据的原始字节流。 要读取字符流,请考虑使用FileReader
。
构造方法:
构造器 | 描述 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的 File 对象 file 命名。 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建 FileInputStream ,该文件由文件系统中的路径名 name 命名。 |
5.5:Writer
-
用于写入字符流的抽象类。 子类必须实现的唯一方法是write(char [],int,int),flush()和close()。 但是,大多数子类将覆盖此处定义的一些方法,以提供更高的效率,附加功能或两者兼而有之。
-
方法:
变量和类型 方法 描述 Writer append(char c) 将指定的字符追加到此writer。 abstract void close() 关闭流,先冲洗它。 abstract void flush() 刷新流。 void write(char[] cbuf) 写一个字符数组 abstract void write(char[] cbuf, int off, int len) 写一个字符数组的一部分。
public static void main(String[] args) throws IOException {
//writer
FileWriter fw = new FileWriter("G:\\idea的创建文件临时\\文本\\b.txt",true);
//fw.write('a');
fw.append("锄禾日当午").append(",").append("汗滴禾下土"); //可以一致追加
fw.write("锄禾日当午");
fw.flush(); //刷新
fw.close();
}
5.6:Reader
-
用于读取字符流的抽象类。 子类必须实现的唯一方法是read(char [],int,int)和close()。 但是,大多数子类将覆盖此处定义的一些方法,以提供更高的效率,附加功能或两者兼而有之。
public static void main(String[] args) throws IOException { FileReader fr = new FileReader("b.txt"); /* while (true){ int c = fr.read(); if (c == -1) break; System.out.print((char)c); }*/ char[] chars = new char[100]; int len = fr.read(chars); System.out.println(new String(chars)); String text = new String(chars,0,len); System.out.println(text.length()); fr.close(); }
6.字节流读取文字
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("b.txt");
byte[] bytes = new byte[1000];//最长识别长度1000
int len = fis.read(bytes);
System.out.println(new String(bytes,0,len));
}
7.字符输出
public static void main(String[] args) throws IOException {
//字符输出(打印流)
PrintStream ps = new PrintStream("G:\\idea的创建文件临时\\文本\\c.txt");
ps.println("haha1");
ps.println("haha2");
ps.println("haha3");
PrintWriter pw = new PrintWriter("G:\\idea的创建文件临时\\文本\\c.txt");
pw.println("haha1");
pw.println("haha2");
pw.println("haha3");
pw.flush();
FileOutputStream fos = new FileOutputStream("G:\\idea的创建文件临时\\文本\\c.txt");
PrintWriter pw = new PrintWriter(fos);//把得到的字节流转化为打印流
pw.println("hohoho1");
pw.println("hohoho2");
pw.println("hohoho3");
pw.flush();
//缓存读取流,将字符输入流 转化为带有缓存的可以一次读取一行的缓存字符读取流
FileReader fw = new FileReader("G:\\idea的创建文件临时\\文本\\c.txt");
BufferedReader br = new BufferedReader(fw);
String text = br.readLine();
System.out.println(text);
}
8.文件加密和解密工具
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
public class Demo6 {
public static void main(String[] args) throws Exception {
System.out.println("请输入文件的全路径");
Scanner input = new Scanner(System.in);
String filename = input.nextLine();
//原文件
File oldFile = new File(filename);
//加密文件 加前缀mi-
File newFile = new File(oldFile.getParentFile(),"mi-"+oldFile.getName());
FileInputStream fis = new FileInputStream(oldFile);
FileOutputStream fos = new FileOutputStream(newFile);
while (true){
int b = fis.read();
if(b == -1){
break;
}
//任何数据^10两次 结果还是其本身 加密解密过程
fos.write(b^10);
}
System.out.println("加密或解密完成");
}
}
9.字节转换字符流
public static void main(String[] args) throws IOException {
//转换流 :将字节流转换成字符流 使用了装饰者模式
FileInputStream fis = new FileInputStream("G:\\idea的创建文件临时\\文本\\b.txt");
//将字节输入流转换为字符输入流
//参数1 要转换的字节流
//参数2 指定编码名称
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
while (true){
int c = isr.read();
if(c==-1){
break;
}
System.out.println((char) c);
}
FileOutputStream fos = new FileOutputStream("G:\\idea的创建文件临时\\文本\\a.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos);
osw.write("床前明月光");
osw.flush();
osw.close();
}
10.收集异常日志
public static void main(String[] args) throws FileNotFoundException {
//收集异常信息
try {
String s = null;
s.toString();
}catch (Exception e){
PrintWriter pw = new PrintWriter("G:\\idea的创建文件临时\\文本\\bug.txt");
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
pw.print(format.format(new Date()));
e.printStackTrace(pw);
pw.close();
}
}
11.properties
//properties文件与properties类
Properties pt = new Properties();
//键=值
pt.put("name","金苹果");
pt.put("info","讲述历了金苹果种植的过程");
FileWriter fw = new FileWriter("G:\\idea的创建文件临时\\文本\\book.properties");
pt.store(fw,"存储的图书");
fw.close();
Properties pt = new Properties();
Reader fw = new FileReader("G:\\idea的创建文件临时\\文本\\book.properties");
pt.load(fw);
System.out.println(pt.get("name"));
System.out.println(pt.get("info"));
}
12.序列化技术
Java 提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。
将序列化对象写入文件之后,可以从文件中读取出来,并且对它进行反序列化,也就是说,对象的类型信息、对象的数据,还有对象中的数据类型可以用来在内存中新建对象。
整个过程都是 Java 虚拟机(JVM)独立的,也就是说,在一个平台上序列化的对象可以在另一个完全不同的平台上反序列化该对象。
类 ObjectInputStream 和 ObjectOutputStream 是高层次的数据流,它们包含反序列化和序列化对象的方法。
public class Demo14 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//序列化
Book b = new Book("金苹果","讲述了种植过程");
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("G:\\idea的创建文件临时\\文本\\book.txt"));
oos.writeObject(b);
oos.close();
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("G:\\idea的创建文件临时\\文本\\book.txt"));
//Object o = ois.readObject();
//System.out.println(o);
Book o1 = (Book) ois.readObject();
System.out.println(o1.getInfo());
}
static class Book implements Serializable {//标记
private String name;
private String info;
public Book(String name, String info) {
this.name = name;
this.info = info;
}
public Book() {}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public String getInfo() {return info;}
public void setInfo(String info) {this.info = info;}
@Override
public String toString() {
return "Book{" +
"name='" + name + '\'' +
", info='" + info + '\'' +
'}';
}
}
}
注意:
一个类的对象要想序列化成功,必须满足两个条件:
1.该类必须实现 java.io.Serializable 接口。
2.该类的所有属性必须是可序列化的。如果有一个属性不是可序列化的,则该属性必须注明是短暂的。
如果你想知道一个 Java 标准类是否是可序列化的,请查看该类的文档。检验一个类的实例是否能序列化十分简单, 只需要查看该类有没有实现 java.io.Serializable接口。
13.try-with-resources
import java.io.*;
public class Demo15 {
public static void main(String[] args) throws FileNotFoundException {
//1.7以前
FileReader fr = null;
try {
FileReader fr = new FileReader("G:\idea的创建文件临时\文本\book.txt");
int c = fr.read();
System.out.println((char)c);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
fr.close();
}catch (Exception e){
e.printStackTrace();
}
}
//jdk9
FileReader fr = new FileReader("G:\\idea的创建文件临时\\文本\\book.txt");
PrintWriter pw = new PrintWriter("G:\\idea的创建文件临时\\文本\\book.txt");
try(fr;pw){
int c = fr.read();
System.out.println((char)c);
}catch (IOException e) {
e.printStackTrace();
}
CloseDemo d = new CloseDemo();
try(d) {
}catch (Exception e){
}
}
static class CloseDemo implements Closeable {
@Override
public void close() throws IOException {
System.out.println("Close方法被调用。");
}
}
}