创建文件对象:可以是物理文件或目录,操作文件或目录的属性(路径、权限、日期和时间等)
通过流来读写文件,流是一组有序的数据序列,以先进先出方式发送信息的通道
很多的信息,都是通过文件来读取的,文件是数据源
对于程序来说,把文件读入到程序中,这是输入,把资料读出去是是输出。
在Java中流的分类:
按流向区分: 1、输出流---->OutputStream和Writer作为基类
2、输入流---->InputputStream和Reader作为基类 输入输出流是相对于计算机内存来说的
按照处理数据单元划分: 1、字节流---->字节输入流InputputStream 字节输出流OutputStream这两个作为基类 字节流是8位通过字节流,字符流是16位Unicode字符流
2、字符流---->字符输入流Reader 字符输出流Writer这两个作为基类
通常使用按处理数据单元划分的多一点。
字节流: InputStream
read() 从输入流一个字节一个字节的读,返回的是该字节的整数表示形式,如果到了输入流的末尾,返回-1
read(byte[ ] a) 从输入流读取若干字节,把这些字节保存到数组a中,返回的是读取到字节数,如果到了输入流的末尾,返回-1
read(byte[ ] a,int off,int len) 从输入流读取若干字节,把这些字节保存到数组a中,off指的是字节数组中开始保存数据的起始下标,len指读取的字节数 目。返回的是读取到的字节数,如果到了输入流的末尾,返回-1
close()
available() 可以从输入流中读取的字节数目
FileInputStream(子类FileInputStream常用的构造方法)
new FileInputStream(File file) 这是一个文件类
new FileInputStream(String path) 这是路径
OutputStream
write(int a)
write(byte [ ] a)
write(byte [ ] a,int off ,int len)
close()
flush() 强制将缓冲区清空
FileOutputStream
new FileOutputStream(File file)
new FileOutputStream(String path)
new FileOutputStream(String path,boolean append)可以指定覆盖或追加文件内容,设置为true的时候,就是追加
Reader
read() 从输入流一个字节一个字节的读,返回的是该字节的整数表示形式,如果到了输入流的末尾,返回-1
read(byte[ ] a) 从输入流读取若干字节,把这些字节保存到数组a中,返回的是读取到字节数,如果到了输入流的末尾,返回-1
read(byte[ ] a,int off,int len) 从输入流读取若干字节,把这些字节保存到数组a中,off指的是字节数组中开始保存数据的起始下标,len指读取的字节数 目。返回的是读取到的字节数,如果到了输入流的末尾,返回-1
close()
InputStreamReader(是Reader的子类)可以指定字符编码格式
new InputStreamReader(InputStream in)
new InputStreamReader(InputStream in, String charsetName) String charsetName这就是想要的编码格式,流和文件是编码格式化要一致,比如文件 格式是GBK,然后设置的也要是GBK
FileInputStreamReader(是InputStreamReader的子类,该类只能按照本地平台的字符编码来读取数据,用户不能指定其他的字符编码类型)
new FileReader(File file)
new FileReader(String name)
中文乱码: 原因:文件编码格式 和程序环境的编码格式不一致谢
解决方案:FileReader是无法指定编码格式的,会按照程序的编码格式打印的。可以使用InputStreamReader字符输入流
BufferedReader 缓冲区输入流类,再将Reader类包装成BufferedReader类,为了提高效率,把文件内容都读到了缓冲区中,然后读取数据的时候,就直接在缓冲区区读取
readLine() 这个方法,一次将一行的内容读取出来
System.getProperty("file.encoding");获得本地平台的字符编码类型
Writer
writer(String str) 将str字符串里包含的字符输出到指定的输出流中
writer(String str,int off,int len) 将str字符串里从off位置开始,长度为len的多个字符输出到输出流中
close()
flush() 刷新输出流,清空缓存
OutputStreamWriter(是Writer的子类)
OutputStreamWriter(OutputStream out)
OutputStreamWriter(OutputStream out,String charsetName)
BufferedWriter
Writer中也有输出的字符的缓冲区输出流,注意缓冲区的内容是字符串了,不再是字节了
缓冲区其实就是一个字节数组,它要积累的一定的数量,才会输入或输出
注意:所有的流都要关了,输出流不仅要关流,还要清空缓冲区的数据
二进制流:就是进行图片、音乐等这样的文件,就是使用二进制流进行读写的
DataInputStream:是FileInputStream的子类,与FileInputStream结合使用,使用的方法跟InputStream方法一样
new DataInputStream (InputStream in)
DataOutputStream:是FileOutputStream的子类,与FileOutputStream结合使用
new DataOutputStream(OutputStream in)
序列化与反序列化:序列化就是将对象(Java中创建的对象)的状态写入到特定的流中的位置,记得对象所属的类可以完成序列化,要完成序列化的对象,要记得去实现序列化的接口Serializable,才可以进行序列化的操作,对象中的某一个状态不想被序列化,可以在相应的属性中加一个关键字transient。
序列化,就是把对象放进到流中,这个使用的是ObjectOutputStream,反之则使用ObjectInputStream
ObjectInputStream
new ObjectInputStream(FileInputStream fis) 注意:因为是Object对象,所以使用的方法跟InputStream一样,只是是readObject()方法
ObjectOutputStream
new ObjectOutputStream(FileOutputStream fis) 注意:反序列化接收到的是Object对象,所以要进行类型转换,使用的方法也是writerObject()方法
使用io的步骤:
1、引入相关的类
2、构造文件输入流或输出流或字符输入流或字符输出流
3、读取或写出文本文件的数据
4、关闭流对象
案例1:普通的输入和输出
import java.io.File;
import java.io.IOException;
public class TestClass {
/**
* 创建一个文件或者目录
* @param file
*/
public void creatFile(File file){
if(file.exists()){//判断文件或目录是否存在,存在为true
System.out.println("此文件已存在!");
}else{
try {
file.createNewFile();//创建文件
System.out.println("文件创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获得文件的信息
* @param file
*/
public void getFileInfo(File file){
if(file.exists()){//先判断是否有此文件或者目录
if(file.isFile()){//判断是否是文件
//获得文件的绝对路径
String string=file.getPath();//相对路径
String a=file.getAbsolutePath();//绝对路径
String name=file.getName();//获得文件名
System.out.println("相对路径: "+string);
System.out.println("绝对路径: "+a);
System.out.println("文件名为:"+name);
System.out.println("文件大小为:"+file.length());
}
if(file.isDirectory()){//判断是否是目录
System.out.println("此文件是目录");
}
}else {
System.out.println("此文件不存在!");
}
}
/**
* 删除文件
* @param file
*/
public void del(File file){
if(file.exists()){//先要判断是否有此文件才可以进行删除工作
file.delete();
System.out.println("删除文件成功!");
}else{
System.out.println("此文件不存在");
}
}
}
public static void main(String[] args) {
//要去判断是否有这个文件或者目录,如果没有,那么就去创建一个文件
TestClass testClass=new TestClass();
File file=new File("E:/练习/text.txt");//这里是要创建的文件
// testClass.creatFile(file);//通过调用方法去检查是否有该文件或目录,没有就创建
// testClass.getFileInfo(file);
testClass.del(file);
}
案例2:输入流和输出流的结合使用
public static void main(String[] args) {
//出现的问题:1:前面有一堆的字符,然后输入的中文有乱码的问题,解决的方法是FileOutputStream的write方法中,结束的位置是data,不是数组的长度
//先把要复制的文件输入出来,然后再输出文件出来
//创建输入流
FileOutputStream fos=null;
//创建输出流
FileInputStream fis=null;
try {
//需要复制的原文件
fis=new FileInputStream("E:/练习/test.txt");
//复制到的文件,内容进行追加
fos=new FileOutputStream("E:/练习/text.txt",true);
//读取的长度
int data=-1;
//创建一个数组,去接收文件
byte [] b=new byte[1024];
try {
//通过读取去获得文件内容
while ((data=fis.read(b))!=-1) {
//通过输出流将文件写到目标文件中去,长度是读取到的文件内容的长度
fos.write(b, 0, data);
}
/*//这里在循环条件中读取了一次,然后在循环体中又读取了一次,所以读取出来的文件内容是没有第一个字节的
while((fis.read())!=-1){
fis.read(b);
//这里结束的尾部是数组的长度,如果数组没有读取出那么多,就会在文件中尾部输出很多的空格,所以这里要是文件的长度
fos.write(b,0,b.length);
}*/
System.out.println("复制成功!");
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
案例3:所有文件的输入和输出流的结合使用
public static void main(String[] args) {
InputStream is=null;//输入流
InputStreamReader isr=null;
BufferedInputStream bis=null;
OutputStream os=null;//输出流
OutputStreamWriter osw=null;
BufferedOutputStream bos=null;
try {
//创建出输入流
is=new FileInputStream("F:/刘楠梅/hello.txt");
bis=new BufferedInputStream(is);
isr=new InputStreamReader(is,"GBK");//因为txt文件默认的编码格式是GBK,所以输入流设置的编码格式也要是GBK
//创建输出流
os=new FileOutputStream("G:/测试/你好.txt",true);
bos=new BufferedOutputStream(os);
osw=new OutputStreamWriter(os,"GBK");
//设置接收读取的长度
int len=-1;
//读取的字符数组
byte [] b=new byte[1024];
//循环遍历文件的内容,当内容为-1的时候,跳出循环
while((len=bis.read(b))!=-1){
//将文件输出
bos.write(b);
}
//要将输出流强制清空,不然文件不会有内容
bos.flush();
System.out.println("完成复制!");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
//最后关闭所有使用的流,记得后的先关闭,最先的最后关闭
osw.close();
bos.close();
os.close();
isr.close();
bis.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
案例4:这是一个字符流的输入
public static void main(String[] args) {
Reader reader=null;
try {
reader=new FileReader("E:/练习/text.txt");
int data=-1;
//读取的不再是字节了,而是字符了,所以使用char数组去接收读取出来的内容
char []b=new char[1024];
//可以使用StringBuffer类去添加字符串,会比较灵活
StringBuffer stringBuffer=new StringBuffer();
try {
//data是实际读取到的字符数
while ((data=reader.read(b))!=-1) {
stringBuffer.append(b);
}
System.out.println(stringBuffer);
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
//记得一定要关闭流
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
案例5:二进制输入流和输了流的结合使用
public static void main(String[] args) {
DataInputStream dis=null;
FileInputStream fis=null;
DataOutputStream dos=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
fis=new FileInputStream("G:/图/IMG_0054.JPG");//地址
dis=new DataInputStream(fis);
bis=new BufferedInputStream(fis);
fos=new FileOutputStream("E:/视频/myphote.JPG");
dos=new DataOutputStream(fos);
bos=new BufferedOutputStream(fos);
byte [] b=new byte[1024];
int len=-1;
while((len=bis.read(b))!=-1){
bos.write(b);
}
System.out.println("写完");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
try {
bos.close();
dos.close();
fos.close();
bis.close();
dis.close();
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
案例6:序列化与反序列化
public static void main(String[] args) {
Student stu=new Student("小红",18,"123456");
InputStream is=null;
ObjectInputStream ois=null;
//这是序列化,是把对象写进流中,是输出
OutputStream os=null;
ObjectOutputStream oos=null;
try {
//序列化
os=new FileOutputStream("G:/测试/hello.txt");//输出流
oos=new ObjectOutputStream(os);
oos.writeObject(stu);//传入的参数是Object类型
os.flush();
is=new FileInputStream("G:/测试/hello.txt");//输入流
ois=new ObjectInputStream(is);
Student s=(Student)ois.readObject();
System.out.println(s.getName()+" "+s.getAge()+" "+s.getPassword());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
try {
ois.close();
is.close();
oos.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}