IO流简介
流的定义:用来处理不同设备之间的数据传输
input:输入:文件中→java程序中:叫输入
output: 输出:java程序中→文件中,叫输出,,把内容写到文件中
按流分向:
字节流:字节输入:InputStream基类、、、字节输出流:OutputStream
字符流:字符输入:Reader、、、字符流:Writer
InputStream字节输入流
方法:
public abstract int read() throwsIOException从输入流中读取数据的下一个字节。一次读一个字节。
public int read(byte[] b) throws IOException从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b
中。一次读一个字节数组。返回读入缓冲区的总字节数。如果因为已到达流末尾而不再有数据可用,则返回 -1。
public int read(byte[] b, int off, int len) throws IOException将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。返回读入缓冲区的总字节数。如果因为已到达流末尾而不再有数据可用,则返回 -1。
public void close() throwsIOException关闭此输入流并释放与该流关联的所有系统资源。
代码实现:一般应用
import java.io.*;
import java.util.Scanner;
/**
* InputStream:所有字节输入流的抽象类
* @author hp
*
*/
public class MyInputStream{
InputStream in;
void readmethod() throws Exception {
byte[] b = new byte[23];
in = new FileInputStream("in.txt");
in.read(b); //一次性读到byte中
in.close();
}
void readmethod2() throws Exception {
byte[] b = new byte[20];
in = new FileInputStream("in.txt");
in.read(b,1,10); //一次性读多少个字节到byte中,从哪个下标开始存
in.close();
System.out.println(new String(b));
}
void readmethod3() throws Exception{
int i;
in = new FileInputStream("in.txt");
OutputStream out = new FileOutputStream("out.txt");
while((i=in.read())!=-1) { //单个字节读
out.write(i); //单个字节写
}
out.close();
in.close();
}
void readmethod4() throws Exception{
in = new FileInputStream(new File("in.txt"));
Scanner sc = new Scanner(in);
String str=null;
while(sc.hasNext()) {
str=sc.nextLine();
System.out.println(str);
}
sc.close();
in.close();
}
void readSkipmethod() throws Exception {
byte[] b = new byte[23];
in = new FileInputStream("in.txt");
System.out.println( in.available());//获取文件大小字节数
in.skip(10);//跳过多少个字节数
in.read(b); //一次性读到byte中
in.close();
System.out.println(new String(b));
}
public static void main(String[] args) throws Exception {
MyInputStream in = new MyInputStream();
in.readmethod2();
//in.readmethod3();
// in.readSkipmethod();
}
}
FileInputStream:文件字节输入流
public class FileInputStream extendsInputStream,从文件系统中的某个文件中获得输入字节
构造方法:
public FileInputStream(File file) throws FileNotFoundException,传入的参数是要读取的文件。
public FileInputStream(String name) throws FileNotFoundException。传入的参数是要读取的文件名。
方法:继承父类方法。
public int read() throws IOException从此输入流中读取一个数据字节。返回下一个数据字节;如果已到达文件末尾,则返回 -1。
BufferedInPutStream:高效字节输入流
public class BufferedInputStream extendsFilterInputStream。在创建 BufferedInputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
构造方法:
public BufferedInputStream(InputStream in)
public BufferedInputStream(InputStream in, int size)
public class Lianxi4 {
publicstatic void main(String[] args) throws IOException {
FileInputStreamfs = new FileInputStream("a.txt");
BufferedInputStreambis = new BufferedInputStream(fs);
byte[] b = new byte [10];
intlen2;
while((len2= (bis.read(b, 2,6))) != -1){
Strings = new String(b,2,6);
System.out.println(s);
}
bis.close();
}
}
OutputStream字节输出流
这是一个抽象类,是所有字节数出流的父类,输出流接收输出字节,并将它们发送到一些接收器,定义OutputStream类,应用至少一个接收器接收字节
返回值类型 | 方法名 | 方法简介 |
void | flush( ) | 刷新输出流,是缓存数据被写出来 |
void | write(byte [ ] b) | 写b.length 字节从指定的字节数组的输出流 |
void | write(byte [ ] b, int off, int len) | 写len字节从字节数组数据中到输入流 |
abstract int | write( int b ) | 将指定的字节写入该输出流中 |
void | close( ) | 关闭流 |
FileOutputStream:(文件字节数出流)
主要功能是从源文件写入资料到指定的文件中
构造方法:
public FileOutputStream(File file) throws FileNotFoundException创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果文件不存在,自动创建文件,如果父目录不存在,报错。
public FileOutputStream(String name) throws FileNotFoundException创建一个向具有指定名称的文件中写入数据的输出文件流。
public FileOutputStream(String name, boolean append) throws FileNotFoundException创建一个向具有指定 name 的文件中写入数据的输出文件流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。如果第二个参数是false,则每次都重新写入。
public FileOutputStream(File file, boolean append) throws FileNotFoundException创建一个向指定 File 对象表示的文件中写入数据的文件输出流。如果第二个参数为 true,则将字节写入文件末尾处,而不是写入文件开始处。如果第二个参数是false,则每次都重新写入。
方法:继承父类方法。在传入字符串时,可以使用String的getBytes()方法将字符串转为byte数组,再使用public void write(byte[] b)方法写入数据。
public void write(int b) throws IOException将指定的字节写入此输出流。一次只能写一个字节,不能写中文,因为一个中文汉字在GBK编码中占2个字节。
publicstatic void main(String[] args) throws IOException {
Filef = new File("a.txt");//写文件时如果文件不存在,会自动创建,但是如果父目录不存在,会报错。
FileOutputStreamos = new FileOutputStream(f);
os.write(98);//一次写入一个字节
os.write('}');
os.write("98".getBytes());//写入的是98
byte[] b = {'a','n','g','w','u'};
os.write(b);//一次写入一个字节数组
os.write(b,0, b.length);
os.write("云和数据".getBytes());//通过String类的getBytes()方法(返回byte数组)将字符串转为byte数组。
os.close();
}
}
BufferedOutputStream(高效字节输出流):
public class BufferedOutputStreamextendsFilterOutputStream,FilterOutputStream是OutputStream的子类。在创建 BufferedOutputStream 时,会创建一个内部缓冲区数组。在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充该内部缓冲区,一次填充多个字节。
构造方法:
public BufferedOutputStream(OutputStream in),传入的参数是普通的字节输出流对象。
public BufferedOutputStream(OutputStream out,int size),size是缓冲区大小,一般不设置,有默认值。缓冲区长度不要太大,否则浪费空间。
方法:继承父类方法。
特别注意:高效流中必须调用flush方法才能写出成功,因为在高效流中有缓冲区,每次调用write方法时其实是先把数据写在缓冲区,调用flush方法时才写到底层输出流中。
为什么不写flush,只写close也可以写入成功?
因为close方法底层其实调用了flush方法,即在关闭时也进行刷新了,我们一般把flush和close都写上。
为什么普通流不需要刷新?
因为普通=流每一次write方法时都调用了底层资源,直接写在底层数据流中。
代码示例:
package io;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Lianxi3 {
publicstatic void main(String[] args) throws IOException {
FileOutputStreamos = new FileOutputStream("cc.txt");//创建普通流,自动生成文件
BufferedOutputStreambos = new BufferedOutputStream(os);//传入普通输出流对象,创建高效流
byte [] c = {'w','y','h','j','a','v','a'};
bos.write(c,2,3);//从数组的索引为2的元素开始长度为3的元素写出:hja
bos.flush();//必须刷新或关闭
bos.close();//关闭流时只需要关闭高效流即可,因为高效流的底层关闭了普通流。
}
}
字符输出流:Writer
public abstract class Writerextends Object,抽象类,子类:BufferedWriter、OutputStreamWriter。。。。
java.io.OutputStreamWriter的子类:FileWriter。
文件字符输出流:FileWriter
功能方法与高效字节输出流相同,,但是字符输出流只能写文本(图片,音乐,视频,都不能使用字符流)
构造方法:
public FileWriter(File file) throwsIOException
public FileWriter(File file, boolean append)throws IOException
public FileWriter(String fileName, booleanappend) throws IOException
public FileWriter(String fileName) throwsIOException
用法与普通字节输出流相同。
方法:
public void write(int c) throws IOException,写入单个字符,参数是要写入字符的int。
public void write(char[] cbuf, int off, intlen) throws IOException写入字符数组的某一部分。cbuf - 字符缓冲区,off - 开始写入字符处的偏移量
,len - 要写入的字符数 。
public void write(String str, int off, int len) throwsIOException写入字符串的某一部分。str - 字符串,off - 开始写入字符处的偏移量,len - 要写入的字符数 。
public void flush() throws IOException刷新该流的缓冲。
public void close() throws IOException,关闭流。
publicclass Lianxi6 {
public static void main(String[] args)throws IOException {
FileWriter f1 = newFileWriter("m.txt");
f1.write('你');
char [] c ={'i','l','o','v','e','j','a','v','a'};
f1.write(c,2,4);
String s = "好好学习天天向上";
f1.write(s, 3, 5);
f1.flush();
f1.close();
}
}
高效字符输出流:BufferedWriter
public class BufferedWriter extends Writer,将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入,可以指定缓冲区的大小,或者接收默认的大小,在大多数情况下,默认值就都用
构造方法:
publicBufferedWriter(Writer out)创建一个使用默认大小输出缓冲区的缓冲字符输出流。
publicBufferedWriter(Writer out, int sz)创建一个使用给定大小输出缓冲区的新缓冲字符输出流。 sz - 输出缓冲区的大小,是一个正整数 。
需要传入普通字符输出流。(必须刷新才能写入成功)
方法:
与文件字符输出流相同。
publicvoid newLine() throws IOException写入一个行分隔符。(换行)
字符输入流:Reader
publicabstract class Readerextends Objectimplements Readable, Closeable。是抽象类,子类:BufferedReader,InputStreamReader(子类:FileReader)
FileReader:(文件字符输入流)
publicclass FileReader extends InputStreamReader。用于读取字符流。
构造方法:
publicFileReader(File file) throws FileNotFoundException
publicFileReader(String fileName) throws FileNotFoundException
方法:
publicint read() throws IOException,读取单个字符。返回作为整数读取的字符,范围在 0 到 65535 之间 (0x00-0xffff),如果已到达流的末尾,则返回 -1。
publicint read(char[] cbuf) throws IOException,将字符读入数组。返回
读取的字符数,如果已到达流的末尾,则返回 -1 。
publicabstract int read(char[] cbuf, int off, int len) throws IOException
将字符读入数组的某一部分。返回读取的字符数,如果已到达流的末尾,则返回 -1 。
代码示例:
publicclass Lianxi7 {
public static void main(String[] args)throws IOException {
FileReader f1 = newFileReader("m.txt");
/* intlen;
while ((len = f1.read()) != -1) {//读取一个字符
System.out.println((char)len);
}*/
char [] c = new char [4];
int len1;
while ((len1 = f1.read(c,1,3)) != -1) {//读取数组
System.out.println(Arrays.toString(c));
}
f1.close();
}
}
高效字符输入流:(BufferedReader)
public class BufferedReader extends Reader,从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
构造方法:
public BufferedReader(Reader in)创建一个使用默认大小输入缓冲区的缓冲字符输入流。
public BufferedReader(Reader in, int sz)创建一个使用指定大小输入缓冲区的缓冲字符输入流。sz -输入缓冲区的大小 。
方法:
继承父类方法。
publicString readLine() throws IOException读取一个文本行。通过下列字符之一即可认为某行已终止:换行 ('\n')、回车 ('\r') 或回车后直接跟着换行。 返回:包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 null 。
InPutStreamReader类:字节字符转换输入流
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
//1.实例化File的对象
//File file = new File("file/input1.txt");
//2.实例化转换输入流的对象
//注意:当一个流的存在的意义是为了实例化另外一个流,则这个流不需要手动进行关闭
//InputStream input = new FileInputStream(file);
//InputStreamReader reader = new InputStreamReader(input);
//使用默认的字符集【GBK】进行实例化转换流
//InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("file/input1.txt")));
//使用指定字符集进行实例化转换流
//字符集一般使用字符串直接传参,不区分大小写,但是,如果字符集书写有误的话,则会跑出java.io.UnsupportedEncodingException
InputStreamReader reader = new InputStreamReader(new FileInputStream(new File("file/input1.txt")),"UTF-8");
//3.读取
char[] arr = new char[16];
int len = 0;
while((len = reader.read(arr)) != -1) {
String string = new String(arr, 0, len);
System.out.println(string);
}
reader.close();
}
}
OutPutStreamWriter类:字节字符转换输出流
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
//需求:将一段文本以utf-8的格式写入到文件中【注,文件格式为默认格式】
//1.实例化FIle对象
//注意:对于所有的输出流而言,文件可以不存在,在进行写入的过程中可以自动进行创建
//但是,对于所有的输入流而言,文件必须先存在,然后才能操作,否则,会抛出FileNotFounedException
File file = new File("file/output1.txt");
//2.实例化转换输出流
//如果不想覆盖源文件中的内容时,则在传参的时候,设置一个参数为true
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file,true), "utf-8");
//3.写入
writer.write("家客户放假啊刚回家");
//4.刷新
writer.flush();
//5.关闭
writer.close();
}
}
SequenceInputStream:
一个SequenceInputStream代表其他输入的逻辑连接,就是将两个或以上输入流进行合并
import java.io.*;
public class MySequenceInputStream {
public static void main(String[] args) throws Exception {
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream("test.txt"));
FileInputStream in1=new FileInputStream("buff.data");
FileInputStream in2 = new FileInputStream("data.txt");
BufferedInputStream bin1 = new BufferedInputStream(in1);//缓冲
BufferedInputStream bin2 = new BufferedInputStream(in2);
SequenceInputStream seq = new SequenceInputStream(bin1,bin2);
int i;
while((i=seq.read())!=-1) {
bout.write(i);
}
bout.close();
seq.close();
}
}
ByteArrayOutputStream
ByteArrayInputStream
输入和输出都是从文件中来的,当然,野了将输出的位置设置在内存上,
这个类实现了一个输出流,其中的数据被写入一个字节数组,当数据被写入时,缓冲区会自动边长
数据可以用toByteArray()和toString()检索
public class TextDemo02 {
public static void main(String[] args) throws IOException {
//定义一个字符串,全部由大写字母组成
String string = "HELLOWORLD";
//内存输入流
//向内存中输出内容,注意:跟文件读取不一样,不设置文件路径
ByteArrayInputStream bis = new ByteArrayInputStream(string.getBytes());
//内存输出流
//准备从内存中读取内容,注意:跟文件读取不一样,不设置文件路径
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int temp = 0;
//read()方法每次只读取一个字符
while((temp = bis.read()) != -1) {
//将读取的数字转为字符
char c = (char)temp;
//将字符变为大写
bos.write(Character.toLowerCase(c));
}
//循环结束之后,所有的数据都在ByteArrayOutputStream中
//取出内容,将缓冲区内容转换为字符串
String newString = bos.toString();
//关闭流
bis.close();
bos.close();
System.out.println(newString);
}
}
对象流:对象序列化
如果将一个对象写入到本地文件中,被称为对象的序列化;
如果将一个对象从本地文件中读取出来,被称为对象反序列化
注意:一个对象流只能操作一个对象,如果试图操作多个对象的话,可以将对象放到数组中,将对象数组的对象进行序列化,写入到本地文件中,再次读出来,获取到的仍然是集合对象,然后将集合进行遍历
public class ObjectStreamDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
//objectOutputStreamUsage();
objectInputStreamUsage();
}
// 写:将对象进行序列化
public static void objectOutputStreamUsage() {
//1.实例化一个Person的对象
Person person = new Person("张三", 10, 'B');
//2.实例化一个对象输出流的对象
ObjectOutputStream output = null;
try {
output = new ObjectOutputStream(new FileOutputStream(new File("file/person.txt")));
//3.将对象写入到流中
output.writeObject(person);
//4.刷新
output.flush();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
try {
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// 读:反序列化
public static void objectInputStreamUsage() {
//1.实例化对象输入流的对象
try {
ObjectInputStream input = new ObjectInputStream(new FileInputStream(new File("file/person.txt")));
//2.读取
Object object = input.readObject();
//3.对象的向下转型
if(object instanceof Person) {
Person p = (Person)object;
System.out.println(p);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
RandomAccessFile类
public class TextDemo01 {
public static void main(String[] args) throws Exception {
RandomAccessFile file = new RandomAccessFile("file.txt", "rw");
// 以下向file文件中写数据
file.writeInt(20);// 占4个字节
file.writeDouble(8.236598);// 占8个字节
//这个长度写在当前文件指针的前两个字节处,可用readShort()读取
file.writeUTF("这是一个UTF字符串");
file.writeBoolean(true);// 占1个字节
file.writeShort(395);// 占2个字节
file.writeLong(2325451l);// 占8个字节
file.writeUTF("又是一个UTF字符串");
file.writeFloat(35.5f);// 占4个字节
file.writeChar('a');// 占2个字节
//把文件指针位置设置到文件起始处
file.seek(0);
// 以下从file文件中读数据,要注意文件指针的位置
System.out.println("——————从file文件指定位置读数据——————");
System.out.println(file.readInt());
System.out.println(file.readDouble());
System.out.println(file.readUTF());
//将文件指针跳过3个字节,本例中即跳过了一个boolean值和short值。
file.skipBytes(3);
System.out.println(file.readLong());
//跳过文件中“又是一个UTF字符串”所占字节
//注意readShort()方法会移动文件指针,所以不用写2。
file.skipBytes(file.readShort());
System.out.println(file.readFloat());
// 以下演示文件复制操作
System.out.println("——————文件复制(从file到fileCopy)——————");
file.seek(0);
RandomAccessFile fileCopy = new RandomAccessFile("fileCopy.txt", "rw");
int len = (int) file.length();// 取得文件长度(字节数)
byte[] b = new byte[len];
//全部读取
file.readFully(b);
fileCopy.write(b);
System.out.println("复制完成!");
}
}