部分资源来自温柔的养猫人,仅供学习参考。
文件I/O
流的概念
用于处理文件内部的数据
- 字节处理流:OutputStream()(输出字节流)、InputStream()(输入字节流);
- 字符处理流:Writer(输出字符流)、Reader(输入字符流);
OutputStream
public abstract class OutputStream extends Object implements Closeable, Flushable{}
Closeable
public interface Closeable extends AutoCloseable{
public void close() throws IOException;
}
Flushable
public interface Flushable{
void flush() throws IOException;
}
No | 方法 | 类型 | 描述 |
---|---|---|---|
01 | public abstract void write(int b) throws IOException; |
普通 | 输出单个字节数据 |
02 | public void write(byte[] b) throws IOException; |
普通 | 输出一组字节数据 |
03 | public void write(byte[] b, int off, int len) throws IOException; |
普通 | 输出部分字节数据 |
将数据写入文件
- 【覆盖】构造方法:
public FileOutputStream(File file) throws FileNotFoundException;
- 【追加】构造方法:
public FileOutputStream(File file, boolean append) throws FileNotFoundException
例子:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); //1.指定要操作文件的路径 if(!file.getParentFile().exists()){ //文件不存在 file.getParentFile().mkdirs(); //创建父目录 } OutputStream output=new FileOutputStream(file); //2.通过子类实例化 String str="www.mldn.cn"; //要输出的文件内容 output.write(str.getBytes()); // 3.将字符串变为字节数组 output.close(); //4.关闭资源 } }
加入自动关闭处理:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); //1.指定要操作文件的路径 if(!file.getParentFile().exists()){ //文件不存在 file.getParentFile().mkdirs(); //创建父目录 } try(OutputStream output=new FileOutputStream(file,true)) { //2.通过子类实例化 String str="www.mldn.cn\r\n"; //要输出的文件内容 output.write(str.getBytes()); // 3.将字符串变为字节数组 }catch(IOException e) { e.printStackTrace(); } } }
InputStream
public abstract class InputStream extends Object implements Closeable
No | 方法 | 类型 | 描述 |
---|---|---|---|
01 | public abstract int read() throws IOException |
普通 | 读取单个字节数据,如果现在已经读取到底了,返回-1 |
02 | public int read(byte[] b) throws IOException |
普通 | 读取一组字节数据,返回的是读取的个数,如果数据已经读取到底了则返回-1 |
03 | public int read(byte[] b, int off, int len) throws IOException |
普通 | 读取一组字节数据(只占数组的部分) |
例:读取文件数据
/JavaAPIDemo.javaimport java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); InputStream input=new FileInputStream(file); byte[] data=new byte[1024]; //开辟一个缓冲区读取数据 int len = input.read(data); //读取数据,数据全部保存在字节数组中,返回读取个数 System.out.println("【"+new String(data,0,len)+"】"); input.close(); } }
新方法
/JavaAPIDemo.javaimport java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); InputStream input=new FileInputStream(file); byte[] data=input.readAllBytes(); //读取全部数据 System.out.println("【"+new String(data)+"】"); input.close(); } }
Writer
public abstract class Writer extends Object implements Appendable, Closeable, Flushable
- 输出字符数组:
public void write(char[] cbuf) throws IOException;
- 输出字符串:
public void write(String str) throws IOException;
使用Writer类输出:
覆盖:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileWriter; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); //父目录必须存在 } // Writer out =new FileWriter(file, true);//内容追加 Writer out = new FileWriter(file); //内容覆盖 String str = "www.mldn.cn"; out.write(str); out.close(); } }
追加:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileWriter; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); //父目录必须存在 } Writer out = new FileWriter(file); //内容覆盖 String str = "www.mldn.cn\r\n"; out.write(str); out.append("中国人民万岁。"); //追加输出内容 out.close(); } }
Reader
public abstract class Reader extends Object implements Readable, Closeable
数据读取:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileReader; import java.io.Reader; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); if(file.exists()){ //文件存在则进行读取 Reader in= new FileReader(file); char data[]=new char[1024]; int len=in.read(data); System.out.println("读取内容:"+new String(data,0,len)); //读取内容:www.mldn.cn 中国人民万岁。 in.close(); } } }
字节流与字符流的区别
在使用OutputStream类输出的时候,如果没有使用close()方法关闭输出流会发现内容依然可以实现正常的输出;但是如果在使用Writer的时候没有使用close()方法关闭输出流,那么这个时候内容将无法进行输出,因为Writer使用到了缓冲区,当使用close()方法的时候实际上会出现有强制刷新缓冲区的情况,所以这个时候会将内容进行输出,如果没有关闭,那么将无法进行输出操作,所以此时如果在不关闭的情况下想将全部的内容进行输出可以使用flush()方法强制性清空。
使用Writer并强制性清空:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileWriter; import java.io.Writer; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); //父目录必须存在 } Writer out = new FileWriter(file); String str = "www.mldn.cn"; out.write(str); out.flush();//强制性刷新 www.mldn.cn } }
字节流在进行处理的时候并不会使用到缓冲区,而字符流会使用到缓冲区,另外使用缓冲区的字符流更加适合进行中文数据的处理,所以在日后的开发中如果要涉及到包含有中文信息的输出,一般都会使用字符流进行处理,但是从另外一方面来讲,字节流和字符流的基本处理形式是相似的,由于IO很多情况下都是进行数据的传输使用(二进制),所以我们的重点将以字节流为主。
转换流
转换流可以实现字节流和字符流操作的功能转换。
类:OutputStreamWriter:
定义: public class OutputStreamWriter extends Writer
构造方法:public OutputStreamWriter(OutputStream out);
类:InputStreamReader:
定义:public class InputStreamReader extends Reader
构造方法: public InputStreamReader(InputStream in);
观察转换
/JavaAPIDemo.javaimport java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("D:"+ File.separator + "hello" + File.separator + "mldn.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs();//父目录必须存在 } OutputStream output=new FileOutputStream(file); Writer out=new OutputStreamWriter(output); //字节流变为字符流 out.write("www.mldn.cn"); //直接输出字符串,字符流适合于处理中文 out.close(); } }
继承关系:
FileWriter:
public class FileWriter extends OutputStreamWriter
FileReader:
public class FileReader extends InputStreamReader
I/O操作深入
字符编码
常用编码格式:
- GBK/GB2312:国标编码,可以描述中文信息,其中GB2312只描述简体中文,而GBK包含简体中文和繁体中文;
- ISO8859-1:国际通用编码,可以用其描述所有的字母信息,如果是象形文字,则需要进行编码处理;
- UNICODE编码:采用十六进制的方式存储,可以描述所有文字信息;
- UTF编码:象形文字部分使用十六进制编码,而普通的字母采用 ISO8859-1编码,它的优势在于适合快速的传输,节约带宽,也就成为了开发中首选的编码,主要使用“UTF-8”编码。
内存操作流
ByteArrayInputStream
- 构造:public ByteArrayInputStream(byte[] buf);
ByteArrayOutputStream
- 构造:public ByteArrayOutputStream();
ByteArrayOutputStream类中的两个重要的方法:
获取数据:public byte[] toByteArray();
使用字符串的形式获取:public String toString();
利用内存流实现一个小写字母转大写字母的操作
/JavaAPIDemo.javaimport java.io.ByteArrayOutputStream; import java.io.InputStream; import java.io.OutputStream; import java.io.ByteArrayInputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { String str="www.mldn.cn"; //小写字母 InputStream input=new ByteArrayInputStream(str.getBytes()); //将数据保存到内存流 OutputStream output=new ByteArrayOutputStream();//读取内存中的数据 int data = 0; while ((data = input.read())!= -1){ //每次读取一个字节 output.write(Character.toUpperCase((char)data)); //保存数据 } System.out.println(output); //WWW.MLDN.CN input.close(); output.close(); } }
管道流
管道流主要功能是实现两个线程之间的IO处理操作。
字节管道流:PipedOutputStream、PipedInputStream
- 连接处理:public void connect(PipedInputStream snk) throws IOException;
字符管道流:PipedWriter、PipedReader
- 连接处理:public void connect(PipedReader snk) throws IOException;
RandomAccessFile
处理超大型文件时有优势
构造方法:
public RandomAccessFile(File file, String mode) throws FileNotFoundException
跳字节读取:
- 向下跳:
public int skipBytes(int n) throws IOException;
- 向回跳:
public void seek(long pos) throws IOException;
输入与输出
打印流
打印流设计思想:
/JavaAPIDemo.javaimport java.io.File; import java.io.FileOutputStream; import java.io.Exception; import java.io.OutputStream; public class JavaAPIDemo { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator +"mldn.txt"); //定义操作文件 PrintUtil pu= new PrintUtil(new FileOutputStream(file)); pu.println("姓名:小强子"); pu.print("年龄:"); pu.println(78); pu.close(); } } class PrintUtil implements AutoCloseable { //实现一些常用数据的输出 private OutputStream output; //不管现在如何进行输出操作,核心使用的就是OutputStream public PrintUtil(OutputStream output) { //由外部来决定输出的位置 this.output = output; } @Override public void close() throws Exception { this.output.close(); } public void print(String str) { //输出字符串 try { this.output.write(str.getBytes()); //输出 } catch (IOException e) { e.printStackTrace(); } } public void println(String str) { this.print(str + "\r\n"); } public void print(long num) { this.print(String.valueOf(num)); } public void println(long num) { this.println(String.valueOf(num)); } }
PrintStream:
public class PrintStream extends FilterOutputStream implements Appendable, Closeable
构造方法:public PrintStream(OutputStream out);
PrintWriter:
public class PrintWriter extends Writer
构造方法:public PrintWriter(OutputStream out);
System类对IO的支持
System类是一个系统类,而且是一个从头到尾一直都在使用的系统类,而在这个系统类之中提供有三个常量:
- 标准输出(显示器):public static final PrintStream out;
- 错误输出:public static final PrintStream err;
- 标准输入(键盘):public static final InputStream in;
BufferedReader类
读取一行数据: public String readLine() throws IOException;
Scanner类
Scanner类的返回值可以为String类型,相较于其他输入方式有优势,Scanner类中有如下几种方法:
- 构造:public Scanner(InputStream source);
- 判断是否有数据:public boolean hasNext();
- 取出数据:public String next();
- 设置分隔符:public Scanner useDelimiter(String pattern);
序列化
序列化基本定义
注意:需继承Serializable父接口。
序列化与反序列化
有了序列化的支持类后,如果想要实现序列化和反序列化操作则可以利用以下两个类完成。
序列化:ObjectOutputStream:
类定义:public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants
构造方法:
public ObjectOutputStream(OutputStream out) throws IOException
操作方法:
public final void writeObject(Object obj) throws IOException
反序列化:ObjectInputStream:
类定义:public class ObjectInputStream extends InputStream implements ObjectInput,ObjectStreamConstants
构造方法:
public ObjectInputStream(InputStream in) throws IOException
操作方法:
public final Object readObject() throws IOException, ClassNotFoundException
transient关键字
该关键字可以将属性脱离序列化。
例:
private transient String name;