一、IO流
1.IO流的分类
按操作数据分为:字节流和字符流
按流的流向分为:输入流和输出流
2.IO流的作用
IO流是用来处理设备之间的数据传输的。java对数据的操作是通过流的方式,操作流的对象都在IO包中。
3.IO 流的抽象基类
第一,字节流的抽象基类:InputStream和OutputStream
第二,字符流的抽象基类:Reader和Writer
注意:
这四个基类派生的子类名称都是以父类名称作为子类名称的后缀。比如:InputStream的子类FileInputStream,Reader的子类FileReadr
二、字符流
1.字符流一般是操作纯文本文件的,一般用流FileReader和FileWriter
后缀名是父类名。 前缀名是该流对象的功能。
读取文件用FileReader,而写入文件则用流FileWriter
2.FileWriter流,即向文件中写入数据的流
例子:需求:在硬盘上,创建一个文件并写入一些文字数据。
找到一个专门用于操作文件的Writer子类对象。FileWriter
示例:
import java.io.*;
class FileWriterDemo
{
public static void main(String[] args) throws IOException
{
//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。
//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。
//其实该步就是在明确数据要存放的目的地。
FileWriter fw = new FileWriter("demo.txt");
//调用write方法,将字符串写入到流中。
fw.write("abcde");
//刷新流对象中的缓冲中的数据。
//将数据刷到目的地中。
//fw.flush();
//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。
//将数据刷到目的地中。
//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。
fw.close();
}
}
若想对上面的文件接着继续写,在构造函数传递一个“true”,则写成: <span style="font-family: SimSun;">FileWriter fw = new FileWriter("demo.txt",true); </span><span style="font-family: SimSun;">fw.write("fghio"); </span><span style="font-family: SimSun;">fw.close();</span>
3.FileReader即对已经存在的文件进行读取,读取有两种方式
第一种方式:用read()即一次读取一个字符,并返回int型,即字符相对应的ASCII码值
代码:
import java.io.*;
class FileReaderDemo
{
public static void main(String[] args) throws IOException
{
//创建一个文件读取流对象,和指定名称的文件相关联。
//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundException
FileReader fr = new FileReader("demo.txt");
//调用读取流对象的read方法。
//read():一次读一个字符。而且会自动往下读。
int ch = 0;
while((ch=fr.read())!=-1)
{
System.out.println(
}
fr.close();
}
}
第二种方式:利用方法 int read(char[] cbuf):将字符读入数组
返回的值是读取的字符数。
import java.io.*;
class FileReaderDemo2
{
public static void main(String[] args) throws IOException
{
FileReader fr = new FileReader("demo.txt");
//定义一个字符数组。用于存储读到字符。
//该read(char[])返回的是读到字符个数。
char[] buf = new char[1024];
int num = 0;
while((num=fr.read(buf))!=-1)
{
System.out.println(new String(buf,0,num));
}
fr.close();
}
}<span style="font-family:SimSun;">
</span>
4、字符流的综合练习
需求:将c盘中的一个文本文件复制到D盘
示例:
复制的原理:
其实就是将C盘下的文件数据存储到D盘的一个文件中。
步骤:
1,在D盘创建一个文件。用于存储C盘文件中的数据。
2,定义读取流和C盘文件关联。
3,通过不断的读写完成数据存储。
4,关闭资源。
*/
import java.io.*;
class CopyText
{
public static void main(String[] args) throws IOException
{
copy_2();
}
//第二种读取文件的方式:即将数据先读入到数组中的方式。
public static void copy_2()
{
FileWriter fw = null;
FileReader fr = null;
try//对异常进行处理
{
fw = new FileWriter("SystemDemo_copy.txt");
fr = new FileReader("SystemDemo.java");
//定义一个数组来存放读取到的数据
char[] buf = new char[1024];
int len = 0;
while((len=fr.read(buf))!=-1)
{
//将数组中的有效数据写入流中
fw.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally//此代码块中,存放是关闭资源的操作,由于是必须关闭资源,所以放在finally代码块中
{
if(fr!=null)
try
{
fr.close();
}
catch (IOException e)
{
}
if(fw!=null)
try
{
fw.close();
}
catch (IOException e)
{
}
}
}
//从C盘读一个字符,就往D盘写一个字符。
public static void copy_1()throws IOException
{
//创建目的地。
FileWriter fw = new FileWriter("RuntimeDemo_copy.txt");
//与已有文件关联。
FileReader fr = new FileReader("RuntimeDemo.java");
int ch = 0;
while((ch=fr.read())!=-1)
{
fw.write(ch);
}
fw.close();
fr.close();
}
}
三、字节流
1.字节流是用于操作图片的,即用操作媒体信息的。
2.字节流的读写流是:FileInputStream和FileOutputStrean
FileInputStream是对文件进行读取操作;
FileOutStream是对将信息向文件中写入。
3.FileInputStream
读取文件的方式有三种:第一,利用字节流的特有方法:int available()返回文件中的字节数
第二,用int read()即一次读取一个字节的方式
第三,用int read(数组)即将读取到的字节存入到数组中。
例子:需求,读取一个文件数据,并打印在控制台上
代码:
<span style="font-family:SimSun;font-size:18px;">import java.io.*;
class FileStream
{
public static void main(String[] args) throws IOException
{
readFile_3();
}
//利用字节流的特有方法进行读取。只是用此方法时文件不能太大,否则内存会溢出。
public static void readFile_3()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
//int num = fis.available();
byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。
//将信息读入数组中
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
//利用方法int read(数组)来读取信息
public static void readFile_2()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
byte[] buf = new byte[1024];
int len = 0;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
fis.close();
}
//利用一次读取一个字符的方法来读取,即int read()
public static void readFile_1()throws IOException
{
FileInputStream fis = new FileInputStream("fos.txt");
int ch = 0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
fis.close();
}
}</span>
4.字节流的综合运用
/*
复制一个图片
思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。
*/
import java.io.*;
class CopyPic
{
public static void main(String[] args)
{
FileOutputStream fos = null;
FileInputStream fis = null;
try
{
//定义输出流与文件相关联
fos = new FileOutputStream("c:\\2.bmp");
//定义输入流与要读取的文件相关联
fis = new FileInputStream("c:\\1.bmp");
//定义一个数组,将信息读入数组中
byte[] buf = new byte[1024];
int len = 0;
//通过for循环来将文件中的信息读取完
while((len=fis.read(buf))!=-1)
{
fos.write(buf,0,len);
}
}
catch (IOException e)
{
throw new RuntimeException("复制文件失败");
}
finally//关闭资源
{
try
{
if(fis!=null)
fis.close();
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(fos!=null)
fos.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
四、字符流缓冲区
1.字符流的缓冲区,,内部封装的是数组
读取缓冲区BufferedReader,提供了方法:String readLine(),即一次读取一行
返回的是读取到的改行的字符串,不包含任何行终止符。如果已经达到末尾,则返回null
写入缓冲区BufferedWriter,提供了方法,newLine()即换行
2.缓冲区的综合运用
需求:通过缓冲区复制一个.java文件。
import java.io.*;
class CopyTextByBuf
{
public static void main(String[] args)
{
//定义两个流缓冲区:读取流缓冲区和写入流缓冲区
BufferedReader bufr = null;
BufferedWriter bufw = null;
try
{
bufr = new BufferedReader(new FileReader("BufferedWriterDemo.java"));
bufw = new BufferedWriter(new FileWriter("bufWriter_Copy.txt"));
//通过循环利用方法readLine,一次读取一行的操作来进行读取信息
String line = null;
//readLine方法,底层调用的仍是read()方法
while((line=bufr.readLine())!=null)
{
bufw.write(line);//将读取到的信息写入缓冲区流中
bufw.newLine();//利用写入流缓冲区的换行功能来换行,因为line中并不包括换行符
bufw.flush();//刷新缓冲区,记住,只要用到缓冲区就要记得刷新。
}
}
catch (IOException e)
{
throw new RuntimeException("读写失败");
}
finally//关闭系统资源
{
try
{
if(bufr!=null)
bufr.close();//由于关闭缓冲区,就是关闭缓冲区中的流对象,
//最终关闭的是系统资源,所以此处就不用再写关闭流对象了。
}
catch (IOException e)
{
throw new RuntimeException("读取关闭失败");
}
try
{
if(bufw!=null)
bufw.close();
}
catch (IOException e)
{
throw new RuntimeException("写入关闭失败");
}
}
}
}
五、字节流缓冲区
包括BufferedInputStream和BufferedOutputStream,底层封装的是数组,所以读取时,不用再用read(数组)来读取了
注意:
1.BufferedInputStream并没有功能readLine(),readLine()功能是字符流缓冲区特有的。
2.BufferedOutputStream并没有功能newLine(),newLine()功能是字符流读出流缓冲区特有的。
对字节流缓冲区的综合运用:
/*
演示mp3的复制。通过缓冲区。
BufferedOutputStream
BufferedInputStream
*/
import java.io.*;
class CopyMp3
{
public static void main(String[] args) throws IOException
{
long start = System.currentTimeMillis();
copy();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒");
}
//通过字节流的缓冲区完成复制。
public static void copy()throws IOException
{
BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("c:\\0.mp3"));
BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("c:\\1.mp3"));
int by = 0;
while((by=bufis.read())!=-1)
{
bufos.write(by);
}
bufos.close();
bufis.close();
}
}
六、转换流
字节流和字符流之间的转换流
1.读取流转换流:InputStreamReader,是字节流通向字符流的桥梁
2.写入流转换流:OutputStreamReader:是字符流通向字节流的桥梁
3.InputStream System.in:对应的标准输入设备:键盘,返回值为InputStream
PrintStream System.out:对应的标准输出设备:控制台,返回值为PrintStream,即是OutputStream的子类。
4.键盘录入的最常见写法为:BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
输出设备的最常见的写法
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
综合运用:
需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。
import java.io.*;
class TransStreamDemo
{
public static void main(String[] args) throws IOException
{
/*获取键盘录入对象。
InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader
InputStreamReader isr = new InputStreamReader(in);
//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
BufferedReader bufr = new BufferedReader(isr);
*/
//将上面简化为如下,也是键盘的最常见写法。
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
/*输处设备流的转换
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
BufferedWriter bufw = new BufferedWriter(osw);*/
//输出设备的最常见的写法
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
bufr.close();
}
}
5.
转换流一般伴有字符编码
常用到的编码表示UTF-8和GBK,一般咱们所使用的文件的编码表是GBK
UTF-8是三个字节代表一个字符,而GBK是两个字节代表一个字符
例子:
import java.io.*;
class EncodeStream
{
public static void main(String[] args) throws IOException
{
//writeText();
readText();
}
//对文件以指定的编码表进行读取
public static void readText()throws IOException
{
//在流中执行了以彪编码表GBK来读取文件中的信息
InputStreamReader isr = new InputStreamReader(new FileInputStream("utf.txt"),"gbk");
//将文件读入数组中
char[] buf = new char[10];
int len = isr.read(buf);
//将数组转换为字符串
String str = new String(buf,0,len);
System.out.println(str);
isr.close();//关闭资源
}
//以指定的编码表形式向文件中写入信息。
public static void writeText()throws IOException
{
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"),"UTF-8");
osw.write("你好");
osw.close();
}
}