- 掌握java.io保重类的继承关系
- 可以使用gFile类进行文件的操作
- 可以使用字节流或字符流擦欧总文件内容并区分出字节流与字符流
- 可以掌握内存操作输入输出流的使用
- 了解线程通信流----------管道流的作用
- 可以掌握System类对io的支持:System.out、System.err、System.in
- 可以使用打印流方便的打印输出内容,并可以使用java新特性 格式化输出
- 可以使用BufferedReadera类读取花冲去中的内容
- 了解java通的输入工具类Scanner类的使用
- 掌握数据操作流:DataInputStream和DataOutputstream类的使用
- 可以使用SequenceInputStream合并两个文件的内容
- 可以使用压缩流完成ZIP文件格式的压缩
- 了解回退流(PushbacckInputStream)类的作用
- 了解字符的主要彪马类型及乱码产生原因
- 可以掌握对象序列化的作用以及Serializable接口、Externalizable接口、transient关键字的使用
在整个Java.io包中最重要的就是5个类1个接口,5各类是指:File、OutputStream、InputStream、Writer、Reader;1个接口知的是Serializable。掌握了这些就掌握了io擦欧总的核心。
1):操作文件的类---File
整个IO中唯一一个表示与文件本身有关的类就是File类。
File f = new File("d:\\test.txt");//必须给出完整路径
f.createNewFile();//根据给定的路径创建新文件
Window系统中使用反斜杠表示目录的分隔符:“\”
Linux中使用正斜杠表示目录的分隔符:“/”
File.pathSeparator;//File类中提供的静态常量
File.separator;//File类中提供的静态常量
结果:
pathSeparator: ;
separator: \
对于创建文件的操作来说,最好的做法时使用以上的常量表示路径分隔符。这样代码就可以在任意操作系统中使用。
例如:开发程序时程序运行在window系统中,发布程序时程序部署在Linux或者其他的操作系统上,如果不使用File.separator,则程序运行时可能存在问题。
File f = new File("D:"+File.separator+"test.txt");//必须给出路径
if(f.exists())//判断文件是否存在
f.delete();//删除文件
===========================================================
File f = new File("D:"+File.separator+"test.txt");//必须给出路径
if(f.getParentFile().exists())//父路径不存在
f.mkdir();//创建文件夹
===========================================================
File f = new File("D:"+File.separator);
String str[] = f.list();//列出给定目录中的内容
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
结果:
eclipse
Java
MySQL
oracle
....
===========================================================
File f = new File("D:"+File.separator);
String str[] = f.listFiles();//列出给定目录中全部文件
for(int i=0;i<str.length;i++){
System.out.println(str[i]);
}
结果:
D:\eclipse
D:\Java
D:\MySQL
D:\oracle
....
===========================================================
File f = new File("D:"+File.separator);//路径
if(f.isDirectory()){ //判断是否是目录
System.out.println(f.getPath()+"路径是目录");
}else{
System.out.println(f.getPath()+"路径不是目录");
}
结果:
D:\路径是目录
列出指定目录的全部内容
package javaIO;
import java.awt.print.Printable;
import java.io.File;
/**
* 列出指定目录的全部内容
*
*/
public class FileDemo {
public static void main(String[] args) {
File my =new File("d:"+File.separator);//操作路径
print(my);
}
public static void print(File file){//用递归方法调用此方法
if(file!=null){ //增加一个检查机制
if(file.isDirectory()){ //判断是否是一个目录
File f[] = file.listFiles();//如果是目录,则列出全部的内容
if(f!=null){ //判断是否列出有文件夹
for (int i = 0; i < f.length; i++) {
System.out.println(f[i]);//显示文件路径
print(f[i]); //继续列出类容
}
}else {
System.out.println(file); //如果不是目录,则直接打印路径信息。
}
}
}
}
}
部分结果:
d:\Youdao\YoudaoNote\theme\default\public\Icon_SRC_Edit.png
d:\Youdao\YoudaoNote\theme\default\public\Icon_TitleBar_Safe.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_comment.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_comment_show.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_edit.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_export.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_generate.png
d:\Youdao\YoudaoNote\theme\default\public\Icon_toolbar_hideFrame.png
d:\Youdao\YoudaoNote\theme\default\public\Icon_toolbar_insert.png
d:\Youdao\YoudaoNote\theme\default\public\icon_toolbar_more.png
以上程序使用递归的叼哦那形式,不断的判断传进来的路径是后是目录,如果式目录,则继续列出子文件夹,如果不是,则直接打印路径名称。
2):RandomAccessFile类
File类只针对文件本身进行操作,而如果想要对文件内容进行操作,则可以使用RandomAccessFile类,此类属于随机读取类,可以随机的读取一个我呢见中指定位置的数据。为了保证可以进行随机读取,写入的名字只能是是8字节,数字是固定的4字节。
3):字节流与字符流的基本操作
字节流:InputStream、OutputStream
字符流:Reader、Writer
在java中IO操作也是有相应的步骤的,一文件呢的厝安佐为例,主要的操作流程如下:
- 使用File类打开一个文件夹
- 通过字节流的子类或字符流的子类指定输出的位置
- 进行读/写操作。
- 关闭输入/输出。
字节流输出流:OutputSteam
此类定义如下:
public abstract class OutputStream
extends Object
implements Closeable,Flushable
此类为抽象类,如果想使用此类的化,可以通过子类FileOutputStream实例化对象。
public FileOutputStream(File file) throws FileNotFoundException
package javaIO;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class OutputStreamDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
OutputStream out = new FileOutputStream(f,true);//在文件末尾追加内容
String str = "\r\n Hello World";//换行
byte b[]= str.getBytes(); //只能输出byte数组,将String转换成数组
/*out.write(b);*/ //将内容输出
for (int i = 0; i < b.length; i++) {
out.write(b[i]);
}
out.close();
}
}
字节输入流:InputStream
public abstract class InputStream
extends Object
implements Closeable
public FileIntputStream(File file) throws FileNotFoundException
package javaIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class InputStreamDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
InputStream input = new FileInputStream(f);
//byte b[]= new byte[1024]; //定义一个数组,长度为1024字节,会出现空间浪费
byte b[] = new byte[(int)f.length()];//所有内容读到这个数组中,数组大小由文件决定,但文件内容不能过大。
/*out.write(b);*/ //将内容输出到数组b中,如果内容超过1024,则丢失
/*int len = input.read(b);*/
int temp=0;
int len = 0;
while((temp = input.read())!=-1){
//将每次读的值都赋给temp,入股temp变量不是-1,就说面文件没有读完
b[len]=(byte)temp;
len++;
}
input.close();
System.out.println("读入数据的长度是:"+len);
System.out.println("内容为:"+new String(b,0,len));//把读到b数组里的内容输出。
}
}
}
}
字符流:
字符输出流:FileWriter
public abstract class Writer
extends Object
implements Appendable,Closetable,Flushable
package javaIO;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class WriterDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
Writer out = new FileWriter(f,true);
String str = "\r\n Hello World";//换行
out.write(str);
out.close();
}
}
字符输入流:FileReader
public abstract class Reader
extends Object
implements Readable,Closeable
package javaIO;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class ReaderDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
Reader input = new FileReader(f);
char ch[] = new char[1024];
/*int len = input.read(ch);*/
int temp =0;
int len = 0;
while((temp= input.read())!=-1){
ch[len]=(char)temp;
len++;
}
System.out.println(new String(ch,0,len));
}
}
字节流与字符流的区别
使用字节流,如果不直接关闭输出流,可以看到文件中依然有内容输出。如果字符流没有关闭输出流,文件中没有内容输出,索命缓冲区中的内容是无法输出的,但是如果使用out.flush()方法,强制性清空缓冲区中的内容,即使没有关闭输出流,文件中也有内容输出。
所以得出结论,字符流使用了缓冲区,,而字节流没有使用缓冲区。
所有的文件在硬盘存储或者传输的时候都是以字节的方式进行的。包括图片等都是按字节的方式存储的。而字符只有在内存中才会形成,所以在开发中,字节流使用更广泛。
范例:文件的复制
package javaIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class Copy {
public static void main(String[] args) throws IOException {
File f1 = new File("d:"+File.separator+"text.txt");
File f2 = new File("d:"+File.separator+"demo.txt");
InputStream input = new FileInputStream(f1);//字节输入流
OutputStream out = new FileOutputStream(f2);//字节输出流
int temp = 0 ;
//边读边写
while((temp=input.read())!=-1){
out.write(temp);
}
System.out.println("复制完成");
}
}
4):转换流------OutputStreamWriter类和InputStreamReader类
OutputStreamWriter是Writer的子类:将一个字符流转换成字节流
InputStreamReader是Reader的子类:将一个字节流转换成字符流
package javaIO;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
public class OutputStreamWriterDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
Writer out = new OutputStreamWriter(new FileOutputStream(f));
out.write("Hello World");
out.close();
}
}
package javaIO;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
public class InputStreamReaderDemo {
public static void main(String[] args) throws IOException {
File f = new File("d:"+File.separator+"text.txt");
Reader input = new InputStreamReader(new FileInputStream(f));
char c[] = new char[1024];
int len = input.read(c);
input.close();
System.out.println(new String(c,0,len));
}
}
5):内存操作流
字节内存流:ByteArrayInputStream(内存字节输入流)、ByteArrayOutputStream(内存字节输出流)
字符内存流:CharArrayInputStream(内存字符输入流)、CharArrayOutputStream(内存字符输出流)
package javaIO;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public class ByteArrayDemo {
public static void main(String[] args) {
String str = "HELLO WORLD";
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int temp = 0;
while((temp = bis.read())!=-1){
char c= (char)temp;
bos.write(Character.toLowerCase(c));
}
System.out.println(bos.toString());
}
}
结果:
hello world
6):管道流
作用:可以进行两个线程之间的通信,分为管道输入流PipedOutputStream,和管道输出流PipedInputStream
如果想使用管道流,就必须把输出流连在输入流上。
线程1--->PipedOutputStream --->PipedInputStream ----> 线程2
package javaIO.piped;
import java.io.IOException;
import java.io.PipedOutputStream;
public class Send implements Runnable {
private PipedOutputStream pos = null;
public PipedOutputStream getPos() {
return pos;
}
public Send() {
this.pos = new PipedOutputStream();
}
@Override
public void run() {
String str = "Helle World";
try {
this.pos.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
try {
this.pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package javaIO.piped;
import java.io.IOException;
import java.io.PipedInputStream;
public class Receive implements Runnable {
private PipedInputStream pis = null;
public Receive() {
this.pis = new PipedInputStream();
}
public PipedInputStream getPis() {
return pis;
}
@Override
public void run() {
byte b[] = new byte[1024];
int len=0;
try {
len = pis.read(b);
} catch (IOException e) {
e.printStackTrace();
}
try {
this.pis.close();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("接受的内容是:"+new String(b,0,len));
}
}
package javaIO.piped;
import java.io.IOException;
public class PipedDemo {
public static void main(String[] args) throws IOException {
Send s = new Send();
Receive r = new Receive();
s.getPos().connect(r.getPis());
new Thread(s).start();
new Thread(r).start();
}
}
结果:
接受的内容是:Helle World
7):打印流
PrintStream是OutputStream的子类。
把一个输出流的实例传递到打印流之后,可以更加方便的输出内容,也就是说,是打印六把输出流重新装饰了一下,就象送别人的礼物,需要把礼物包装一下以显得更加好看,所以,这样设计称为装饰设计模式。
package javaIO.print;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintDemo {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps =null;
ps = new PrintStream(new FileOutputStream(new File("d:"+File.separator+"text.txt")));//所有的输出都是向文件中打印
ps.print("hello ");
ps.print("world");
ps.print("1+1=2");
ps.close();
}
}
与使用OutputStream相比,明显方便多了。
使用打印流进行格式化
%s :表示内容为字符串
%d :表示内容为整数
%f :表示内容为小数
%c :表示内容为字符
package javaIO.print;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintDemo2 {
public static void main(String[] args) throws FileNotFoundException {
PrintStream ps = null;
ps = new PrintStream(new FileOutputStream(new File("d:"+File.separator+"text.txt")));//所有的输出都是向文件中打印
String name = "java";
int age = 30;
float score = 99.0f;
char sex = 'M';
ps.printf("姓名:%s;年龄:%d:成绩:%f;性别:%c",name ,age ,score,sex);
ps.close();
}
}
结果:
姓名:java;年龄:30:成绩:99.000000;性别:M
8):System类对IO的支持
9):BufferedReader类
从缓冲区之中读取内容,所有的输入字节数据都将放在缓冲区中,
在JDK1.5之前,提供了BufferedReader类方便用户进行输入流数据的读取操作,而从JDK1.5之后,卡时为例进一步简化输入流的操作,有提供了Scanner类。
10):Scanner类
此类不仅可以完成之前的输入数据操作,还可以方便的对输入数据进行验证。
Scanner scan = new Scanner(System.in);
if(scan.hasNextInt()){
int i = scan.nextInt();
}
if(scan.hasNext("^\\d{4}-\\d{2}-\\d{2}$")){//判断输入格式是否是字符串
String str = scan.next("^\\d{4}-\\d{2}-\\d{2}$");//接受日期格式的字符串
}
11):数据操作流----DataInputStream、DataOutputStream
12):合并流
合并流的主要功能是将两个文件的内容合并成一个文件,如果要实现合并流,则必须使用SequenceInputStream类
13):压缩流
可以将问价压缩成ZIP、JAR、GZIP
ZipOutputStream类
ZipFile类
ZipInputStream类
14):回退流
在java IO中所有的数据都是采用顺序的读取方式,即对于一个输入流来说,都是采用从头到尾顺序读取的。如果某个不需要的流被读出来,就需要处理掉。(PushbackInputStream、PushbackReader)
15)字符编码
- ISO8859-1 单字节编码,最多只能表示0~255的字符范围,主要用在英文上
- GBK/GB2312 中文的国际编码,专门用来表示汉字,是双字节编码,GBK 表示简体和繁体,GB2312 只代表简体
- unicode Java中就是使用此编码方式,也是最标准的一种编码,是使用十六进制表示的编码,但此编码不兼容ISO8859-1编码
- UTF: 可以用来表示所有的语言
在所有的项目开发中都要使用UTF-8编码,
16):对象序列化
将一个对象编程二进制的数据流的一种方式。可以方便的实现对象的传输或存储。
如果一个对象要实现序列化,就需要实现java.io.Serializable接口
如果要完成对象的传输,则需要依靠对象输出流(ObjectOutputStream)和对象输入流(ObjectInputStream)
程序--->ObjectOutputStream--->序列化对象--->ObjectInputStream--->程序
对象序列化和反序列化是的版本兼容性问题
在序列化操作中加入要给serialVersionUID的常量,可以通过此常量来验证版本的一致性
private static final long serialVersionUID = 1L;
serialVersionUID的具体类容由用户自己决定。
transient关键字,如果要给对象中国的某个属性不希望被序列化则可以使用该关键字进行声明。
总结:
- 在java中使用File类表示文件本身,可以直接使用过此类完成文件的各种操作,如创建,删除等
- RandomAccessFile可以从指定的位置处开始读取信息,但是要求文件中的各个数据的保存长度必须固定
- 输入输出流,,主要发呢为字节流和字符流,但是在传输中以字节流操作较多,字符流在操作的时候使用到缓冲去,而字节流没有使用到缓冲区。
- 字节流和字符流都是以抽象类的形式定义的,根据其使用的子类不同,输入输出的位置不同
- 在IO中,可以使用转换流 OutputStreamWriter和InputStreamReader来完成字符流和字节流的转换
- 使用ByteArrayInputStream和ByteArrayOutputStream可以对内存进行输入输出操作
- 在线程之间进行输入输出通信,主要使用PipedOutputStream和PiedInputStream类
- 在IO中输出时,最好使用打印流(PrintStream),这样可以方便的输出各种类型的数据
- System类提供了3个支持IO操作的常量:out、err、in(System.out:对应显示器的标准输出,可以使用setOut()方法,修改输出位置。System.err: 错误打印,一般此信息不希望给客户看,可以时setErr()方法修改输出位置,System.in :键盘输入,可以使用setIn()方法,修改输入位置。)
- BufferedReader可以直接从缓冲区中读取数据
- 使用Scanner类可以方便的进行输入流操作
- 对象序列化可以将内存中的对象转化为二进制数据,但对象躲在的类必须实现Serializable接口,一个类中的属性如果使用transient关键字声明的话,则此属性的内容将不会被序列化
- 对象的输入输出,主要使用ObjectOutputStream和ObjectInputStream两个类完成。