概述
Java I/O包含三个部分:
1.流式部分――IO的主体部分;
2.非流式部分――主要包含一些辅助流式部分的类,如:File类、RandomAccessFile类和FileDescriptor等类;
3.其他类--文件读取部分的与安全相关的类,如:SerializablePermission类,以及与本地操作系统相关的文件系统的类,如:FileSystem类和Win32FileSystem类和WinNTFileSystem类。
主要的类如下:
1. File(文件特征与管理):用于文件或者目录的描述信息,例如生成新目录,修改文件名,删除文件,判断文件所在路径等。
2. InputStream(二进制格式操作):抽象类,基于字节的输入操作,是所有输入流的父类。定义了所有输入流都具有的共同特征。
3. OutputStream(二进制格式操作):抽象类。基于字节的输出操作。是所有输出流的父类。定义了所有输出流都具有的共同特征。
4.Reader(文件格式操作):抽象类,基于字符的输入操作。
5. Writer(文件格式操作):抽象类,基于字符的输出操作。
6. RandomAccessFile(随机文件操作):一个独立的类,直接继承至Object.它的功能丰富,可以从文件的任意位置进行存取(输入输出)操作。
一、File
一个用来对文件、文件夹(目录)创建、删除、遍历等操作的类
public class BaseTest { public static void main(String[] args) { //==================File 四个静态属性================== //字符串形式的名称分隔符win是\ linux是/ String separator = File.separator; //字符形式的名称分隔符win是\ linux是/ char separatorChar = File.separatorChar; //字符串形式的路径分隔符win是; linux是: String pathSeparator = File.pathSeparator; //字符形式的路径分隔符win是; linux是: char pathSeparatorChar = File.pathSeparatorChar; //=================File 四个构造方法======================= File file = new File("D"+ File.pathSeparator +File.separator+"jks"); File file1 = new File(file,"test.txt"); File file2 = new File("D:","jsk"); //================file 常用成员方法======================= //创建文件 boolean newFile = file.createNewFile(); //创建文件夹(mkdirs递归创建) file.mkdir(); file.mkdirs(); boolean exists = file.exists(); //删除 file.delete(); //目录递归遍历 readFile(file); } public static void readFile(File file){ File[] files = file.listFiles(); for (int i = 0; i < files.length; i++) { if(files[i].isDirectory()){ readFile(files[i]); }else { System.out.println(files[i].getPath()); } } } }
pathSeparator、separator区别:
File.pathSeparator指的是分隔连续多个路径字符串的分隔符,例如:
java -cp test.jar;abc.jar HelloWorld
就是指“;”
File.separator才是用来分隔同一个路径字符串中的目录的,例如:
C:\Program Files\Common Files
就是指“\”
二、io
1、概述
java中的数据是以流的方式传递,也就是二进制方式传递,有字节和字符流;分为输出输入流两种,出入(写读)都是相对内存而言的,即输出指的是吧数据从内存写到磁盘,输入指的是把数据从磁盘读入内存
2、流体系
- 使用字节流好还是字符流好?
所有的文件在硬盘或在传输时都是以字节的方式进行的,包括图片等都是按字节的方式存储的,而字符是只有在内存中才会形成,所以在开发中,字节流使用较为广泛。 - 字节流是最基本的,所有的InputStream和OutputStream的子类都是,主要用在处理二进制数据,它是按字节来处理的。但实际中很多的数据是文本,又提出了字符流的概念,它是按虚拟机的encode来处理,也就是要进行字符集的转化。这两个之间通过 InputStreamReader,OutputStreamWriter来关联,实际上是通过byte[]和String来关联。 在实际开发中出现的汉字问题实际上都是在字符流和字节流之间转化不统一而造成的。在从字节流转化为字符流时,实际上就是byte[]转化为String时,public String(byte bytes[], String charsetName) 有一个关键的参数字符集编码,通常我们都省略了,那系统就用操作系统的lang。而在字符流转化为字节流时,实际上是String转化为byte[]时,byte[] String.getBytes(String charsetName)也是一样的道理。至于java.io中还出现了许多其他的流,按主要是为了提高性能和使用方便,如BufferedInputStream,PipedInputStream等。
- 实际字节流和字符流区别处理代码和以上区别,还有字符流再操作文件的时候加入了缓存区
代码区分
public static void main(String[] args) throws IOException { File file= new File("d:"+File.separator+"test.txt"); String str = "hello world"; //=====================字节流使用===================== FileOutputStream outputStream = new FileOutputStream(file); outputStream.write(str.getBytes());//字节流只能操作字节,将数据从内存输出(写入)磁盘 outputStream.close(); //=====================字符流使用===================== FileWriter writer = new FileWriter(file); writer.write(str);//字符流直接对字符操作 将数据从内存输出(写入)磁盘 /**关闭之后才会将数据写入,没有这句文件没有内容,因为字符流内容还在缓冲区, * 只有调用close会强制刷新缓冲区数据进行输出,如果想在不关闭时也可以将 * 字符流的内容全部输出,则可以使用Writer类中的flush()方法完成*/ writer.close(); }
三、字节流
字节流的两个顶层inputStream、 outputStream 都是抽象类,不能直接new,由其子类实现各种文件输出输入
1、字节输入流FileInPutStream
2、字节输出流FileOutPutStream
3、使用字节流对文件复制
四、字符流
字符流的两个顶层父类Reader和Writer都是抽象类,不能直接new
1、字符输入流
2、字符输出流
备注:flush()和close()区别
flush()将缓冲区的数据刷新到目的地,刷新后流还可以继续使用
close()关闭资源,但在关闭前会将缓冲区的数据先刷先到目的地,然后关闭,关闭之后不可使用,如果写入数据过多,一定要一边写一边刷新 最后一次可以不用刷新,由close完成刷新并关闭
只有writer的子类才使用flush()
3、字符流实现文件的复制
五、转换流
1、字符转字节流类OutPutStreamWriter
OutputStreamWriter(Outputstream in)//给一个字节输出流的子类 FileOutputStream
OutputStreamWriter(Outputstream in ,charset s)//给一个字节输出流的子类,并且指定编码集 如果不给出 默认是gbk
2、字节转字符流类InputStreamReader
InputStreamReader(inputstream out)//给一个字节输入流子类 如FileInputStream
InputStreamReader(inputstream out ,charset s)//给一个字节输入流子类,并且指定编码集 如果不给出 默认是gbk
总结
六、缓冲流
缓冲流是为了提高java中io流的传输效率,有字节缓冲流 字符缓冲流,字节缓冲流本身没有传输流的能力,而是依靠一起流,对其提高效率,
1、字节输出缓冲流BufferedOutputStream
2、字节输入缓冲流BufferedInputStream
3、字符输出缓冲流BufferedReader
4、字符输入缓冲流BufferedWriter
5、字符缓冲流复制文件
七、对象流(序列化流)
如果将一个对象写入到本地文件中,被称为对象的序列化
如果将一个本地文本中的对象读取出来,被称为对象反序列化
注意:
1.要实现类的对象的序列化,首先本来要实现implements Serializable
2.一个对象流只能操作一个对象,如果试图采用一个对象流操作多个对象的话,会出现EOFException【文件意外达到了文件末尾】。如果向将多个对象序列化到本地,可以借助于集合,【思路:将多个对象添加到集合中,将集合的对象写入到本地文件中,再次读出来,获取到的仍然是集合对象,遍历集合】
3.对象序列化和反序列化的时候需要注意,序列化的时候有一个
private static final long serialVersionUID = 1L;
其中serialVersionUID的值是一个任意的整数,序列化和反序列化的时候这个数必须一致,否则将不能反序列化。会报错:
java.io.InvalidClassException: demo_0806.Student; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 2
八、内存流
向内存写数据
ByteArrayInputStream bis = new ByteArrayInputStream(t.getBytes());
读取内存里面的数据
ByteArrayOutputStream bos = new ByteArrayOutputStream();
案列:
String t = "大家好!";
//通过ByteArrayInputStream的构造方法向内存中写入数据
ByteArrayInputStream bis = new ByteArrayInputStream(t.getBytes());
//创建读内存的流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int temp=0;
while((temp=bis.read())!=-1){//注意这里是bis不是bos
char c=(char)temp;
bos.write(Character.toUpperCase(c));// toUpperCase(c)转成大写
}
System.out.print(bos.toString());
bis.close();
bos.close();
九、打印流printStream
平时我们在控制台打印输出,是调用 print 方法和 println 方法完成的,这两个方法都来自于java.io.PrintStream 类,该类能够方便地打印各种数据类型的值,是一种便捷的输出方式。
public static void main(String[] args) throws FileNotFoundException {
//系统默认流向是控制台
System.out.println("hello");
PrintStream printStream = new PrintStream("d:"+File.separator+"test.txt");
//改变默认流向输出
System.setOut(printStream);
System.out.println("hello ...");
}
十、使用总结
1、首先决定要操作的是字符还是字节
- 字节选择FileInputStream和FileOutPutStream
- 字符选择FileWriter和FileReader
- 一般视频 音频 图片用字节 文本用字符
2、其次决定要不要转字符
- InputStramReader和OutPutStreamWriter
3、然后决定用不用转换字符提高速率
- 提高字节输出输入BufferedInputStream和BufferedOutPutStream
- 提高字符输出输入BufferReader BufferWriter
4、操作对象使用ObjectInputStream和ObjectOutputStream