IO流知识点总结——博客园:师妹开讲啦
课本知识点总结--博客园:师妹开讲啦
Java中的流是有序的数据序列,是传递数据信息的载体,也是程序中的数据所经历的路径
流根据方向可分为输入流和输出流:输入流是将数据源传递给程序,输出流是将数据从程序传递到目的地,如内存、文件、网络等。
根据流的角色可分为节点流(FileInputStream、FileOutputStream、FileReader、FileWriter)和处理流
根据组成流的不同,可以将其分为字节流(FileInputStream、FileOutputStream、BufferedInoutStream、BufferedOutputStream、ObjectInputStream、ObjectOutputStream)和字符流(FileReader、FileWriter、BufferedReader、BufferedWriter、InputStreamReader、OutputStreamWriter):字节流是由字节组成的,主要用于处理二进制数据(图片、音频文件),字符流是由字符组成,主要用于处理文本的数据。
java.io.File类不属于Java流系统,但它是文件流进行文件操作的辅助类。
File类的对象是一个“文件或目录”的抽象代表。File类的对象并不打开文件或目录,而是指定要操作的文件或目录。File类的对象一旦创建,就不能再更改,即它代表的抽象路径是不能改变的。
String list[]=file.list();//只返回文件名,没有路径信息
File listFile[]=file.listFiles();//不但返回文件名称还含有路径信息
mkdir()——返回值类型:boolean,只能创建单层目录,不能含有子目录,即只能在已存在的目录中创建目录
mkdirs()——返回值类型:boolean,可以创建多级目录,可以含有子目录,即可以在不存在的目录中创建文件夹
例1:给定一个目录,列出此目录下的所有文件和目录
public class ListFile{
public static void main(String[] args){
System.out.println("请输入路径:");
Scanner scan=new Scanner(System.in);
String path=scan.next();
File file=new File(path);
fileList(file);
public static void fileList(File file){
if(file.isFile()){
System.out.println(file.getName());
}else{
System.out.println("\t"+file.getPath()+"是目录");
File fileName[]=file.listFiles();
for(int i=0;i<fileName.length;i++){
fileList(fileName[i]);
}
}
}
}
向文件中写入时,若指定文件在操作前不存在,则操作之后系统会自动创建该文件,但目标文件存在的目录必须存在,否则抛出FileNotFoundException异常
String s="Java学习手记";
byte[] b=s.getBytes();
char[] c=s.toCharArray();
字节流是对文件本身直接进行操作,不需要通过缓冲区,而字符流则要通过缓冲流来操作文件,即使用字节流时,就算没有执行close()方法关闭字节流的操作,还是可以向文件输出内容的,但在字符流中,若不执行close()方法,就无法像文件写入内容,因为程序在执行过程中引入了缓冲区机制,即写操作先将内容放入缓冲区,若写操作完毕后,不将缓冲区内容刷新到文件,文件将为空,但可以使用flush()强制清除内容。执行close()方法时默认执行flush()方法
转换流:BufferedRead——readLine()一次读取一行,BufferedWriter——newLine()写入一个行分隔符
内存操作流:ByteArrayInputStream、ByteArrayOutputStream
ByteArrayInputStream将数据写入内存中,ByteArrayInputStream类的实例化对象和执行read()方法都不需要处理异常,但调用close()方法需要处理异常,可调用的close()是没有任何操作的一个空方法,在关闭字节数组输入流后仍可被调用,而不会产生任何IOException
内存操作流一般用于处理临时信息,因为临时信息不需要保存,使用后就可以删除
PrintStream类是FilterOutputStream的子类
例2:使用Scanner从文件中获取数据
public class ScannerDemo{
public static void main(String[] args){
File file=new File("E:/JavaDemo/10/poetry.txt");
if(!(file.exists())){
System.out.println("文件不存在");
System.exit(0);
}
FileInputStream fis=null;
Scanner scan=null;
try{
fis=new FileInputStream(file);
scan=new Scanner(fis);
}catch(Exception e){
e.printStackTreace();
}
StringBuffer sbu=new StringBuffer();
while(scan.hasNext()){
sbu.append(scan.next()).append("\n");
}
System.out.print(sbu);
}
}
随机(任意)访问文件类:RandomAccessFile
java.io.RandomAccessFile类不属于流,是Object的子类,但融合了流类InputStream和OutputStream的功能,既提供与InputStream类似的read()方法,又提供OutputStream类似的write()方法,还提供更高级的直接读写各种基本数据类型数据的读写方法,例如readInt()、writeInt(),该类还可以从文件的任意位置开始访问文件,但要求文件中的各个数据保存的长度必须相等
顺序输入流(合并流):SequenceInputStream
SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,在关闭输入流时,可只关闭顺序输入流,因为顺序输入流的close()方法将依次关闭被串联的输入流,但不会关闭输出流
ZipEntry类的对象是用来表示ZIP文件条目,代表ZIP文件内的进入点(entry)
例3:ZipOutputStream类压缩文件夹
public class ZipOutputStreamDemo{
public static void main(String[] args){
File f1=new File("zip");
File f2=new File("zipjava.zip");
FileInputStream fis=null;
FileOutputStream fout=null;
ZipOutputStream zout=null;
File fileName[]=null;
byte b[]=new byte[1024];
int temp=0;
try{
fout=new FileOutputStream(f2);
zout=new ZipOutputStream(fout);
zout.setComment("Use ZipOutputStream compression zip Directory");//设置注释
if(f1.isDirectory()){
fileName=f1.listFiles();
for(int i=0;i<fileName.length;i++){
fis=new FileInputStream(fileName[i]);
zout.putNextEntry(new ZipEntry(fileName[i].toString()));
System.out.println("正在压缩"+fileName[i]+".......");
while((temp=fis.read(b))!=-1){
zout.write(b,0,temp);
}
System.out.println("压缩"+fileName[i]+"完成");
}
}
zout.close();
fout.close();
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
例4:ZipFile类解压缩ZIP文件
public class ZipFileDemo{
public static void main(String[] args){
File file=new File("zipjava.txt");
File zipFile=new File("java.zip");
InputStream in=null;
FileOutputStream fout=null;
ZipEntry entry=null;
ZipFile zip=null;
byte b[]=new byte[1024];
int temp=0;
try{
zip=new ZipFile(zipFile);
entry=new ZipEntry("java.txt");
in=zip.getInputStream(entry);
fout=new FileOutputStream(file);
while((temp=in.read(b))!=-1){
fout.write(b,0,temp);
}
zip.close();
fout.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
对象序列化
序列化:对象存储,对象转换为字节 反序列化:字节转换为对象
对象的序列化的用途:1、把对象的字节序列永久的保存到硬盘上,通常存放在一个文件中 2、在网络上传送对象的字节序列
如需要某个对象能支持序列化机制,必须让它实现Serializable接口,该接口只是一个标记接口,实现该接口无需实现任何方法,仅仅表明该类的对象是可序列化的
对象被序列化时参与序列化的内容:属性、类名,不能序列化的内容:方法、类中的所有方法、static关键字和transient关键字修饰的属性
Serializable接口和Externalizable接口均可以完成对象的序列化和反序列化,被Serializable接口声明的类对象的内容都将被序列化,而Externalizable接口声明的类的对象可以选择需要序列化的内容。但一般使用Serializable接口实现序列化,因为该接口不需要实现任何方法,而Externalizable接口定义了readExternal()和writeExternal()方法,实现该接口的类必须实现这两个方法
视频知识点总结
创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件,而且该文件回被创建到指定目录下,如果该目录下已有同名文件,将被覆盖。
字节流如若不使用close()方法,结果仍可在文件中显示,字符流如若不使用close()方法则为空,可以使用flush()将缓冲去中缓存的内容推出,就可显示出内容。
FileWriter fw=new FileWriter(“demo.txt”,true);//传递一个true参数,代表不覆盖已有的文件,并在已有文件的末尾处进行数据续写。
记事本当中不能识别“\n”,要想换行使用“\r\n”
只要用到缓冲区,就要刷新(flush())
关闭缓冲区,就是在关闭缓冲区中的流对象
缓冲区中提供了一个跨平台的换行符(newLine())
缓冲区提供了一个一次读一行的方法readLine(),方便于对文本数据的获取,返回的时候只返回回车符之前的数据内容,并不返回回车符。当返回null时,表示读到文件末尾。
byte[] buf=new byte[fis.available()];//定义一个刚刚好的缓冲区,不用再循环了
(建议在文件小的前提下使用,如若过大还是使用数组的1024倍较合适)
11111111—提升到int型(11111111 11111111 11111111 11111111)仍是-1,只要在前面补0(-1&255)—255(00000000 00000000 00000000 11111111),既可以保留原字节数据不变,又可以避免-1的出现。
System.setIn()//重新分配“标准”输入流。 System.setOut()// 重新分配“标准”输出流。
相当于复制文件getParent()方法返回的是绝对路径中的父目录,若File f=new File(“a.txt”);getParent()则返回null
File f1=new File(“C:\\text.java”);File f2=new File(“D:\\hahah.java”);f.renameTo(f1);//true renameTo()方法类似于剪切
package practice;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
public class JavaFileList {
public static void main(String[] args) {
File dir=new File("f:/java");
List<File> list=new ArrayList<File>();
fileToList(dir, list);
File file=new File(dir,"javaList.txt");
writeToFile(list, file.toString());
}
public static void fileToList(File dir,List<File> list){
File[] files=dir.listFiles();
for(File file:files){
if(file.isDirectory()){
fileToList(file,list);
}else{
if(file.getName().endsWith(".java"))
list.add(file);
}
}
}
public static void writeToFile(List<File> list,String javaListFile){
BufferedWriter bufw=null;
try{
bufw=new BufferedWriter(new FileWriter(javaListFile));
for(File f:list){
String path=f.getAbsolutePath();
bufw.write(path);
bufw.newLine();
bufw.flush();
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(bufw!=null){
bufw.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
package practice;
//Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。
//属性列表中每个键及其对应值都是一个字符串。
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiesDemo {
public static void main(String[] args) throws IOException {
setAndGet();
method_1();
loadDemo();
}
public static void setAndGet(){
Properties prop=new Properties();
prop.setProperty("zhangsan", "30");
prop.setProperty("lisi", "39");
// String value=prop.getProperty("lisi");
//stringPropertyNames()返回此属性列表中的键集,其中该键及其对应值是字符串,
//如果在主属性列表中未找到同名的键,则还包括默认属性列表中不同的键。
Set<String> names=prop.stringPropertyNames();
for(String s:names){
System.out.println(s+":"+prop.getProperty(s));// 用指定的键在此属性列表中搜索属性
}
}
public static void method_1() throws IOException{
BufferedReader bufr=new BufferedReader(new FileReader("info.txt"));
String line=null;
Properties prop=new Properties();
while((line=bufr.readLine())!=null){
String[] arr=line.split("=");
prop.setProperty(arr[0],arr[1]);
}
bufr.close();
System.out.println(prop);
}
public static void loadDemo() throws IOException{
Properties prop=new Properties();
FileInputStream fis=new FileInputStream("info.txt");
prop.load(fis);//从输入流中读取属性列表(键和元素对)
prop.setProperty("wangwu", "39");//只改变内存的结果,不能改变文件本身
FileOutputStream fos=new FileOutputStream("info.txt");
prop.store(fos, "haha");// 以适合使用 load(InputStream) 方法加载到 Properties 表中的格式,
//将此 Properties 表中的属性列表(键和元素对)写入输出流。
//System.out.println(prop);
prop.list(System.out);//将属性列表输出到指定的输出流
fos.close();
fis.close();
}
}
package practice;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class RunCount {
public static void main(String[] args) throws IOException {
Properties prop=new Properties();
File file=new File("count.ini");
if(!file.exists()){
file.createNewFile();
}
FileInputStream fis=new FileInputStream(file);
prop.load(fis);
int count=0;
String value=prop.getProperty("time");
if(value!=null){
count=Integer.parseInt(value);
if(count>=5){
System.out.println("您好,使用次数已到,拿钱");
return;
}
}
count++;
prop.setProperty("time", count+"");
FileOutputStream fos=new FileOutputStream(file);
prop.store(fos, "");
}
}
将多个文件合并至一个文件中
package practice;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.Vector;
public class SequenceDemo{
public static void main(String[] args) throws IOException{
//Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引
//进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建
//Vector 后进行添加或移除项的操作。
Vector<FileInputStream> v=new Vector<FileInputStream>();
v.add(new FileInputStream("e:/1.txt"));//将指定元素添加到此向量的末尾
v.add(new FileInputStream("e:/2.txt"));
v.add(new FileInputStream("e:/3.txt"));
//实现 Enumeration 接口的对象,它生成一系列元素,一次生成一个。
//连续调用 nextElement 方法将返回一系列的连续元素。
Enumeration<FileInputStream> en=v.elements();// 返回此向量的组件的枚举
SequenceInputStream sis=new SequenceInputStream(en);
FileOutputStream fos=new FileOutputStream("e:/4.txt");
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
}
切割、合并文件
package practice;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
public class SplitFile {
public static void main(String[] args) throws IOException{
// splitFile();
merge();
}
public static void merge() throws IOException{
ArrayList<FileInputStream> a1=new ArrayList<FileInputStream>();
for(int x=1;x<=5;x++){
a1.add(new FileInputStream("e:/"+x+".part"));
}
final Iterator<FileInputStream> it=a1.iterator();
Enumeration<FileInputStream> en=new Enumeration<FileInputStream>(){
public boolean hasMoreElements(){
return it.hasNext();
}
public FileInputStream nextElement(){
return it.next();
}
};
SequenceInputStream sis=new SequenceInputStream(en);
FileOutputStream fos=new FileOutputStream("e:/0.jpg");
byte[] buf=new byte[1024];
int len=0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}
fos.close();
sis.close();
}
public static void splitFile() throws IOException{
FileInputStream fis=new FileInputStream("吴亦凡.jpg");
FileOutputStream fos=null;
byte[] buf=new byte[1024*10];
int len=0;
int count=1;
while((len=fis.read(buf))!=-1){
fos=new FileOutputStream("e:/"+(count++)+".part" );
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
操作对象ObjectInputStream与ObjectOutputStream需要实现Serializable接口
(写入文件的信息看不懂)
静态变量不能实现序列化
非静态不想实现序列化则可在前加:transient//transient int age;
一般在实现对象流的时候,对象实体的文件以“.object”为后缀名
-----------管道流:PipedInputStream和PipedOutputStream与线程结合使用
RandomAccessFile该类不算是IO体系中的子类,而是直接继承自Object,但它是IO包中的成员,因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
该类只能操作文件,而且操作文件还有模式,只读r,读写rw等,而且该对象的构造函数要操作的文件不存在会自动创建。如果存在则不会覆盖。
如果模式为只读,不会创建文件,会去读取一个已存在的文件,如果该文件不存在则会出现异常。
一个中文两个字节
RandomAccessFile raf=new RandomAccessFile(“ran.txt”,”r”);//r:只读、rw:读写、
Seek()//设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取 或写入操作。(既可往前跳又可往后跳)
skipBytes()// 尝试跳过输入的 n 个字节以丢弃跳过的字节(只可往前跳)
DataInputStream和DataOutputSteam用于操作基本数据类型的数据的对象。
//写入文件的信息看不懂、读取时必须按写入的顺序读
“你好”的Gbk文件用utf-8解码结果是??
“你好”的Utf_8文件用gbk解码结果是三个别的文字
编码:字符串变成字节数组String-byte[];str.getBytes(charsetName)
解码:字节数组变成字符串byte[]-String:new String(byte[],charsetName);
Integet.toBinaryString(b)将数值b转换成二进制,若只想要后八位则b&255