1、File
1)构造方法
2)创建
3)判断、获取
4)删除
2、字节流
1)字节流写数据的3种方式
FileOutputStream fos = new FileOutputStream("e:\\a.txx");
//将字符转为字节
Bytes[] bytes = "abcdefffjdlsajflasdfjklasdf".getBytes();
fos.write(bytes,0,bytes.length);
//关闭资源
fos.close();
2)字节流写数据实现换行
fos.write("\rn\".getBytes());
windows:\r\n
linux:\n
mac:\r
3)字节流写数据实现追加
FileOutputStream fos = new FileOutputStream("e:\\a.txx",true);
//加上true之后,就是从文件的末尾写入,不加true,默认是从文件的开头写入
4)异常处理
FileOutputStream fos = null;
try{
fos = new FileOutputStream("e:\\a.txx",true);
}catch(IOExcetion p){
e.printStackTrace();
}finally{
//不管文件读写有没有出错,最后一定要 close资源
if(fos !=null) fos.close();
}
3、读写文件
1)读取文件
//读取文件的数据,读物1024整数个字节
public static void readFile2()throws IOException {
FileInputStream input =new FileInputStream("e:\\file.txt");
//读取1024字节及其整数倍
byte[]bytes =new byte[1024];
//单次读取的长度
int len;
while ((len =input.read(bytes)) != -1){
System.out.println("长度:"+len);
System.out.println(new String(bytes,0,len));
}
2)写入文件,读1024整数倍个字节
//实现将file.txt内容写入到file2.txt,读取1024整数倍个字节
public static void readAndWrite() throws IOException {
//先创建file2.txt
FileOutputStream out = new FileOutputStream("e:\\file2.txt",true);
//获得file.txt,用于读取文件
FileInputStream input = new FileInputStream("e:\\file.txt");
//装读取文件的流
byte[] b = new byte[1024];
//装单次读入大小
int len;
//读取文件数据
while((len = input.read(b)) != -1){
//将数据写入到file2.txt
out.write(b,0,len);
}
out.close();
input.close();
}
3)读取1个字节就写入一个字节
4、复制图片
//复制图片
public static void readPicture() throws IOException {
//图片目的地
FileOutputStream out = new FileOutputStream("e:\\pic.png");
//图片原始位置
FileInputStream inputStream =new FileInputStream("e:\\25.png");
//存取单次读入的数据
byte[] bytes = new byte[1024];
//存取单次读取的数据的长度
int len;
//读数据
while ((len = inputStream.read(bytes)) != -1){
//写数据:bytes
out.write(bytes,0,len);
}
out.close();
inputStream.close();
}
5、字节缓冲流
1)写入数据
2)读取数据,一次读取一个字节
3)读取数据,一次读取一个字节数组
4)复制视频
public static void readVedio()throws IOException {
//1.找到视频文件
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("e:\\08.avi"));
//2.创建目标文件
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("e:\\09.avi"));
byte[] b =new byte[1024];
int len;
//3.读取、写入
while ((len = bis.read(b)) !=-1) {
bos.write(b,0,len);
}
//4.关闭流
bos.close();
bis.close();
}
4、字符流
对于汉字的存储,如果是GBK进行编码,占用的是2个字节;如果是UTF-8进行编码,占用3个字节。
1)为什么出现字符流?
字节流操作中文不是特别方便,Java提供了字符流
字符流=字节流+编码表
在进行汉字存储时,无论哪一种编码存储,第一个字节都是负数。
2)字符串中的编码与解码
编码:
byte[] getBytes():使用平台的默认字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
byte[] getBytes(String charsetName):使用指定的字符集将该 String编码为一系列字节,将结果存储到新的字节数组中
解码:
String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的 String
String(byte[] bytes, String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
2)字符流中的编码与解码
字符流抽象基类
Reader:字符输入流的抽象类
Writer:字符输出流的抽象类
字符流中和编码解码问题相关的两个类:
InputStreamReader
OutputStreamWriter
//使用默认编码写入
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("e:\\file.txt"));
//使用指定編碼寫入
OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream("e:\\file.txt"),"UTF-8");
osw.write("中国");
osw.close();
//使用默认编码读取
// InputStreamReader isr = new InputStreamReader(new FileInputStream("e:\\file.txt"));
//使用指定编码读取
InputStreamReader isr =new InputStreamReader(new FileInputStream("e:\\file.txt"),"UTF-8");
int len;
while ((len =isr.read())!=-1){
System.out.print((char)len);
}
//使用指定编码读取
isr.close();
3)字符流写数据
//字符流写数据:方式一:void write(int c)
OutputStreamWriter osw =new OutputStreamWriter(new FileOutputStream("e:\\file.txt"),"UTF-8");
//方式一:void write(int c)
osw.write(97);
osw.write("\r\n");
//方式二:void write(char[] cbuf)
char[]c =new char[]{'1','2','3'};
osw.write(c);
osw.write("\r\n");
//方式三:void write(char[] cbuf, int off, int len)
char[]c2 =new char[]{'1','2','3','4','5','6','7'};
//从下标为0开始写,写入3个,也就是1、2、3
osw.write(c2,0,3);
osw.write("\r\n");
//方式四:void write(String str)
String str ="zhangsan";
osw.write(str);
osw.write("\r\n");
//方式四:void write(String str, int off, int len)
osw.write(str,0,3);//zha
osw.write("\r\n");
osw.close();
4)字符流读数据
InputStreamReader isr =new InputStreamReader(new FileInputStream("e:\\file.txt"));
//方式一:int read()
int len;
while ((len =isr.read())!=-1){
System.out.print((char)len);
}
// 方式二:int read(char[] cbuf)
char[]c =new char[1024];
while ((len =isr.read(c))!=-1){
System.out.print(new String(c,0,len));
}
isr.close();
5)复制文件
方式一:
方式二:使用FileReader与FileWriter
5、字符缓冲流
字符缓冲流:
BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小。默认值足够大,可用于大多数用途
BufferedReader:从字符输入流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小。
默认值足够大,可用于大多数用途
构造方法:
BufferedWriter(Writer out)
BufferedReader(Reader in)
BufferedReader br =new BufferedReader(new FileReader("e:\\file.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("e:\\file4.txt"));
int len;
char[]c =new char[1024];
while ((len =br.read(c))!=-1){
bw.write(c,0,len);
}
br.close();
bw.close();
}
1)特有功能
BufferedWriter:
void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
public String readLine() :读一行文字。
结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null
一行行读取数据,进行文件复制:
public static void line2()throws IOException {
BufferedReader br =new BufferedReader(new FileReader("e:\\file.txt"));
BufferedWriter bw=new BufferedWriter(new FileWriter("e:\\file3.txt"));
String line;
while ((line =br.readLine())!=null){
bw.write(line);
bw.newLine();
}
br.close();
bw.close();
}
案例1:点名器
案例2:集合到文件(需求:把ArrayList集合中的学生数据写入到文本文件。要求:每一个学生对象的数据作为文件中的一行数据。 格式:学号,姓名,年龄,居住地 举例:1001,李局,30,北京)
案例3:文件到集合(需求:把文本文件中的数据读取到集合中,并遍历集合。要求:文件中每一行数据是一个学生对象的成员变量值。举例:举例:1001,李局,30,北京)
案例4:集合到文件(数据排序)(键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩)。要求按照成绩总分从低到高写入文本文件 。 格式:姓名,语文成绩,数学成绩,英语成绩 举例:zs,18,9,10)
案例5:复制单级文件夹
public class TestFile {
public static void main(String[] args) throws IOException {
copyfile();
}
private static void copyfile() throws IOException {
//获取要复制的文件夹,源文件
File srcFile = new File("e:\\file");
//获取文件名
String srcFolderName = srcFile.getName();
File destFolder = new File("e:\\照片",srcFolderName);
//如果目的地目录不存在,就新建
if(!destFolder.exists()){
destFolder.mkdir();
}
//获取数据源目录下的所有文件
File[] files = srcFile.listFiles();
for(File srcF:files){
String srcFileName = srcF.getName();
File destFile = new File(destFolder,srcFileName);
copy(srcF,destFile);
}
}
//f1目标文件,f2要输入到的文件
private static void copy(File f1, File f2) throws IOException {
FileInputStream bis = new FileInputStream(f1);
FileOutputStream bos =new FileOutputStream(f2);
byte[] b= new byte[1024];
int len;
while ((len=bis.read(b))!=-1){
bos.write(b,0,len);
}
bis.close();
bos.close();
}
}
案例6:复制多级文件夹
public class TestFile4 {
private static String srcFatherPath="C:\\Users\\Administrator\\Desktop\\图片";
private static String desFatherPath="e:\\zfile";
public static void main(String[] args) throws IOException {
//找到文件對象
File srcFile = new File(srcFatherPath);
File desFile = new File(desFatherPath);
//调用复制文件夹方法
copyFolder(srcFile,desFile);
}
public static void copyFolder(File srcFile,File desFile) throws IOException {
//如果源文件是一个文件夹
if(srcFile.isDirectory()){
//获取文件夹的名称
String srcFileName = srcFile.getName();
//创建目标文件夹
File desFolder = new File(desFile,srcFileName);
//判断目标文件夹是否存在
if(!desFolder.exists()){
//不存在,新建
desFolder.mkdirs();
}
//获取文件夹,里面的文件对象数组
File[] fileArray = srcFile.listFiles();
//遍历数组
for(File file: fileArray){
//对每个遍历出来的对象,再次判断是文件夹还是文件
copyFolder(file,desFolder);
}
}else{
//如果不是一个文件夹,说明是一个文件,就复制文件
File newFile = new File(desFile,srcFile.getName());
copy(srcFile,newFile);
}
}
private static void copy(File srcFile, File desFile) throws IOException {
//读取源文件
FileInputStream fis =new FileInputStream(srcFile);
//写入新文件
FileOutputStream fos = new FileOutputStream(desFile);
int len;
byte[] b = new byte[1024];
while ((len=fis.read(b))!=-1){
fos.write(b,0,len);
}
fos.close();
fis.close();
}
}
6、特殊操作流
1)标准输入输出流
输入
输出
(System.out)输出语句的本质:是一个标准的输出流
PrintStream ps = System.out;
PrintStream类有的方法,System.out都可以使用
2)打印流
字节打印流:PrintStream
字符打印流:PrintWriter
打印流的特点:
只负责输出数据,不负责读取数据。永远不会抛出IOException。有自己的特有方法。
字节打印流
PrintStream(String fileName):使用指定的文件名创建新的打印流
使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
可以改变输出语句的目的地
public static
void setOut(PrintStream out):重新分配“标准”输出流
字符打印流
复制文件
2)对象序列化流
要实现序列化和反序列化就要使用对象序列化流和对象反序列化流:
对象序列化流:ObjectOutputStream
对象反序列化流:ObjectInputStream
序列化
对象序列化
反序列化流
序列化与反序列化问题
a、用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会不会出问题呢?
会出问题,会抛出InvalidClassException异常
b、如果出问题了,如何解决呢?
重新序列化;给对象所属的类加一个serialVersionUID
private static final long serialVersionUID = 42L;
c、如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?
给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程
3)properties
Properties类表示一组持久的属性。Properties可以保存到流中或从流中加载。属性列表中的每个键及其对应的值都是一个字符串。
案例:猜数字游戏,将游戏剩余次数放入文件中