IO流
在设备之间进行数据传输的操作
- 在方向上: 输入流、输出流
- 在单位上: 字节流、字符流
字节流
- 字节输入流:InputStream
- 字节输出流:OutputStream
两个抽象类,不能直接实例化,提供了一些具体的子类.例如:
详解
文件字节输入流:FileInputStream
- 构造方法
//推荐使用第一种:直接跟当前的具体路径!
public FileInputStream(String name)throws FileNotFoundException
public FileInputStream(File file) throws FileNotFoundException
- 读数据
public abstract int read():一次读取一个字节
//一次读取一个字节数组,返回值:描述的是实际读取的字节数
public int read(byte[] b) throws IOException
- 使用步骤
1)创建FileInputStream对象:指向哪个文件
2)读数据,展示结果
3)关闭资源 - 示例
一次读取一个字节
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建FileInputStream对象
FileInputStream fis = new FileInputStream("fis.txt") ;
//获取,赋值,判断可以写在一块
//定义一个字节,一次读取一个字节
int by = 0 ;
//结束条件:-1 :当前read():返回值为-1:流对象读取已经到达文件末尾
while((by=fis.read())!=-1) {
//数据没有读取完毕
System.out.print((char)by); //强制转换:造成中文乱码:中文存储的问题
//一个中文:gbk格式:一个中文两个字节,而且第一个字节是负数!
}
//关闭资源
fis.close();
}
}
一次读取一个字节数组
public static void main(String[] args) throws IOException {
//创建一个字节文件输入流对象
FileInputStream fis = new FileInputStream("fis2.txt") ;
//一般情况:定义字节数组的时候:
//一次读取一个字节数组的最终版代码
//长度:是1024或者1024的整数倍
byte[] bytes = new byte[1024] ;
//赋值,判断
//定义一个实际读取的字节数
int len = 0 ;
while((len=fis.read(bytes))!=-1) {
//没有读完,继续读取
System.out.println(new String(bytes, 0, len));
//每次从0开始,读取实际字节数
}
//关闭资源
fis.close();
}
详解
文件字节输出流:FileOutputStream
- 构造方法
//推荐使用第一种:直接跟当前的具体路径!
public FileOutputStream(String name) throws FileNotFoundException
public FileOutputStream(File file) throws FileNotFoundException
//创建输出流对象,并指向文件,将文件内容写入到末尾:第二个参数为:true:写入末尾
public FileOutputStream(String name, boolean append)
- 写数据
//将指定的字节写入此文件输出流。
public void write(int b)
//将 b.length个字节从指定的字节数组写入此文件输出流。
public void write(byte b[])
//将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。
//b - 数据。 off - 数据中的起始偏移量。 len - 要写入的字节数。
public void write(byte b[], int off, int len)
- 使用步骤
1)创建OutputStream字节输出流对象,同时指向某个文件路径
2)写数据:给文件中写入内容
3)关闭相关的系统资源 - 示例
写入字节数组
public class FileOutputStreamDemo {
public static void main(String[] args) throws IOException {
//1)创建OutputStream字节输出流对象,同时指向某个文件路径
// OutputStream out = new FileOutputStream("fos.txt") ;//抽象类多态方式
//创建输出流对象---->调用系统资源:在本地的项目下创建具体文件fos.txt
//流对象---指向文件地址
FileOutputStream fos = new FileOutputStream("fos.txt") ;
//2)写入内容
//通过流对象给文件写入内容(写入的字节数组)
fos.write("hello,outputStream".getBytes());
//3)释放资源
//将输出流对象的系统资源释放掉!
fos.close();
}
}
write(byte[] b, int off, int len)
public static void main(String[] args) throws IOException {
//创建一个文件字节输出流对象
FileOutputStream fos = new FileOutputStream("fos2.txt") ;
byte[] bytes = {97,98,99,100,101} ;
//void write(byte[] b, int off, int len) :写入字节数组的一部分
fos.write(bytes, 1, 2);
//关闭资源
fos.close();
}
末尾追加数据,FileOutputStream(String name, boolean append)
public static void main(String[] args) throws IOException {
//public FileOutputStream(String name, boolean append):
//末尾追加内容
FileOutputStream fos = new FileOutputStream("fos4.txt", true) ;
//写入数据
for(int x = 0 ; x <10 ; x ++) {
fos.write(("hello"+x).getBytes());
//写入一个换行符号
fos.write("\r\n".getBytes());
}
//关闭资源
fos.close();
}
使用FileInputStream,FileOutputStream进行读写复制操作
两种方式,写一种即可
public class CopyFileDemo {
public static void main(String[] args) throws IOException {
//封装d盘的文件FileInputStreamDemo.java ---源文件
//创建字节文件输入流对象
FileInputStream fis = new FileInputStream("d:\\FileInputStreamDemo.java") ;
//封装目标文件:当前项目下:Copy.java
FileOutputStream fos = new FileOutputStream("Copy.java") ;
//读写复制操作
//方式1):1次读取一个字节
int by = 0 ;
while((by=fis.read())!=-1) {
//读一个字节,写一个字节到fos流对象中
fos.write(by);
}
//方式2:一次读取一个字节数组
//定义一个数组
byte[] bytes = new byte[1024] ;
int len = 0 ;
while((len=fis.read(bytes))!=-1) {
//写一个字节数组:从0开始,写入实际字节数
fos.write(bytes, 0, len);
}
//释放资源
fos.close();
fis.close();
}
}
BufferedInputStream:字节缓冲输入流(高效)
只是提供缓冲区,具体文件读写复制操作还是需要用底层流(InputStream/OutputStream)
- 构造方法
public BufferedInputStream(InputStream in)
- 示例
和FIleInputStream相似
两种方式,选一种即可
public class BufferedInputStreamDemo {
public static void main(String[] args) throws IOException {
//创建一个BufferedInputStream流对象
BufferedInputStream bis =
new BufferedInputStream(new FileInputStream("bos.txt")) ;
//方式1:一次读取一个字节
int by = 0 ;
while((by=bis.read())!=-1) {
//展示在控制台上
System.out.print((char)by);
}
//方式2:一次读取一个字节数组
byte[] bytes = new byte[1024] ;
int len = 0 ;
while((len=bis.read(bytes))!=-1) {
System.out.println(new String(bytes,0,len));
}
//释放资源
bis.close();
}
}
BufferedOutputStream:字节缓冲输出流(高效)
只是提供缓冲区,具体文件读写复制操作还是需要用底层流(InputStream/OutputStream)
- 构造方法
//当前缓冲流只是在流中提供了byte[] 缓冲区,默认足够大,一般通过带一个参的构造方法创建!
public BufferedOutputStream(OutputStream out)
public BufferedOutputStream(OutputStream out, int size)
- 示例
和FileOutputStream相似
public class BufferedOutputStreamDemo {
public static void main(String[] args) throws IOException {
//public BufferedOutputStream(OutputStream out)
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("bos.txt")) ;
/**
* this(out, 8192); 第二个参数:缓冲大小8192
*/
//写数据
bos.write("hello,bufferedOutputStream!".getBytes());
//释放资源
bos.close();
}
}
使用字节缓冲流进行文件的读写复制操作
public class CopyFile {
public static void main(String[] args) throws IOException{
//复制开始的时间
long start = System.currentTimeMillis() ;
// method1("BufferedInputStreamDemo.java","Copy.java") ;
method2("BufferedInputStreamDemo.java","Copy.java") ;
//复制结束的时间
long end = System.currentTimeMillis() ;
System.out.println("共耗时"+(end-start)+"毫秒") ;
}
// FileInputStream/FileOutputStream:一次读取一个字节数组
private static void method2(String srcFile, String destFile) throws IOException {
//封装源文件和目的地文件
FileInputStream fis = new FileInputStream(srcFile) ;
FileOutputStream fos = new FileOutputStream(destFile) ;
byte[] buf = new byte[1024] ;
int len = 0 ;
while((len=fis.read(buf))!=-1) {
fos.write(buf, 0, len);
}
//释放资源
fis.close();
fos.close();
}
//FileInputStream/FileOutputStream:一次读取一个字节
private static void method1(String srcFile, String destFile) throws IOException {
//封装源文件和目的地文件
FileInputStream fis = new FileInputStream(srcFile) ;
FileOutputStream fos = new FileOutputStream(destFile) ;
int by = 0 ;
while((by=fis.read())!=-1) {
fos.write(by);
}
//释放资源
fis.close();
fos.close();
}
}
字符流
- 字符输入流:Reader
- 字符输出流:Writer
字符流是在字节输入流之后出现的,解决了中文乱码问题!
一般情况:针对某个文本文件进行读写复制操作: 优先采用字符流 (使用记事本打开并且能读懂!)
两个抽象类,不能直接实例化,提供了一些具体的子类.例如:
详解
InputStreamReader:字符转换输入流
- 构造方法:
//使用默认字符集进行解码(gbk格式)
public InputStreamReader(InputStream in)
//使用指定的字符集进行解码
public InputStreamReader(InputStream in, String charsetName)
- 成员方法
public int read():读单个字符
public int read(char[] cbuf):读字符数据
public int read(char[] cbuf,int offset,int len)读字符数组的一部分
- 示例
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException{
//创建字符转换输入流对象
/*InputStreamReader isr = new InputStreamReader(
new FileInputStream("osw.txt"), "utf-8") ;*/
InputStreamReader isr = new InputStreamReader(
new FileInputStream("osw.txt")) ;//默认gbk格式
//将osw.txt文件内容展示在控制台上
//一次读取一个字符
//public int read():读单个字符
int ch = 0 ;
while((ch=isr.read())!=-1) {
//展示在控制台上
System.out.print((char)ch);
}
//一次读取一个字符数组
char[] chs = new char[1024] ;
int len = 0 ;//实际字符数
while((len=isr.read(chs))!=-1) {
System.out.println(new String(chs,0,len));
}
//关闭资源
isr.close();
}
}
OutputStreamWriter:字节流转字符流
- 构造方法
//gbk格式 使用默认字符集进行编码的字符输出流
public OutputStreamWriter(OutputStream out)
//使用指定的字符集构造出一个字符输出流
public OutputStreamWriter(OutputStream out, Charset cs)
- 成员方法
public void write(int c):写入单个字符
public void write(char[] cbuf):写入字符数组
public abstract void write(char[] cbuf,int off,int len) 写入字符数组的一部分
public void write(String str):写入字符串内容
public void write(String str,int off,int len):写入字符串一部分
- flush()和close()
flush():一个刷新流:将缓冲的数据刷新出来(中文:默认gbk格式:一个中文对两个字节),流刷新之后还可以继续写入数据;
close()方法:将跟该流相关的系统资源释放掉,不再指向当前操作的文件,关闭之后不能再写入数据否则出现IOException - 示例
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException{
/*
OutputStreamWriter osw = new OutputStreamWriter
(new FileOutputStream("osw.txt"), "utf-8") ;//编码格式:utf-8
*/
OutputStreamWriter osw = new OutputStreamWriter
(new FileOutputStream("osw.txt"));
//写入数据
public void write(int c)
osw.write('a');
// public void write(char[] cbuf):写入字符数组
char[] chs = {'我','爱','高','圆','圆'};
osw.write(chs);
//public abstract void write(char[] cbuf,int off,int len)
osw.write(chs, 1, 4);
// public void write(String str)
osw.write("今天老地方见");
//关闭之前:先去刷新流
osw.flush();
//释放资源
osw.close();
}
}
字符转换输入流和字符转换输出流的便捷类
- FileReader/FileWriter —继承自InputStreamReader/OutputStreamWriter
- 构造方法简单
FileReader(String pathname)
FileWriter(String pathname)
- 示例
public class FileReader_andFileWriter_Demo {
public static void main(String[] args) throws IOException {
//封装源文件:OutputStreamWriterDemo.java
FileReader fr = new FileReader("OutputStreamWriterDemo.java") ;
//封装目的文件:当前项目下:Demo.javas
FileWriter fw = new FileWriter("Demo.java") ;
//一次读取一个字符数组
char[] chs = new char[1024] ;
int len = 0 ;
while((len=fr.read(chs))!=-1) {
//写
fw.write(chs, 0, len);
//刷新
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
使用字符流复制文件
public class CopyFile {
public static void main(String[] args) throws IOException {
//1)封装源文件---->InputStreamReader
InputStreamReader isr = new InputStreamReader
(new FileInputStream("OutputStreamWriterDemo.java")) ;
//可以用便捷类
//FileReader fr = new FileReader("OutputStreamWriterDemo.java");
// 2)封装目的地文件---->D盘下 Copy.java OutputStreamWriter
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("D:\\Copy.java")) ;
//可以用便捷类
//FileWriter fw = new FileWriter("D:\\Copy.java");
//一次读取一个字符
int ch = 0 ;
while((ch=isr.read())!=-1) {
//写
osw.write(ch);
//刷新
osw.flush();
}
//关闭资源
osw.close();
isr.close();
}
}
BufferedReader:字符缓冲输入流(高效)
- 构造方法
BufferedReader(Reader r):构造一个字符缓冲输入流提供默认缓冲区大小
- 特有功能
public String readLine():一次读取一行内容,当读取到\n(换行了),就终止!
BufferedReader(Reader r):可以作为键盘录入(使用流的方式)
- 示例
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
//创建字符缓冲输入流对象
BufferedReader br = new BufferedReader(new FileReader("OutputStreamWriterDemo.java")) ;
String line = null ;
while((line=br.readLine())!=null) {
//没有读完毕
System.out.println(line);
}
//释放资源
br.close();
}
}
BufferedWriter:字符缓冲输出流
- 构造方法
public BufferedWriter(Writer out):构造一个缓冲输出流,默认缓冲区大小
- 特有功能
public void newLine():写入行的分隔符(换行)
- 示例
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//创建一个缓冲输出流对象
BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt")) ;
//写数据:
bw.write("hello");
//bw.write("\r\n");
//特有功能
bw.newLine();
bw.write("world");
bw.newLine();
bw.write("Java");
bw.newLine();
//刷新
bw.flush();
//关闭资源
bw.close();
}
}
键盘输入
public class Demo {
public static void main(String[] args) throws IOException {
/*
Scanner sc = new Scanner(System.in) ;
System.out.println("请您输入String数据:");
String str = sc.nextLine() ;
System.out.println(str);
*/
//使用BufferedReader(Reader r):可以作为键盘录入
/*
//分步走
InputStream in = System.in ;
//创建Reader流对象
Reader r = new InputStreamReader(in) ; //字符转换流:通向字节流的桥梁
//创建BufferedReader流对象
BufferedReader br = new BufferedReader(r) ;
*/
//一步走
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)) ;
System.out.println("请您输入一个数据:"); //"100" 数字字符串
//利用BufferedReader:的readLine()读取一行数据
String line = br.readLine() ; //"100"
//String---int: Integer.parseInt(String str)
int num = Integer.parseInt(line) ;
System.out.println("您录入的字符串是:"+num);
}
}
使用BufferedReader/BufferedWriter读写复制
public class Test {
public static void main(String[] args) throws IOException {
//封装源文件
BufferedReader br = new BufferedReader(new FileReader("Demo.java")) ;
//封装目标文件
BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a.java")) ;
//读写
String line = null ;
while((line=br.readLine())!=null) {
//读一行,bw写一行
bw.write(line);
bw.newLine();
bw.flush();
}
//释放资源
bw.close();
br.close();
}
}
读写复制操作小结
字节流
- FileInputStream/FileOutputStream
一次读取一个字节
一次读取一个字节数组 - BufferedInputStrea/BufferedOutputStream(推荐,高效)
一次读取一个字节
一次读取一个字节数组
可以复制文件(文本,音频,视频等)
字符流
- InputStreamReader/OutputStreamWriter
一次读取一个字符
一次读取一个字符数组 - FileReader/FileWriter(同上,只是写法便捷了)
一次读取一个字符
一次读取一个字符数组 - BufferdReader/BufferedWriter(高效)
一次读取一个字符
一次读取一个字符数组
一次读取一行