第一课 IO流的概述
IO(Input Output)概述。
1、特点。
1)IO流用来处理数据之间的流通。
2)Java对数据的操作是通过流的方式。
3)Java用于操作流的对象都在IO包中
4)流按操作分为:字节流和字符流。
5)流按方向分为:输入流和输出流。
2、IO流的常用基类。
1)字节流的抽象基类:InputStream、OutputStream。
2)字符流的抽象基类:Reader、Writer。
注:由这四个类派生出来的子类都是以其父类名作为后缀、其类的功能作为前缀。
第二课 字符流的读写
FileWriter类
一、概述。
1、用来写入字符文件的便捷类。
2、此类的构造方法假定默认字符编码和默认字节缓冲区大小都是可接受的。
二、构造方法摘要。
1、FileWriter(File file) 根据给定的 File 对象构造一个 FileWriter 对象。
2、FileWriter(String fileName, boolean append) 根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。
三、方法摘要。
1、Writer append(char c) 将指定的字符c添加到输出流中。
2、void close() 关闭输出流。
3、void flush() 将输出流中未输出的数据强制清除。
4、void write(char[] cbuf) 将字符数组中的字符写到输出流中。
5、void write(char[] cbuf,int off,int len) 将字符数组内部分字符写到输出流中。off指定了字符数组的其实位置,len指定元素的个数。
6、void write(int i) 向输出流写入一个字符。
示例一:
import java.io.*;
/*
* 字符流和字节流
*
* 字节流的基类。
* InputStream OutputStream
*
* 字符流的基类
*
* Reader Writer
*
* 先学习字符流的特点:
* 既然IO流是操作数据的
* 那么最常见体现形式是:文件
*
* 需求:
* 现在硬盘上创建一个文件,并且写入一些数据。
*
* 找到一个专门用于操作文件Writer子类的对象.FileWriter。后缀名是父类名,前缀名是功能
*/
public class FileWriteDemo {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
//创建一个可以往文件中写入字符数据的字符输出流对象
/*
* 既然是往文件中写入文字数据,那么在创建对象时,就必须明确该文件,(用于存储数据的目的地)
*
* 如果文件不存在,则会自动创建
*
* 如果文件存在,则会覆盖
*
* 如果构造函数中加入true,可以追加。
*
* 注:由于在创建对象时,需要指定创建文件位置,如果指定的位置不存在,就会发生IOException异常,所以在整个步骤中,需要对IO异常进行try处理。
*/
public static void main(String[] args)
{
FileWriter fw=null;
try {
fw=new FileWriter("demo1.txt");
/*
* 调用Writer对象中的write(string)方法。写入数据
*
* 其实数据写入到临时存储缓冲区中,
*
*/
// fw.write("a1b"+LINE_SEPARATOR+"HEHE");
fw.write("xixi7");
/*
* 进行刷新将数据直接写入到目的地
*
*/
fw.flush();
/*
* 关闭前现调用flush()进行刷新之后关闭。
*/
} catch (IOException e) {
}
finally{
if(fw!=null)
try {
fw.close();
} catch (IOException e) {
throw new RuntimeException("关闭失败");
}
}
}
}
FileReader类
一、概述。
1、用来读取字符文件的便捷类。
2、此类的构造方法假定默认字符编码和默认字节缓冲区大小都是适当的。
二、构造函数摘要。
1、FileReader(File file) 在给定从中读取数据的 File 的情况下创建一个新 FileReader。
2、FileReader(String fileName)在给定从中读取的额数据的文件命中创建一个新的FileReader
三、方法的摘要。
1、void close() 关闭字符流。
2、int read() 读取单个字符。
3、int read(char[] chuf) 将字符读入数组,并返回读入的字符数。
示例一:
import java.io.*;
public class FileReadDemo{
public static void main(String[] args) throws IOException
{
// /*
// * 1,创建读取字符数据的流对象
// *
// * 2。在创建流对象时必须明确读取的文件,一定要确定该文件是存在的,如果不在会抛出异常
// *
// * 3.用一个读取流关联一个已存的文件
// *
// */
FileReader fr=new FileReader("demo1.txt");
//第一种读取方式。
// int ch=fr.read();//一次读一个字符而且会自动向下读,返回整数,如果读到末尾返回-1;
// System.out.println((char)ch);
//
// while(true){
// int ch=fr.read();
// if(ch==-1)
// break;
// System.out.println((char)ch);
// }
/*
* 使用read(char[])读取文本中的数据
*
* 先创建字符数组。
*
*
*/
//第二中读取方式。
char[] bf=new char[10];
fr.read(bf);
System.out.println(new String(bf));
System.out.print(new String(bf,0,bf.length));
fr.close();
}
}
文件读写操作练习。
示例:
import java.io.*;
import java.nio.CharBuffer;
/*
* 复制文件。
*
* 原理。
* 1.先创建一个文件用于读取数据。
* 2.定义读取流和文件关联。
* 3.通过不断的读取完成数据的存储。
* 4.关闭资源。
*
*/
public class CopyFileDemo {
public static void main(String[] args)
{
// FileReader fr=new FileReader("demo.txt");
// String[] buf=new String[1024];
// FileWriter fw=new FileWriter("demo1.txt");
// int ch=0;
// while(!((ch=fr.read())==-1))
// fw.write(ch);
// fr.close();
// fw.close();
FileReader fr=null;
FileWriter fw=null;
try{
fr=new FileReader("demo.txt");
char[] bf=new char[1024];
fw=new FileWriter("demo2.txt");
//创建一个字符数组用于缓存读取的数据
int leng=0;
while((leng=fr.read(bf))!=-1)
fw.write(bf,0,leng);
}catch(Exception e){
}finally{
if(fr!=null)
try {
fr.close();
fw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
字符流的缓冲区讲解。
一、概括。
1、缓冲区的出现为了提高对数据的读写效率。
2、缓冲区只有结合流才能使用。
3、在流的基础上对流的功能进行增强。
4、对应类:
BufferedReader。
BufferedWriter。
二、构造函数摘要。
1、BufferedReader类的构造函数。
BufferedReader(Reader in) 创建一个使用默认大小输入缓冲区的缓冲字符输入流。
2、BufferedWriter类的构造函数:
BufferedWriter(Writer out) 创建一个使用默认大小输出缓冲区的缓冲字符输出流。
三、方法摘要。
1、BufferedReader类的方法。
1)close() 关闭该流并释放与之关联的所有资源。
2)int read() 读取单个字符。
3)int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。
4)String readLine() 读取一个文本行。
2、BufferedWriter类的方法。
1)void close() 关闭此流,但要先刷新它。
2)void flush() 刷新该流的缓冲。
3)void newLine() 写入一个行分隔符。
4)void write(char[] cbuf, int off, int len) 写入字符数组的某一部分。
5)void write(int c) 写入单个字符。
示例:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class BufferedWriterDemo {
public static void main(String[] args) throws IOException
{
FileWriter fw=new FileWriter("demo3.txt");
//为了提高写入效率,使用字符流缓冲区。
//创建一个字符流缓冲区的对像,并和制定要被缓冲的对象相关联。
BufferedWriter buf=new BufferedWriter(fw);
//使用缓冲区写入的方法,将数据写入到缓冲区‘
buf.write("abcd");
buf.newLine();
buf.write("xixi");
//使用缓冲区的刷新方法,将数据刷到目的地。
buf.flush();
FileReader fr=new FileReader("demo3.txt");
BufferedReader bur=new BufferedReader(fr);
String s=null;
while((s=bur.readLine())!=null)
System.out.println(s);
// 关闭缓冲区,其实就是关闭的被缓冲的对象。
buf.close();
bur.close();
}
}
缓冲区知识扩展之自定义缓冲区。
import java.io.FileReader;
import java.io.IOException;
/*
* 自定义的读取缓冲区。其实就是模拟一个BufferedReader.
*
* 缓冲区中无非就是封装一个数组,并对外提供了更多方法对数组进行访问。
*
* 其实这些方法最终的操作都是数组的角标
*
* 缓冲的原理:
* 其实就是从源中获取一批数据装进缓冲区。
*
* 在从缓冲区中不断取出一个一个数据
*
* 但此次取完后,再从源中继续取一批数据进入缓冲区,
* 当源中的数据光时,用一个-1,做结束标记,
*
*/
public class MyBufferedReader {
private FileReader r;
//定义一个数组作为缓冲区
private char[] buf=new char[1024];
//定义一个指针用于操作这个数组的中的元素,当操作最后一个元素时,指针应为零
private int pos=0;
//定义一个计数器用于记录缓冲区的数据个数,当数据减到零,缓冲区继续从源中获取数据进入缓冲区
private int count=0;
MyBufferedReader(FileReader r)
{
this.r=r;
}
public int Myread() throws IOException
{
if(count==0)
{
count=r.read(buf);
pos=0;
}
if(count<0)
return -1;
char ch=buf[pos];
pos++;
count--;
return ch;
//1.从源中获取一批数据到缓冲区中.需要先做判断,只有计数器为0时,才从源中获取数据
// if(count==0)
// {
// count=r.read(buf);
// if(count<0)
// return -1;
// pos=0;
// char ch=buf[pos];
// pos++;
// count--;
// }
// else if(count>0)
// {
// char ch=buf[pos];
// pos++;
// count--;
// }
}
public String MyreadLine() throws IOException
{
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=Myread())!=-1)
{ //将从缓冲区读取的字符,存储到缓存行中的缓冲区中
if(ch=='\r')
continue;
if(ch=='\n')
return sb.toString();
sb.append((char)ch);
}
if(sb.length()!=0)
return sb.toString();
return null;
}
public void Myclose() throws IOException
{
r.close();
}
}
根据自定义的缓冲区进行读取操作。
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class BufferedReaderDemo {
public static void main(String[] args) throws IOException
{
FileReader fr=new FileReader("demo1.txt");
MyBufferedReader bur=new MyBufferedReader(fr);
String s=null;
while((s=bur.MyreadLine())!=null)
System.out.println(s);
// 关闭缓冲区,其实就是关闭的被缓冲的对象。
bur.Myclose();
}
}
BufferedReader类的知识扩展。
LineNumberReader类简介:
跟踪行号的缓冲字符输入流。此类定义了方法 setLineNumber(int) 和 getLineNumber(),它们可分别用于设置和获取当前行号。 默认情况下,行编号从 0 开始。
此类代码示例:
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PrintStream;
public class LineNumberReaderDemo {
private static final String LINE_SEPARATOR = System.getProperty("line separator");
public static void main(String[] args) throws IOException
{
FileWriter fw=new FileWriter("demo4.txt");
FileReader fr=new FileReader("demo3.txt");
//获取对象
LineNumberReader Ln=new LineNumberReader(fr);
String s=null;
Ln.setLineNumber(100);//设置行数从100开始
while((s=Ln.readLine())!=null)
{
int c=Ln.getLineNumber();//得到行数
System.out.println(c);
fw.write(Ln.getLineNumber()+":"+s+ LINE_SEPARATOR);
System.out.println(Ln.getLineNumber()+":"+s);
}
fr.close();
fw.close();
}
}
第三课 字节流的读写
OutputStreamWriter类
一、概述。
1、字节流与字符流不同的是,字节流不仅可以操作文本文件,还可以操作媒体文件。
2、读写字节流:
InputStream 输入流。
OutputStreamStream 输出流。
字节流的读写操作示例:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStremDemo {
public static void main(String[] args) throws IOException
{
demo_write();
// demo_read();
}
public static void demo_write() throws IOException
{
//创建字节流输出对象,用于操作文件
FileOutputStream fs=new FileOutputStream("demo5.txt");
// 写入数据直接写入到目的地中。
fs.write("abcd张愉".getBytes());//获取字符串的自己数组
fs.close();
}
public static void demo_read() throws IOException{
//创建一个读取流对象,和指定的文件关联
FileInputStream Is=new FileInputStream("demo5.txt");
System.out.println(Is.available());//返回字节个数;
// int ch=0;
// while((ch=Is.read())!=-1)
// System.out.println((char)ch);
byte[] b=new byte[1024];
int leng=0;
while((leng=Is.read(b))!=-1)
System.out.println(new String(b,0,leng));
Is.close();
}
}
字节流缓冲区讲解。
一、概述。
字节流缓冲区的出现和字符流缓冲区的出现一样,都是为了提高读写的效率。
二、构造函数摘要。
1、BufferedOutputStream类
BufferedOutputStream(OutputStream out) 创建一个新的缓冲输出流,以将数据写入指定的底层输出流。
2、BufferedInputStream类
BufferedInputStream(InputStream in) 创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用
示例:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMp3Text {
public static void Copy_1() throws IOException {
FileInputStream fs=new FileInputStream("家家 - 尘埃.mp3");
FileOutputStream fos=new FileOutputStream("1.mp3");
byte[] b=new byte[fs.available()];
int ch=0;
while((ch=fs.read(b))!=-1)
fos.write(b,0,ch);
fos.close();
fs.close();
}
public static void Copy_2() throws IOException
{
FileInputStream fs=new FileInputStream("家家 - 尘埃.mp3");
//字节流缓冲区
BufferedInputStream bis=new BufferedInputStream(fs);
FileOutputStream fos=new FileOutputStream("2.mp3");
//字节流缓冲区
BufferedOutputStream bos=new BufferedOutputStream(fos);
byte[] b=new byte[1024];
int ch=0;
while((ch=bis.read(b))!=-1)
{
bos.write(b,0,ch);
bos.flush();
}
bis.close();
bos.close();
}
public static void Copy_3() throws IOException
{
FileInputStream fs=new FileInputStream("家家 - 尘埃.mp3");
FileOutputStream fos=new FileOutputStream("3.mp3");
byte[] b=new byte[fs.available()];
fos.write(b);
fos.close();
fs.close();
}
public static void Copy_4() throws IOException
{
FileInputStream fs=new FileInputStream("家家 - 尘埃.mp3");
FileOutputStream fos=new FileOutputStream("4.mp3");
int ch=0;
while((ch=fs.read())!=-1)
fos.write(ch);
fos.close();
fs.close();
}
public static void main(String[] args) throws IOException {
//Copy_1();
Copy_2();
//Copy_3();
//Copy_4();
}
}
第四课 IO流的操作规律。
读取键盘录入
1、标准键盘输入输出流。
InputStream System.in “标准”输入流。 输入设备:键盘。
PrintStream System.out “标准”输出流。输出设备:控制台。
2、转化流。
1)字节流与字符流之间的桥梁。
2)方便字节流与字符流之间的操作。
InputStreamReader将字节流通向字符流
a、获取键盘录入对象。
InputStream in=System.in;
b、将字节流对象转成字符流对象,使用转换流。
InputStreamReaderisr=new InputStreamReader(in);
c、为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader
BufferedReaderbr=new BufferedReader(isr);
示例一:
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class TransStreamDemo {
public static void main(String[] args) throws IOException
{
/*
*1.无论从键盘读取还是打印在控制台上实际上操作的都是字节
*
*
*
*
*
*
*
*/
//读
//字节流
InputStream in=System.in;
//将字节流转化为字符流的桥梁
InputStreamReader Isr=new InputStreamReader(in);
//字符流
BufferedReader bur=new BufferedReader(Isr);
//写
//字节流
OutputStream out=System.out;//控制台
//把字节转化为字符
OutputStreamWriter Osw=new OutputStreamWriter(out);
BufferedWriter bufw=new BufferedWriter(Osw);
String line=null;
while((line=bur.readLine())!=null)
{
if(line.equals("over"))
break;
// else
// System.out.println(s.toUpperCase());
// Osw.write(line.toUpperCase()+"\r\n");//把字符流发送给控制台
// Osw.flush();
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
}
}
示例二:
import java.io.*;
/*读取键盘上的数据,并且打印在控制台上
*
* 键盘本身就是一个标准的输入设备
*
* 对于java而言,对于这种输入设备都有对应的对象
*
*
*/
public class ReadKey {
public static void readKey1()throws IOException
{
InputStream in=System.in;
int ch=in.read();//堵塞式方法,没有录入数据时等待,一直到等有数据时
System.out.println(ch);
//回车键为两个字符
int ch1=in.read();//堵塞式方法,没有录入数据时等待
System.out.println(ch1);
int ch2=in.read();//堵塞式方法,没有录入数据时等待
System.out.println(ch2);
}
public static void readKey2()throws IOException
{
/*
* 获取用户录入的数据如果
*/
InputStream in=System.in;//标准输入流
int ch=0;
while((ch=in.read())!=-1)
System.out.println(ch);
}
public static void readKey3()throws IOException
{
/*
* 获取用户输入的数据,
* 并将数据转化为大写
* 如果用户输入over退出
*
* 1. 因为键盘录入只读取一个字节,要判断是否是over,需要先将读到的自己拼成字符串
*
* 2,那就需要一个容器,StringBuilder
*
* 在用户回车之前判断
*/
InputStream in=System.in;//标准输入流
StringBuilder sb=new StringBuilder();
int ch=0;
while((ch=in.read())!=-1)
{
System.out.println(ch);
if(ch=='\r')
continue;
if(ch=='\n')
{
String temp=sb.toString();
if(temp.equals("over"))
break;
System.out.println(temp.toUpperCase());
sb.delete(0, sb.length());
}
else
sb.append((char)ch);
}
}
public static void readKey4() throws IOException{
InputStream in=System.in;//标准输入流
byte[] b=new byte[1024];
int ch=0;
while((ch=in.read(b))!=-1){
String s=new String(b,0,ch);
s=s.substring(0,ch-2);
if(s.equals("over")){
break;
}
else
System.out.println(s.toUpperCase());
}
}
public static void main(String[] args) throws IOException
{
// readKey1();
// readKey2();
// readKey3();
readKey4();
}
}
IO流读写规律总结:
“`
转化流:
InputStreamReader:自节到字符的桥梁。解码。
OutputStreamWriter:字符到字节的桥梁。编码。
流的操作规律:
之所以要弄清这个规律,是因为流的对象太多,开发时不知道用那个对象合适
想要知道开发时用那个对象,只要通过四个明确即可。
1,明确源和目的(汇)
源:InputStream Reader
目的: OutputStream Writer
2,明确数据是否是纯文本数据
源:是纯文本 :Reader
否 :InputStream
目的: 是纯文本 : Writer
否 : OutputStream
到这里就可以明确需求中的具体要用那个体系
3,明确具体的设备
源设备:
+
硬盘(文件):File
键盘 :System.in
内存 :数组
网络 :Socket流
目地设备:
硬盘: File
控制台:System.in
内存: 数组
网络:Socket流
4,是否需要其他额外功能
1,是否需要高效(缓冲区):
是就加上 buffer
需求1:复制一个文本文件:
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本
是:
源:Reader
目的:Writer
3,明确具体设备
源:
硬盘:File
目的
硬盘:File
FileReader fr=new FileReader(“a.txt”)
FileWriter fw=new FileWriter("b.txt")
4,需要额外的功能吗?
需要:需要高效
BufferedReader bufr=new BufferedReader(new FileReader(“a.txt”))
需求2:读取键盘录入信息写入到一个文件中
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本
是:
源:Reader
目的:Writer
3,明确设备
源:键盘
目的:键盘
InputStream in=System.in
FileWriter fw=new FileWriter("b.txt")
这样做可以完成但是麻烦,将读取的字符数据转化为字符串,再有字节流操作
4,需要额外的功能吗?
需要
转换:
将字节流转化为字符流.因为明确的源是Reader,这样操作文本数据便捷
所以要把已有的字节流转化为字符流,使用字节-》字符的对象InputStreamReader
InputStreamReader isr=new InputStreamReader(System.in);
FileWriter fw=new FileWriter(“a.txt”)
还需要额外的功能吗?
需要 高效
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in))
BufferedWriter bufw=new BufferedWriter(new FileWriter("b.txt"))
需求3:
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本
是:
源:Reader
目的:Writer
3,明确设备
源:
硬盘:File
目的:
控制台:System.in
FileWriter fw=new FileWriter("b.txt")
OutputStream out=System.out
4,需要额外功能吗?
需要:转化
FileWriter fw=new FileWriter("b.txt")
OutputStreamWriter out=System.out
需要高效
BufferedReader bufr=new BufferedReader(new FileWriter("b.txt"))
BufferedWriter bufw=new BufferedWriter(new OutputStream(System.out))
需求4:
1,明确源和目的。
源:InputStream Reader
目的:OutputStream Writer
2,是否是纯文本
是:
源:Reader
目的:Writer
3,明确设备
源:
键盘:System.in
目的
控制台:System.out
InputStream in=System.in
OutputStream out=System。out
4,明确额外的功能?
需要转换,因为都是字节流,但是操作的又都是文本数据,
所以使用字符流操作起来更为便捷
InputStreamReader isr=new InputStreamReader(System.in)
OutputStreamWriter isw=new OutputStreamWriter(System.out)
为了高效
BufferedReader bufr=new BufferedReader(new InputStreamReader(System.in))
BufferedWriter bufw=new BufferedWriter(new OutputStreamWriter(System.out))
==============================================================================================
需求5,
将一个中文字符串数据按照指定的编码表写入到一个文本文件中
1,目的:OutputStream Writer
2,是 纯文本 Writer
3,设备 硬盘 File
FileWriter fw=new FileWriter(“a.txt”)
fw.Writer(“你好”);
注意需求中已经指定了编码表,就不能使用FileWriter,因为FileWriter已经指定了默认的编码表(系统平台的码表)gbk,
只能使用outputstreamreater,
outputstreamreater接受一个字节输出流对象,既然是操作文件,那么对应的对象就应该是Fileoutputstream
OutputStreamReader osr=new OutputStreamReader(new FileoutputStream(“a.txt”),charsetName)
需要高效吗?
要
BufferWriter buw=new (new OutputStreamReader(new FileoutputStream(“a.txt”),charsetName)
什么时候用转化流呢?
1,源或者目的使用的对应的设备是字节流,但是操作的确实文本数据,,可以使用转换作为桥梁
提高对文本操作的便捷
2,一旦操作文本涉及到具体的指定编码表时,也是用!!!!