概述
有的流按照字节的方式读取数据,一次读取一个字节byte,等同于一次读取8个二进制,万能的,什么文件都能读。比如
文件file1.txt,采用字节流是这样读的
a中国ba张三ddd
第一次读‘a’(虽然“a”在windows中占用一个字节)
第二次读‘中’的一半(虽然‘中’在windows中占用两个字节)
有的流是按照字符的方式读取数据,一次读一个字符,为了方便读取普通文本,这能读取普通文本,连word文档都读不了,凡是能用记事本打开编辑的都属于文本文件,比如:
文件file1.txt,采用字符流是这样读的
a中国ba张三ddd
第一次读‘a’(虽然“a”在windows中占用一个字节)
第二次读‘中’(虽然‘中’在windows中占用两个字节)
“a”在windows中占用一个字节,在java中占用两个字节
流的四大家族
java.io.InputStream 字节输入流
java.io.OutputStream 字节输出流
java.io.Reader 字符输入流
java.io.Writer 字符输出流
以Stream结尾的是字节流,以Reader/Writer结尾的是字符流(看结尾,别看前面)
四大家族都是抽象类
用完流要关,用输出流完的flush刷新,清空管道,如果没有flush,可能会丢失数据
字节流
FileInputStream
从硬盘往内存上读
import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStream1 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\javaProject-idea\\111.txt");
//int a=fis.read();//返回值是读取到的字节,这里是a,返回的是ASCII码97,读一个字节,调一次读一次,返回-1就是没内容了
//空格也是一个字符,ASCII码是32
int a=0;
while((a=fis.read())!=-1){
System.out.println(a);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
循环如果这样写,它就跳着走,因为判断走一次,判断成功还要再走一次,输出的就是跳着的结果
while((fis.read())!=-1){
int a=fis.read();
System.out.println(a);
}
上面这个程序,内存与硬盘交互太频繁,效率太低,就是一个字节一个字节的拿,想用个数组把硬盘文件里的数据装起来一次交互
idea默认的当前路径是工程project的根目录
这里的根目录就是C:\Users\Administrator\IdeaProjects\diyige
/*
数组读,一次读多个字节
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test02 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\javaProject-idea\\112.txt");
//开始读,采用byte数组,一次读多个字节,最多读取数组.length字节
byte[] bytes=new byte[4];
//这个方法返回的是读取的字节数量(不是字节本身)
int count =fis.read(bytes);//第一次读取4个字节
System.out.println(count);
System.out.println(new String(bytes));//将数组全部转化成字符串,输出的是abcd
System.out.println(new String(bytes,0,count));//读几个转几个
count=fis.read(bytes);//第二次只读取了2个字节
System.out.println(count);
System.out.println(new String(bytes,0,count));//输出的是efcd
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
上面个没用循环
FileInputStream最终版
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Text03 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\javaProject-idea\\112.txt");
byte[]bytes=new byte[4];
int count=0;
while ((count=fis.read(bytes))!=-1){//读一次转一次
System.out.println(new String(bytes,0,count));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
常用方法
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Test04 {
public static void main(String[] args) {
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\javaProject-idea\\112.txt");
int readbytes=fis.available();//还有多少个字节没读
byte[]bytes=new byte[readbytes];//可以直接new个这么长的字节,不需要循环了,数组不能太大,不适合大文件
//skip跳过几个字节
fis.skip(2);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
FileOutputStream
从内存往硬盘上写
写完之后要刷新.flush
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class T1 {
public static void main(String[] args) {
FileOutputStream fos=null;
try {
fos=new FileOutputStream("D:\\javaProject-idea\\112.txt",true);//文件不存在会新建文件
//开始写
byte []bytes={121,111,122,99,100};
fos.write(bytes);
fos.write(bytes,0,2);//以上两种方法是将原文件清空再写
//以追加的方式在末尾写入,不会清空,在构造方法上加上第二个参数,true
String s="我是一个中国人";
byte[] bytes1=s.getBytes();
fos.write(bytes1);
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件复制,什么文件都可以
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Copy1 {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis=new FileInputStream("D:\\javaProject-idea\\111.txt");
fos=new FileOutputStream("D:\\javaProject-idea\\113.txt");
//new byte[1024*1024]1Mb,1024byte是1kb
byte [] bytes=new byte[4];
int count =0;
while ((count=fis.read(bytes))!=-1){
fos.write(bytes,0,count);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
字符流
字节流是byte数组,字符流就是char数组了
只能读取文本文档
FileReader
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
public class Freader {
public static void main(String[] args) {
FileReader reader=null;
try {
reader =new FileReader("D:\\javaProject-idea\\112.txt");
char [] chars=new char[2];
int count =0;
while ((count=reader.read(chars))!=-1){
System.out.print(new String(chars,0,count));//字符转化成字符串
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
FileWriter
import java.io.FileWriter;
import java.io.IOException;
public class Writer {
public static void main(String[] args) {
FileWriter fw=null;
try {
fw=new FileWriter("D:\\javaProject-idea\\111.txt",true);
char []chars={'我','是','a'};
fw.write(chars);
fw.write("\n");//换行
String s="中国人";
fw.write(s);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
缓冲字符流
BufferedReader:
带有缓冲区的字符输入流。
使用这个流的时候不需要自己定义数组。自带缓冲
当一个流的构造方法中需要一个流的时候,传进来的叫做节点流,外面的叫做包装流,也叫处理流,关流的时候,把外层的关掉就行,因为调外层的close方法时,底层也调了里面流的close
有个方法读一行
port java.io.BufferedReader;
import java.io.FileReader;
public class BufferReader1 {
public static void main(String[] args) throws Exception {
FileReader fr=new FileReader("D:\\javaProject-idea\\112.txt");
BufferedReader br=new BufferedReader(fr);
//读一行,但不带换行符
String s=null;
while ((s=br.readLine())!=null){
System.out.println(s);
}
br.close();
}
}
构造方法只能传一个reader,字符流,不能传字节流
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
public class Zhuanhuanliu {
public static void main(String[] args) throws Exception {
//字节流
FileInputStream fis=new FileInputStream("D:\\javaProject-idea\\111.txt");
//转换流,fis是节点流,ir是包装流
InputStreamReader ir=new InputStreamReader(fis);
//处理流,ir是节点流,bf是包装流
BufferedReader bf=new BufferedReader(ir);//这里只能传字符流,以上通过字节流转换成字符流
String line=null;
while ((line=bf.readLine())!=null){
System.out.println(line);
}
bf.close();
}
}
BufferedWriter
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class Bufferwrite {
public static void main(String[] args) throws IOException {
BufferedWriter bw=new BufferedWriter(new FileWriter("D:\\javaProject-idea\\111.txt",true));
bw.write("niahaoa");
bw.flush();
bw.close();
}
}
DataOutStream连同数据类型写进文件中,记事本打不开,必须用DataInStream读,读的顺序要跟写进去的一样
标准输出流
默认输出到控制台,可以改方向
import java.io.FileOutputStream;
import java.io.PrintStream;
public class PrintStream1 {
public static void main(String[] args) throws Exception {
System.out.println("ssss");
PrintStream PS=System.out;
//返回的是一个PrintStream
PS.println("sss");
//改变输出方向,不往控制台输出,参数是一个PrintStream,在里面的参数是文件位置
System.setOut(new PrintStream(new FileOutputStream("D:\\javaProject-idea\\112.txt",true)));
System.out.println("你是我的小苹果");
System.out.println("ssadasdasd");
}
}
日志工具类
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Rizhi {
public static void log(String msg){
try {
//指向一个日志文件
System.setOut(new PrintStream(new FileOutputStream("log.txt",true)));
//获取当前日期,并初始化
Date nowTime=new Date();
System.out.println(nowTime);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String strTime=sdf.format(nowTime);
System.out.println(strTime+": "+msg);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
public class Te {
public static void main(String[] args) {
Rizhi.log("asdasdasdasdasd");
}
}
File类
File和四大家族没关系
File是文件和目录路径的抽象表现形式
D:\javaProject-idea是一个File
D:\javaProject-idea\111.txt也是一个File
创建文件或目录(文件夹)
import java.io.File;
public class File1 {
public static void main(String[] args) throws Exception {
//创建File对象
File f1=new File("D\\file");
System.out.println(f1.exists());
//如果不存在,以文件的方式创建
if (!f1.exists()){
f1.createNewFile();
}
//如果不存在,以目录(文件夹)的方式存在
if (!f1.exists()){
f1.mkdir();
}
//创建多重目录
File f2=new File("D:\\a\\b\\c\\d");
if(!f2.exists()){
f2.mkdirs();
}
}
}
常用方法
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
public class File1 {
public static void main(String[] args) throws Exception {
File f1=new File("D:\\javaProject-idea\\112.txt");
//获取文件的父路径
String s =f1.getParent();
System.out.println(s);
//获取父亲文件
//获取父亲文件的绝对路径
File f2=f1.getParentFile();
System.out.println(f2.getAbsolutePath());
System.out.println(f1.getParentFile().getAbsolutePath());
//获取文件名
System.out.println(f1.getName());
//判断是否是一个目录
System.out.println( f1.isDirectory());
//判断是否是一个文件
System.out.println(f1.isFile());
//获取文件最后一次修改时间,返回是毫秒从1970年算
//将毫秒数转化成日期,日期格式化
long haomiao=f1.lastModified();
Date time=new Date(haomiao);
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
String now=sdf.format(time);
System.out.println(now);
//获取文件大小
System.out.println(f1.length());
}
}
获取当前目录下的所有子文件
import java.io.File;
public class File1 {
public static void main(String[] args) throws Exception {
File f1=new File("D:\\javaProject-idea");
File [] files=f1.listFiles();//返回的是数组
for (File file:files
) {
System.out.println(file.getAbsolutePath());
System.out.println(file.getName());
}
}
}
目录拷贝
import java.io.*;
public class Copy {
public static void main(String[] args) throws Exception{
//拷贝源
File srcFile=new File("D:\\javaProject-idea");
//拷贝目标
File destFile=new File("C:\\");
copy(srcFile,destFile);
}
private static void copy(File srcFile, File destFile) {
if(srcFile.isFile()){
//如果是文件的话,方法就结束
FileInputStream fis=null;
FileOutputStream fos=null;
try {
fis=new FileInputStream(srcFile);
//fos=new FileOutputStream(destdir);往这个路径写,把下面的路径拿上来
String path=destFile.getAbsolutePath().endsWith("\\")?( destFile.getAbsolutePath()+srcFile.getAbsolutePath().substring(3)):(destFile.getAbsolutePath()+"\\"+srcFile.getAbsolutePath().substring(3));
fos=new FileOutputStream(path);
//一边读一边写
byte[] bytes=new byte[1024*1024];
int readcount=0;
while ((readcount=fis.read(bytes))!=-1){
fos.write(bytes,0,readcount);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return;
}
File [] files=srcFile.listFiles();
for (File file:files //这里的file可能是文件也可能是文件夹
) {
//System.out.println(file.getAbsolutePath());
if(file.isDirectory()){
String srcdir=file.getAbsolutePath();
//System.out.println(srcdir);
// System.out.println(srcdir.substring(3));
//System.out.println(destFile.getAbsolutePath());
String destdir= destFile.getAbsolutePath().endsWith("\\")?( destFile.getAbsolutePath()+srcdir.substring(3)):(destFile.getAbsolutePath()+"\\"+srcdir.substring(3));
// System.out.println(destdir);
File f2=new File(destdir);
if(!f2.exists()){
f2.mkdirs();
}
}
//递归调用
copy(file,destFile);//如果file这是个文件夹,就再调用copy
}
}
}
思考,为什么递归在那个地方,不在前一个括号里面
foreach循环,files数组里面有可能会有文件夹也有可能是文件,所以还要遍历,正好调用遍历这个方法,把刚刚foreach遍历出的file当参数传进去
import java.io.File;
public class Di {
public static void main(String[] args) {
File f1=new File("D:\\ddddd\\新建文件夹");
// System.out.println(f1.getAbsolutePath());
Baili(f1);
}
private static void Baili(File srcFile) {
if(srcFile.isFile()){
System.out.println(srcFile.getName()+"是一个文件, 路径是:"+srcFile.getAbsolutePath());
}else{
System.out.println(srcFile.getAbsolutePath()+"是一个文件夹(目录)");
System.out.println("以下是文件夹的子文件");
File [] files=srcFile.listFiles();
for (File file:files
) {
//Baili(file);
System.out.println(file.getName());
}
}
}
}
对象流
序列化要实现Serializable接口,这个接口没有方法,起到标识的作用,java虚拟机自动生成序列化版本号,但是自动生成后的序列化版本号,一旦重新修改了代码,就要重新编译,这个版本号就会重新生成,建议手动写出版本号
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
public class ObjectInputf {
public static void main(String[] args) throws Exception{
Student s1=new Student(111,"zhangsan");
ObjectOutputStream oos =new ObjectOutputStream(new FileOutputStream("students"));
//序列化
oos.writeObject(s1);
oos.flush();
oos.close();
}
}
序列化多个对象
放到集合中
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
public class ObjectInputf {
public static void main(String[] args) throws Exception{
Student s1=new Student(111,"zhangsan1");
Student s2=new Student(222,"zhangsan2");
Student s3=new Student(333,"zhangsan3");
Student s4=new Student(444,"zhangsan4");
List list =new ArrayList();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("studentss"));
oos.writeObject(list);
oos.flush();
oos.close();
}
}
反序列化
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.util.List;
public class Fan {
public static void main(String[] args) throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("studentss"));
// Object obj=ois.readObject();//obj是一个集合
List<Student> studentList= (List<Student>) ois.readObject();
for (Student student:studentList
) {
System.out.println(student);
}
ois.close();
}
}
加上关键字transient,表示不参与序列化
IO与Properties联合使用
Properties是一个集合,键值对都是String类型
Properties在内存中,文件在硬盘上
将经常变得数据写在这个文件中,将需要修改这个文件内容,java不需要改动,不需要重新编译,服务器不需要重启,就可以拿到动态信息
这种文件叫做配置文件
在属性配置文件中##########注释############
mport java.io.FileInputStream;
import java.util.Properties;
public class IoProper {
public static void main(String[] args)throws Exception {
FileInputStream fis=new FileInputStream("D:\\ddddd\\1.txt");
//新建Map集合
Properties pro=new Properties();
//调用Properties对象的load的方法,将1.txt文件中的内容加载到集合中
pro.load(fis);//文件中数据顺着fis管道加载了进来,=左边做key右边做值
//通过key获取value
String username=pro.getProperty("username");
System.out.println(username);
fis.close();
}
}