title: JAVA IO流的基本操作
categories: java IO流
tags:
- java IO流
abbrlink: 23807
date: 2018-02-22 00:00:00
JAVA IO流的基本操作
1.File的操作
/**
* java.io.File
* File 的每一个实例用来表示硬盘上的一个文件或目录
* 我们通过File可以:
* 1:访问一个文件或目录的属性信息。
* 文件名,大小,修改日期,访问权限等
* 2:可以创建文件,删除文件,创建目录,删除目录
* 3.可以访问目录中的所有子项
* 但是不能:
* 不能访问文件数据
* @author lenovo
*
*/
public class FileDemo {
public static void main(String[] args) throws IOException {
/**
* 尽量使用相对路径
* 在eclipse中,"." 当前目录,指的是项目的根目录。
*
*/
File file = new File("."+File.separator+"FileDir"+File.separator+"test.txt");
//获取文件属性
String name = file.getName();
System.out.println("name:"+name);
/**
* 获取大小
* 返回值为一个long值,表示占用的字节量
*/
long length = file.length();
System.out.println("l:"+length);
//最后修改时间
long time = file.lastModified();
Date date = new Date(time);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("last date :"+sdf.format(date));
//判断是否可运行,可读,可写 权限 返回boolean值
System.out.println(file.canExecute());
System.out.println(file.canRead());
System.out.println(file.canWrite());
//判断当前File对象表示的是否为一个文件
boolean isFile = file.isFile();
System.out.println("isFile:"+isFile);
//是否是文件夹
boolean isDir = file.isDirectory();
System.out.println("isDir:"+isDir);
//是否隐藏
System.out.println(file.isHidden());
//创建文件
File file2 = new File("."+File.separator+"FileDir"+File.separator+"creat.txt");
if(!file2.exists()){
file2.createNewFile();
System.out.println("文件creat.txt创建成功");
}
//删除文件
File file3 = new File("."+File.separator+"FileDir"+File.separator+"del.txt");
if(file3.exists()){
file3.delete();
System.out.println("删除del文件成功!");
}
//创建目录
File dir = new File("."+File.separator+"FileDir"+File.separator+"aa");
if(!dir.exists()){
dir.mkdir();
System.out.println("创建aa目录成功!");
}
//创建多级目录
File dir2 = new File("."+File.separator+"FileDir"+File.separator
+"aa"+File.separator+"c"+File.separator+"d");
if(!dir2.exists()){
dir2.mkdirs();
System.out.println("make dirs");
}
//删除目录 删除目录,只能删除空目录
File dir3 = new File("."+File.separator+"FileDir"+File.separator
+"aa"+File.separator+"c"+File.separator+"d");
if(dir3.exists()){
dir3.delete();
System.out.println("删除d目录");
}
//获取一个目录下的所有子项
File dir4 = new File("."+File.separator+"FileDir");
File [] files = dir4.listFiles();
for(File f : files){
System.out.println((f.isFile() ? "文件:" :"目录:")+f.getName());
}
//获取过滤之后的文件
File dir5 = new File("."+File.separator+"FileDir");
File [] fs = dir4.listFiles(new FileFilter() {
public boolean accept(File file) {
System.out.println("正在过滤:"+file.getName());
return file.getName().startsWith("t");
}
});
for(File f : fs){
System.out.println("t开头的文件有:"+f.getName());
}
//递归删除目录所有文件
File dir6 = new File("."+File.separator+"FileDir"+File.separator+"b");
deleteFile(dir6);
}
//递归删除文件
public static void deleteFile(File file){
if(file.isDirectory()){
File[] files = file.listFiles();
for(File f : files){
deleteFile(f);
}
}
file.delete();
}
}
2.RandomAccessFile操作
/**
* java.io.RandomAccessFile
* RandomAccessFile 专门用来读写文件数据
* @author lenovo
*
*/
public class RandomAccessFileDemo {
@Test
public void demo07() throws IOException{
RandomAccessFile src = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"2.doc", "rw");
RandomAccessFile desc = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"3.doc", "rw");
byte[] b = new byte[1024*10];
int len = -1;
long start =System.currentTimeMillis();
while((len = src.read(b)) != -1){
/**
* void write(byte[] data,int offset,int len)
* 将当前数组中从offset指定位置开始,连续len个字节写出
*/
desc.write(b, 0, len);
}
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-start));
src.close();
desc.close();
}
@Test
public void demo06() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"c.txt", "rw");
RandomAccessFile raf2 = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"copy_of_c.txt", "rw");
int d = -1;
while((d = raf.read()) != -1){
raf2.write(d);
}
System.out.println("复制完成");
raf.close();
raf2.close();
}
@Test
public void demo05() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"raf.txt", "rw");
/**
* RandomAccessFile 的读写操作都是基于指针操作的
* 总是在指针当前位置进行读写操作,无论是读还是写,操作完毕后,指针都会向后自动移动。
* 新建的RandomAccessFile指针默认在文件的第一个字节上。
* 我们可以通过操作指针位置来读写具体位置上的字节内容。
* 指针----字节。
*/
long pos = raf.getFilePointer();
System.out.println("指针位置:"+pos);
int max = Integer.MAX_VALUE;
/** 写入一个字节 低八位
* max: vvvvvvvv write()低八位。
* 01111111 11111111 11111111 11111111
* max>>>24 左边补0,右边溢出不管
*/
raf.write(max>>>24);
pos = raf.getFilePointer();
System.out.println("指针位置:"+pos);
raf.write(max>>>16);
raf.write(max>>>8);
pos=raf.getFilePointer();
System.out.println("指针位置:"+pos);
raf.write(max);
//上面写入了int的最大值
raf.writeInt(max);
pos = raf.getFilePointer();
System.out.println("指针位置:"+pos);
raf.writeDouble(1.234);
pos = raf.getFilePointer();
System.out.println("指针位置:"+pos);
raf.writeLong(123L);
pos = raf.getFilePointer();
System.out.println("指针位置:"+pos);
/**
* RandomAccessFile 提供了可以操作指针位置的方法
* void seek(long pos)
* 将指针移动到指定位置
*/
raf.seek(0);
/**
* 读取基本类型数据
* 连续读取4个字节,并将对应int值返回,若读取到文件末尾了,
* 则抛出EOFException(End of File)
*/
int i = raf.readInt();
System.out.println(i);
i = raf.readInt();
System.out.println(i);
double d = raf.readDouble();
System.out.println(d);
long l = raf.readLong();
System.out.println(l);
/**
* void skipByte(int n)
* 忽略给定字节量
* 与seek不同点主要有两个:
* skipByte只能向后忽略
* skipByte给定的是相对值
*
* skipByte在流的使用中很常用
* RandomAcessFile比较常用seek。
*/
raf.seek(0);
raf.skipBytes(8);
d = raf.readDouble();
System.out.println(d);
raf.close();
}
@Test
public void demo04() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"raf.txt", "rw");
byte [] bytes = new byte[100];
int len = raf.read(bytes);
System.out.println(len);
/**
* 该构造方法允许我们将给定的字节数组中指定范围内的字节转换为对应的字符串
*/
String str = new String(bytes, 0, len, "UTF-8");
System.out.println(str);
raf.close();
}
@Test
public void demo03() throws IOException{
RandomAccessFile raf = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"raf.txt", "rw");
/**
* * 批量写出字节
* void write(byte [] data)
* 一次性将给定的字节数组中的所有字节写出
*/
String str = "摩擦摩擦,是魔鬼的步伐";
/**
* byte [] getByte()----上面输出22个byte
* String 提供的该方法可以将当前字符串按照系统默认的字符集转换为对应的一组字节
* GBK -----2个字节一个中文, UTF-8 3个字节一个中文
*
* byte [] getByte(String charset)
* 按照给定的字符集将字符串转换为一组字节
* 字符集:
* GBK--:国标编码,中文2个字节
* UFT-8--:编程编码集,1-4个字节 ,中文3字节 ,是unicode的一个子集,万国码
* ISO8859-1--:欧洲编码,不支持中文
*/
byte [] bytes = str.getBytes("UTF-8");
System.out.println(Arrays.toString(bytes));
raf.write(bytes);
System.out.println("写入完毕");
raf.close();
}
@Test
public void demo02()throws IOException{
/**
* int read()
* 读取一个字节,并以int形式返回
* 若读取到文件末尾则返回值为-1
*/
RandomAccessFile raf2 = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"raf.txt", "r");
int i = raf2.read();
System.out.println(i);
raf2.close();
}
@Test
public void demo01() throws IOException{
/**
* RandomAccessFile 创建支持很多模式
* 常用的有:
* “r”: 只读
* “rw” 读写
*/
RandomAccessFile raf = new RandomAccessFile(
"."+File.separator+"FileDir"+File.separator+"raf.txt", "rw");
/**
* void write(int d)
* 向文件中写入一个字节,写的是该int值
* 对应的2进制内容中的“低八位” 0000 0000 255以内
*
* 8位2进制是一个字节
* int值4字节,32位2进制 00000000 00000000 000000000 000000000
*/
raf.write(12);
/**
* RandomAccessFile 使用完毕后一定记得关闭来释放资源。
* jvm gc不管用
* 在底层的程序进行磁盘读写,此程序无法被gc回收。
*/
raf.close();
}
}
3.字符流与字节流的操作
/**
* 该类用于测试对象流读写对象
* 读写对象一般用于:
* 保存现有对象到硬盘上
* 在网络将传输对象。
*
*接口一般有两个作用:
* 1:约束子类行为(通常含有若干抽象方法,需要子类重写)
* 2:标签接口,就是给子类打个标签,不需要为此改变什么,Serializable。
*
*当一个类需要序列化时,除了该类自身要实现序列化接口外,其内部定义的自定义类型的属性也要实现序列化接口才可以。
*但是由Java提供的类不需要,他们通常都实现了序列化接口。
* @author lenovo
*
*/
public class Person implements Serializable {
/**
* 一个类实现了序列化接口后,通常要自行维护一个常量:serialVersionUID 版本号
* 版本号对于对象反序列化 的策略产生不同影响
* 当我们使用ObjectInputStream对一个对象继续反序列化的时候,
* 该流会检查待反序列化的对象与该类声明的版本号是否一致:
* 一致:可以反序列化
* 不一致:不可以反序列化
*
* 版本号一致时,若待序列化的对象与当前类现有的定义发生冲突(属性结构有变化了),则启用兼容模式:
* 待反序列化对象原有的属性,现在类没有了,则忽略该属性的值。
*
* 带反序列化对象没有的属性,现在类有的,则使用该属性默认值,其他原样还原。
*/
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String gender;
/**
* transient 关键字修饰的属性,序列化时被忽略,达到对象“瘦身"的目的。
*/
private transient List<String> otherInfo;
public Person(){
}
public Person(String name, int age, String gender, List<String> otherInfo) {
super();
this.name = name;
this.age = age;
this.gender = gender;
this.otherInfo = otherInfo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public List<String> getOtherInfo() {
return otherInfo;
}
public void setOtherInfo(List<String> otherInfo) {
this.otherInfo = otherInfo;
}
public String toString(){
return name+","+age+","+gender+","+otherInfo;
}
}
public class InputAndOutputDemo {
@Test
public void demo11()throws IOException{
/**
* PrintWriter提供了用于处理其他流的构造方法,既可以处理字符流,也可以处理字节流。
*/
FileOutputStream fis = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"buffRW.txt");
/**
* 可以直接将字节流包装为缓冲字符输出流
* 但是不足的地方在于,不能按照指定字符集将字符写出,而必须用系统默认字符集。
*/
//PrintWriter pw = new PrintWriter(fis);
OutputStreamWriter osw = new OutputStreamWriter(fis, "UTF-8");
/**
* 当我们使用第一个参数为流的构造方法创建PrintWriter时,它还支持一个重载的构造方法,
* 允许我们传入第二个参数,该参数为boolean类型。若该值为true,则创建的PrintWriter具有
* 自动行刷新:
* 每当调用println()方法写出一行内容后都会自动调用flush将其写出
* 这样做会降低写出效率,但是可以保证写出的及时性。
*/
//PrintWriter pw = new PrintWriter(osw, true);
PrintWriter pw = new PrintWriter(osw);
pw.println("你在南方的寒夜里大雪纷飞");
pw.println("我在北方的艳阳里四季如春");
pw.close();
}
@Test
public void demo10()throws IOException{
/**
* java.io.PrintWriter
* 缓冲字符输出流,特点是可以以行为单位写出字符串,并且该流还具备自动行刷新功能。
*
* 传统的缓冲字符输出流是BufferedWriter。
* 由于PrintWriter在创建的时候内部使用了该流,并且PrintWriter还具有自动行刷新,所以比较常用。
*
* PrintWriter提供了若干构造方法,可以方便快速创建
* @author lenovo
*
*/
/**
* PrintWriter 可以直接创建基于文件的写操作:
* PrintWriter(File file)
* PrintWriter(String path)
*/
PrintWriter pw = new PrintWriter("."+File.separator+"FileDir"+File.separator+"buffRW.txt","UTF-8");
pw.println("哈哈");
pw.write("hehe");
pw.println("不行不行");
pw.close();
}
@Test
public void demo09() throws IOException{
/**
* java.io.BufferedReader-------。字符流。
* 缓冲字符输入流 特点:以行为单位读取字符串
* @author lenovo
*
*/
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"buffRW.txt");
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
BufferedReader br = new BufferedReader(isr);
/**
* String readLine()
* BufferedReader 提供的该方法会读取若干字符,直到读取到换行符位置,
* 然后将换行符之前读取的这若干字符组成一个字符串返回
* 需要注意,返回的字符串中是不包含换行符的!
* 若返回值为null,说明读取到未见末尾了。
*/
String line = null;
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
}
@Test
public void demo08()throws IOException{
/**
* 转码:
* 比如将UTF-8编码的文本转换为GBK编码的文本文件
* 原理:
* 使用UTF-8编码将每一个字符读取出来,再以GBK编码将字符写入另一个文件即可。
* @author lenovo
*
*/
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"osw.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"osw_GBK.txt");
OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");
char [] cr= new char[1024*5];
int len = -1;
while((len = isr.read(cr)) != -1){
osw.write(cr, 0, len);
}
System.out.println("完成转码");
isr.close();
osw.close();
}
@Test
public void demo07()throws IOException{
/**
* Reader 字符输入流 特点:以字符为单位读取数据
* InputStreamReader 是其常用实现类,作用是可以按照指定的字符集读取字符。 *
*/
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"osw.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
int len = -1;
while((len = isr.read()) != -1){
System.out.println((char)len);
}
isr.close();
}
@Test
public void demo06()throws IOException{
/**
* 字符流:
* 以字符为单位读写内容,所以字符流只能读写文本数据!
* 字符流都是高级流,字符与字节之间的转换交给字符流来干,底层实际还是要读写字节的。
* Writer 字符输出流,特点:以字符为单位写出数据,
* OutputStreamWriter:字符流的一个常用实现类。特点是可以按照指定的字符集将给定的字符串
* 转换为对应字节后写出。 *
*/
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"osw.txt");
/**
* 常用构造方法:
* OutputStreamWriter(OutputStream out)
* 按照系统默认字符集将字符串转换为字节后写出
*
* OutputStreamWriter(OutputStream out ,String charsetName)
* 按照给定的字符集将字符串转换为字节后写出。
*/
OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
osw.write("哈哈,你好。");
osw.write("什么意思?");
osw.close();
}
@Test
public void demo05() throws IOException{
/**
* BIS 与BOS
* 缓冲字节输入流,缓冲字节输出流
* 这是一对高级流,作用是可以提高读写效率
*/
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"heike.mp4");
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"heike_2.mp4");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int len = -1;
while((len = bis.read()) != -1){
bos.write(len);
}
System.out.println("复制完成");
bis.close();
bos.close();
}
@Test
public void demo04()throws IOException{
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"2.doc");
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"3.doc");
byte [] data = new byte[1024*10];
int len = -1;
while((len=fis.read(data)) != -1){
fos.write(data, 0, len);
}
System.out.println("复制完毕");
fis.close();
fos.close();
}
@Test
public void demo03()throws IOException{
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"BOF.txt");
BufferedOutputStream bof = new BufferedOutputStream(fos);
String str = "我爱你我的家";
bof.write(str.getBytes());
/**
* void flush()
* 缓冲流都提供了flush的实现。作用是强制将现有缓冲数组中的数据一次性写出。
* 频繁调用该方法会提高写出次数从而降低写出效率,但是当我们需要有写出数据及时性的时候就要使用。
*/
bof.flush();
bof.close();
}
@Test
public void demo02()throws IOException, ClassNotFoundException{
/**
* java.io.ObjectOutputStream
* 高级流,功能是将给定的一个对象转换为一组字节
* 然后通过其处理的流将字节写出。
*/
FileOutputStream fos = new FileOutputStream("."+File.separator+"FileDir"+File.separator+"person.obj");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Person p = new Person();
p.setAge(23);
p.setName("大神");
p.setGender("男");
List<String> list = new ArrayList<>();
list.add("不知道啥");
list.add("啥也不知道");
p.setOtherInfo(list);
/**
* void writeObject(Object obj)
* 该方法会将给定的对象转换为一组字节然后写出
*
* 序列化:
* 将一个数据结构转换为一组字节的过程。
*
* 将内存中的数据写入硬盘长久保存的过程称之为:持久化。
*
*/
oos.writeObject(p);
oos.close();
/**
* java.io.ObjectInputStream
* 高级流,可以进行对象的反序列化
* 将一组字节还原回对象,前提是这一组字节必须是由ObjectOutputStream将一个对象序列化后的字节。
*/
FileInputStream fis = new FileInputStream("."+File.separator+"FileDir"+File.separator+"person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);
/**
* Object readObject()
* 改方法会读取若干字节,然后将其反序列化回对象。
* 并以Object形式返回,需要自己强制类型转换
*/
Person pers = (Person) ois.readObject();
System.out.println(pers);
ois.close();
}
@Test
public void demo01()throws IOException{
/**
* java.io.FileOutputStream
* 文件字节输出流,用于将数据写入到文件中的流
* 该流是一个低级流
* 低级流特点:
* 数据的来源和去向是明确的,真实负责"搬运"数据的流
*/
File file = new File("."+File.separator+"FileDir"+File.separator+"fos.txt");
/**
* 向文件中写出数据
* 一个参数的构造方法:
* FileOutputStream(String path)
* FileOutputStream(File file)
* 创建出来的文件输出流是覆盖写操作,若操作的文件中有数据,会先将数据清除,
* 重写本次写出的数据。。。
* (File 对象)
*
* 若希望追加写操作,则需要传入第二个参数
* 是一个boolean值,为true即可。
* FileOutputStream(File file ,boolean append)
* FileOutputStream(String path ,boolean append)
*
*/
FileOutputStream fos = new FileOutputStream(file,true);
String str = "这些年过的怎么样?";
fos.write(str.getBytes("UTF-8"));
fos.close();
FileInputStream fis = new FileInputStream(file);
byte [] buf = new byte[1024*10];
int len = fis.read(buf);
System.out.println(new String(buf,0,buf.length,"UTF-8"));
fis.close();
}
}
打赏