IO
输入/输出流的分类--流都属于
java.io.*;(记得先引用这个包)
一些分类:
数据流的方向:输入流和输出流
处理数据单位:
字节流(
1个字节1个字节的读取,比如ABC英文符号)和
字符流(
2个字节的读取,比如中文汉字)
按照功能不同:节点流和处理流
注意,文件打开后要colse();
J2SDK 提供所有的流位于java.io内且继承以下四种
抽象流类型:
字节流 | 字符流 | |
输入流 | InputStream | Reader |
输出流 | OutputStream | Writer |
字节流InputStream(可以从文件读数据):
继承自InputStream的流都是
向程序中输入数据,且数据的单位为字节(8 bit)
基本方法:(
注意:
throws IOEception
: 指的是会
抛出
IOEception 。要去
try--catch)
- int read() throws IOException //读取一个字符并以整数的形式返回(0~255, 返回-1意味着已经到输入流的末尾。
- int read(byte[] buffer) throws IOException //读取一系列字节存储到一个数组buffer,返回实际读取的字节数,返回-1意味着已经到输入流的末尾。
- int read(byte[] buffer,int offset, int length) throws IOEception //读取length个字节,并字节数组buffer[offset]开始存,返回实际读取的字节数,返回-1意味着已经到输入流的末尾。
- void close() throws IOExcption //关闭流释放内存资源
- void skip(long n) throws IOExcption //跳过n个字节不读,返回实际跳过的字节数
//读取本身这个java文件,并且打印出代码
import java.io.*;
public class TestFileInputStream{
public static void main(String[] args){
FileInputStream in = null;
try{
in = new FileInputStream("F:\\javajava\\TestFileInputStream.java");
//注意:try--catch里面的东西,就像方法里面的局部变量!!
}catch(FileNotFoundException ex){ //所以没有在try里面写FileInputStream in =new FileInputStream("F:\\javajava\\TestFileInputStream.java");
System.out.println("没有找到文件"); //要是写了。在之后的
in.close()
就无法通过
编译
。找不到这个方法,程序认为没有in这个文件
System.exit(-1);
}
int count=0;
int b =0;
try{
while((b = in.read())!=-1){
System.out.print((char)b);
count++;
}
in.close();
}catch(IOException s){
System.out.println("文件出现问题");
//这里程序运行后会打印出“???”,因为Input/OutputStream是字节流,单个字节操作,中文是两个字节
System.exit(0);
}
System.out.println(count+"字符被打印");
}
}
字节流OutputStream(可以写入数据)
继承自
OutputStream的流是用于
程序中输入数据,且数据的单位为字节(8 bit)
基本方法:
- void write(int b) throws IOEception //向输出流写入一个字节数据,该字节数据为参数b的低8位
- void write(byte[] b) throws IOEception //将一个字节类型的数组中的数据写入输出流
- void write(byte[] b,int off,int len) throws IOEception //将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
- void close() throws IOEception //关闭流释放内存资源
- void flush() throws IOEception //将输出流中缓冲的数据全部写出到目的地
//复制我的F盘\\javajava\\HelloWorld.java文件内容到
F:\\javajava\\game1\\HW.java
import java.io.*;
public class TestFileOutputStream{
public static void main(String[] args){
FileInputStream in = null;
FileOutputStream out = null;
int b = 0;
try{
in = new FileInputStream("F:\\javajava\\HelloWorld.java");
out = new FileOutputStream("F:\\javajava\\game1\\HW.java"); //如果没有这个文件,则程序会帮你创建这个文件
}catch(FileNotFoundException ex){
System.out.println("文件没有找到");
System.exit(-1);
}
try{
while((b=in.read())!=-1){
out.write((char)b);
}
System.out.println("文件复制成功");
}catch(IOException x){
System.out.println("文件出错");
System.exit(-1);
}
}
}
字符流Reader:
继承自Reader 的流都是用于向程序中输入数据(读取该文件的数据),且数据的单位为字符(16 bit)
基本方法:
- int read() throws IOException //读取一个字符并以整数的形式返回(0~255, 返回-1意味着已经到输入流的末尾。
- int read(char[] cbuf) throws IOException //读取一系列字节存储到一个数组cbuf,返回实际读取的字节数,返回-1意味着已经到输入流的末尾。
- int read(char[] cbuf,int offset, int length) throws IOEception //读取length个字节,并字节数组cbufr[offset]开始存,返回实际读取的字节数,返回-1意味着已经到输入流的末尾。
- void close() throws IOExcption //关闭流释放内存资源
- void skip(long n) throws IOExcption //跳过n个字节不读,返回实际跳过的字节数
//打印当前文件的代码
import java.io.*;
public class TestFileReader{
public static void main(String[] args){
FileReader fr = null;
int c =0;
try{
fr =new FileReader("F:\\javajava\\TestFileReader.java");
while((c=fr.read())!=-1){
System.out.print((char)c);
}
fr.close();
}catch(FileNotFoundException ex){
System.out.println("文件没有找到"); //这里程序运行后就会打印完整 的中文,英文Reader,Writer都是字符流,可以两个字节操作
System.exit(-1);
}catch(IOException e){
System.out.println("文件出错");
System.exit(-1);
}
}
}
Writer:
继承自Writer的流都是用于程序中输入数据,且数据的单位为字符(16 bit):
基本方法:
- void write(int c) throws IOEception //向输出流写入一个字符数据,该字节数据为参数c的低8位
- void write(char[] cbuf) throws IOEception //将一个字符类型的数组中的数据写入输出流
- void write(char[] cbuf,int off,int len) throws IOEception //将一个字符类型的数组中的从指定位置(off)开始的len个字节写入到输出流
- void write(String string) throws IOEception //将一个字符串中的字符写入到输出流
- void write(String string,int offset,int length) throws IOEception //将一个字符串从offset开始的length个字符写入到输出流
- void close() throws IOEception //关闭流释放内存资源
- void flush() throws IOEception //将输出流中缓冲的数据全部写出到目的地
//写入文件 50000以内的符号(包含中文,字母等等)
import java.io.*;
public class TestFileWriter{
public static void main(String[] args){
FileWriter fw = null;
try{
fw = new FileWriter("F:\\javajava\\game1\\unicode.dat");
for(int c=0;c<=50000;c++){ //char两个字节,最大到65535,所以没有越界
fw.write(c);
}
fw.close();
}catch(IOException el){
el.printStackTrace();
System.out.println("文件写入错误");
System.exit(-1);
}
}
}
处理流:
处理类型 | 字符流 | 字节流 |
Buffering |
BufferedReader
BufferedWriter
|
BufferedInputStream
BufferedOutputStream
|
Filtering |
FilterReader
FilterWriter
|
FilterInputStream
FilterOutputStream
|
Converting between byte and character |
InputStreamReader
OutputStreamWriter
|
|
Object Serialization | --- |
ObjectInputStream
ObjectOutputStream
|
Data conversion | --- |
DataInputStream
DataOutputStream
|
Counting | LineNumberReader | LineNumberInputStream |
Peeking ahead | PushbackReader | PushbackInputStream |
Printing | PrintWriter | PrintStream |
缓冲流(Buffered):
要“
套接”在相应的
节点流之上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法。
- BufferedReader(Reader in)
- BufferedReader(Reader in ,int sz) //sz为自定义缓存区的大小
- BufferedWriter(Writer out)
- BufferedWriter(Writer out,int sz)
- BufferedInputStream(InputStream in)
- BufferedInputStream(InputStream in,int size)
- BufferedOutputStream(OutputStream out)
- BufferedOutputStream(OutputStream out,int size)
- 缓冲输入流支持其父类的mark和reset方法
- BufferedReader提供了readLine方法用于读取一行字符串
- BufferedReader提供了newLine方法用于读取一行字符串
- 对于输出的缓冲流,写入的数据会在内存中缓存,使用flush方法将会使内存中的数据理科写出
一些例子:
import java.io.*;
public class TestBufferStream1{
public static void main(String[] args){
try{
FileInputStream fis = new FileInputStream("F:\\javajava\\HelloWorld.java");
BufferedInputStream dis = new BufferedInputStream(fis);
int c = 0;
System.out.println(dis.read());
System.out.println(dis.read());
dis.mark(100); //将标记直接标到100,从第100个字符开始读取
for(int i=0;i<=10&&(c=dis.read())!=-1;i++){
System.out.print((char)c+" ");
}
System.out.println();
dis.reset(); //重新回到刚才标记的那个点
for(int i=0;i<=10&&(c=dis.read())!=-1;i++){
System.out.print((char)c+" ");
}
dis.close();
}catch(IOException ex){
System.out.println("文件没有找到");
System.exit(-1);
}
}
}
正是有这些处理流,使得这些
高亮的方法得以使用。
import java.io.*;
public class TestBufferStream2{
public static void main(String[] args){
try{
BufferedWriter bw = new BufferedWriter(new FileWriter("F:\\javajava\\game1\\write1.java"));
BufferedReader br = new BufferedReader(new FileReader("F:\\javajava\\superself.java"));
String s = null;
for(int i=0;i<=100;i++){
s=String.valueOf(Math.random()); //将随机数转换为字符串
bw.write(s);
bw.newLine(); //缓冲流提供的方法,添加一行
}
//bw.flush(); //刷新流,将东西倒光
while((s=br.readLine())!=null){
System.out.println(s);
}
bw.close();
br.close();
}catch(IOException ex){
ex.printStackTrace();
}
}
}
转换流
- InputStreamReader 和 OutputStreamWriter用与字节数到字符数据之间的转换
- InputStreamReader 需要和 InputStream "套接"。
- OutputStreamWriter 需要和 OutputStream "套接"。
- 转换流在构造时可以指定其编码集合,例如:InputStream isr = new InputStreamReader(System.in,"ISO8859_1");
import java.io.*;
public class TestTransForm1{
public static void main(String[] args){
try{
OutputStreamWriter osw = new OutputStreamWriter( //这就是转换流
new FileOutputStream("F:\\javajava\\game1\\transwriter.txt"));
System.out.println(osw.getEncoding());
osw.close();
osw = new OutputStreamWriter(
new FileOutputStream("F:\\javajava\\game1\\transwriter.txt",true),
"ISO8859_1"); //这个地方的"true",使得在文件末端写入数据,而不会覆盖!!
//ISO8859_1的意思是国际编码
osw.write("sdasasdasdadas");
System.out.println(osw.getEncoding());
osw.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
import java.io.*;
public class TestTransForm2{
public static void main(String [] args){
InputStreamReader isr = new InputStreamReader(System.in); //得到键盘的输入
BufferedReader br = new BufferedReader(isr); //处理流使得可以用下面 直接读取一行的方法
String s =null;
try{
s = br.readLine();
while(s!=null){
if(s.equalsIgnoreCase("exit")) break; //忽略大小写
System.out.println(s.toUpperCase());
s=br.readLine();
}
br.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
数据流
- DataInputStream 和 DataOutputStream分别继承自InputStream 和 OutputStream ,它属于流,需要分别“套接”在InputStream和OutputStream类型的节点流上
- DataInputStream 和 OutputStream提供了可以存取与机器无关的java原始类型数据(如:int,double等)的方法。
//高亮的都是Data..Stream带来的方法
//此程序先在节点流ByreArray...Stream套上DataOutputStream数据流,后写进去东西,再套用DataInputStream读出来
import java.io.*;
public class TestDataStream{
public static void main(String[] args){
ByteArrayOutputStream baos =
new ByteArrayOutputStream();
DataOutputStream dos =
new DataOutputStream(baos);
try{
dos.writeDouble(Math.random());
dos.writeBoolean(true);
ByteArrayInputStream bais =
new ByteArrayInputStream(baos.toByteArray());
System.out.println(bais.available());
DataInputStream dis = new DataInputStream(bais);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
dos.close(); dis.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
Print 流:
你看就叫Print,所以这里就只有输出流,没有输入流了。(用于输出很舒服)
- PrintWriter和PrintStream都属于输出流,分别针对字符和字节。
- PrintWriter和PrintStream提供了重载的print
- Println方法用于多种数据类型的输出
- PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息。
- PrintWriter和PrintStream有自动flush功能。
一些方法:
- PrintWriter(Writer out)
- PrintWriter(Writer out,boolean autoFlush)
- PrintWriter(OutputStream out)
- PrintWriter(OutputStream out,boolean autoFulsh)
- PrintStream(OutputStream out)
- PrintStream(OutputStream out,boolean autoFlush)
import java.io.*;
public class TestPrintStream1{
public static void main(String[] args){
PrintStream ps =null;
try{
FileOutputStream fos =
new FileOutputStream("F:\\javajava\\game1\\log.dat");
ps = new PrintStream(fos);
}catch(IOException e){
e.printStackTrace();
}
if(ps !=null){
System.setOut(ps); //把输出的地方从命令行变到了这个ps文件里面
}
int ln = 0;
for(char c =0;c<=60000;c++){
System.out.print(c+" ");
if(ln++ >=100){
System.out.println();
ln=0;
}
}
}
}
//读取文件并且打印出来
import java.io.*;
public class TestPrintStream2{
public static void main(String[]args){
String filename = args[0];
if(filename!=null){
printList(filename,System.out);
}
}
public static void printList(String f,PrintStream fs){ //这是一个方法
try{
BufferedReader br =
new BufferedReader(new FileReader(f));
String s =null;
while((s=br.readLine())!=null){
fs.println(s);
}
br.close();
}catch(IOException e){
fs.println("无法读取文件");
}
}
}
//log记录修改程序的日志
import java.util.*;
import java.io.*;
public class TestPrintStream3{
public static void main(String[] args){
String s =null;
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in));
try{
FileWriter fw = new FileWriter("F:\\javajava\\game1\\logdfile.log",true);
PrintWriter log = new PrintWriter(fw);
while((s=br.readLine())!=null){
if(s.equalsIgnoreCase("exit")) break;
System.out.println(s.toUpperCase());
log.println("----");
log.println(s.toUpperCase());
log.flush();
}
log.println("==="+new Date()+"===");
log.flush();
log.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
Object 流:
直接将Object写入或读出
import java.io.*;
public class TestObjectIO{
public static void main(String[] args){
T t =new T();
t.k = 8;
FileOutputStream fos = new FileOutputStream("F:\\javajava\\game1\\testobject.dat");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(t);
oos.flush();
oos.close();
FileInputStream fis = new FileInputStream("F:\\javajava\\game1\\testobject.dat");
ObjectInputStream ois = new ObjectInputStream(fis);
T tReaded =(T)ois.readObject();
System.out.println(tReaded.i+" "+tReaded.j+" "+tReaded.d+" "+tReaded.k);
}
}
class T implements Serializable{ //要想把一个类的对象化实现序列化一个字节流(写到硬盘或者网络上)必须实现这个接口
int i=0; //Serializable:可以被序列化的
int j =9;
double d =2.3;
int k =0; //如果是这样写的 transient(透明的意思) int k =15; 那么主函数将会打印出k为0
//也就是说transient 在序列化是不予考虑, 不会写入硬盘
}
勤于复习,使用,自然掌握。