io 很好地体现了java面向对象的设计思想
一个接口或抽象类的具体行为由子类决定,那么根据实例化子类的不同 完成的功能也不同
1,File
file类 在整个java.io 包中是一个独立的类,此类的主要功能是完成与平台无关的文件操作。例如:创建文件,产出文件等等。
在File类中提供了一下构造方法:public File(String pathname)
在使用时需要制定一个文件的具体路径
1.1 创建文件
import java.io.File; import java.io.IOException; public class CreateFileDemo01 { public static void main(String[] args) { File file = new File("d:\\demo.txt"); // 找到File类的实例 try { file.createNewFile(); // 创建文件 } catch (IOException e) { e.printStackTrace(); } } }
1.2 删除文件
file.delete();
注:由于windows:\
linux:/
java 本市跨平台的语言 所以FIle类中提供了已下常量
public static final String pathSeparator ; ";"
public static final String separator "\" "/"
来代替所以 用File.separator 来进行分隔
1.3,判断文件是否存在
public boolean exists();
file.exists();
1.4 判断路径是文件还是文件夹
public boolean isDirextory()
public boolean isFile()
File file1=new File("d:"+File.separator+"demo");
File file2=new File("d:"+File.separator+"demo.txt");
System.out.println(file1.isFile);
1.5 列出目录中的内容
import java.io.File; public class ListDemo { public static void main(String[] args) { File file = new File("d:" + File.separator + "docs"); // 找到File类的实例 String path[] = file.list(); // 列出全部的内容 for (int i = 0; i < path.length; i++) { System.out.println(path[i]) ; } } }
list()列出的只是一目录下的文件或文件夹
为了清楚地表示列出的路径:
import java.io.File; public class ListFilesDemo { public static void main(String[] args) { File file = new File("d:" + File.separator + "docs"); // 找到File类的实例 File path[] = file.listFiles(); // 列出全部的子文件或文件夹 for (int i = 0; i < path.length; i++) { System.out.print(path[i].getParent() + " --> "); System.out.println(path[i].getPath()); } } }
listFiles() 列出的却是完整的路径。如果箱操作文件肯经后者更方便。找到了FIle类的对象就找到了完整的路径。
1.6创建目录
mkdir()
File file=new File("d:\\aa\\demo.txt");
File.mkdir();
1.7列出一个目录中所有的文件或文件夹
import java.io.File; public class ListDirectoryDemo { public static void main(String[] args) { File file = new File("d:" + File.separator); list(file); } public static void list(File file) { if (file.isDirectory()) { File lists[] = file.listFiles(); if (lists != null) { for (int i = 0; i < lists.length; i++) { list(lists[i]);// 列出内容 } } } System.out.println(file); } }
2 RandomAccessFile
之前的File类只是针对文件本身进行操作的,而如果要对文件内容进行操作,则需要RandomAccessFile类
此类属于随机读取类,可以随机读取一个文件中指定位置的数据。
想要实现随机读取,则存储数据的时候保证数据长度的一致性是必须的,否则无法成功。
public RandomAccessFile(File file,String mode)throws FileNotFoundException
读模式:r 写:w 读写:rw
其中读写模式是最重要的 如果操作的文件不存在的话 会帮用户自动创建的。
2.1 写入操作
import java.io.File; import java.io.RandomAccessFile; public class RandomAccessFileDemo01 { public static void main(String[] args) throws Exception {// 所有异常抛出 File file = new File("d:" + File.separator + "demo.txt");// 指定要操作的文件 RandomAccessFile raf = new RandomAccessFile(file, "rw");// 以读写的形式进行操作 // 写入第一条数据 String name = "zhangsan";// 表示姓名 int age = 30; // 表示年龄 raf.writeBytes(name); // 以字节的方式将字符串写入 raf.writeInt(age); // 写入整型数据 // 写入第二条数据 name = "lisi ";// 表示姓名 age = 31; // 表示年龄 raf.writeBytes(name); // 以字节的方式将字符串写入 raf.writeInt(age); // 写入整型数据 // 写入第三条数据 name = "wangwu ";// 表示姓名 age = 32; // 表示年龄 raf.writeBytes(name); // 以字节的方式将字符串写入 raf.writeInt(age); // 写入整型数据 raf.close();// 文件操作的最后一定要关闭 } }
2.2 读取操作
RandomAccessFile 操作的读取方法都是从DataInput接口实现而来的,有一系列的readXx()方法可以读取各类型的数据。
但是在RandomAccessFile 中可以实现随机读取,所以有一系列的控制方法。
回到读取点:public void seek(long pos) throws IOException
跳过读取点:public int skipBytes(int n) throws IOException
import java.io.File; import java.io.RandomAccessFile; public class RandomAccessFileDemo02 { public static void main(String[] args) throws Exception {// 所有异常抛出 File file = new File("d:" + File.separator + "demo.txt");// 指定要操作的文件 RandomAccessFile raf = new RandomAccessFile(file, "r");// 以读的形式进行操作 byte b[] = null;// 定义字节数组 String name = null; int age = 0; b = new byte[8]; raf.skipBytes(12); // 跨过第一个人的信息 System.out.println("第二个人的信息:"); for (int i = 0; i < 8; i++) { b[i] = raf.readByte(); // 读取字节 } age = raf.readInt();// 读取数字 System.out.println("\t|- 姓名:" + new String(b)); System.out.println("\t|- 年龄:" + age); raf.seek(0);// 回到开始位置 System.out.println("第一个人的信息:"); for (int i = 0; i < 8; i++) { b[i] = raf.readByte(); // 读取字节 } age = raf.readInt();// 读取数字 System.out.println("\t|- 姓名:" + new String(b)); System.out.println("\t|- 年龄:" + age); raf.skipBytes(12); // 跨过第二个人的信息 System.out.println("第三个人的信息:"); for (int i = 0; i < 8; i++) { b[i] = raf.readByte(); // 读取字节 } age = raf.readInt();// 读取数字 System.out.println("\t|- 姓名:" + new String(b)); System.out.println("\t|- 年龄:" + age); raf.close();// 文件操作的最后一定要关闭 } }
在文件中提供了指针,完成具体的操作功能。
RandomAccessFile可以进行读写操作旦毕竟比较麻烦,java读写操作一般都用字符流或字节流
3,字节流
整个io包中流的操作就分为两种
字节流和字符流
OutputStream InputStream writer reader
3.1 OutputStream 字节输出流
OutputStream 是抽象类 FileOutputStream 是实例化子类。
方法 写入全部字节数组:public void write(byte[] b)throws IOException
写入部分字节数组:public void write(byte[] b,int off,int len)throws IOException
写入一个数据:public abstract void write(int b)throws IOException
import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class OutputStreamDemo01 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 OutputStream out = null; // 声明字节输出流 out = new FileOutputStream(file); // 通过子类实例化 String str = "hello world"; // 要输出的信息 byte b[] = str.getBytes(); // 将String变为byte数组 out.write(b); // 写入数据 out.close(); // 关闭 } }
当然也可以循环一个一个输出
import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class OutputStreamDemo02 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 OutputStream out = null; // 声明字节输出流 out = new FileOutputStream(file); // 通过子类实例化 String str = "hello world"; // 要输出的信息 byte b[] = str.getBytes(); // 将String变为byte数组 for (int i = 0; i < b.length; i++) { out.write(b[i]); // 写入数据 } out.close(); // 关闭 } }
以上操作 会发现一个问题每次执行完,所有的内容都会被覆盖掉,如果希望追加:
仔细观察 构造方法 public FileOutputStream(File file,boolean append)throws FileNotFoundException
如果将append的内容设为true 这表示追加
import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class AppendOutputStreamDemo { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 OutputStream out = null; // 声明字节输出流 out = new FileOutputStream(file, true); // 通过子类实例化,表示追加 String str = "hello world \r\n"; // 要输出的信息,“\r\n”表示换行 byte b[] = str.getBytes(); // 将String变为byte数组 out.write(b); // 写入数据 out.close(); // 关闭 } }
3.2 ,InputStream
字节输入流 也是一个抽象类。FileInputStream 是子类实例化
方法: 将内容读到字节数组中 public int read(byte[] b) throws TOException
每次住一个数据:public abtract int read() throws IOException
import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class InputStreamDemo01 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 InputStream input = null; // 字节输入流 input = new FileInputStream(file);// 通过子类进行实例化操作 byte b[] = new byte[1024];// 开辟空间接收读取的内容 int len = input.read(b); // 将内容读入到byte数组中 System.out.println(new String(b, 0, len)); // 输出内容 input.close(); // 关闭 } }
以上读取方式 有一个问题 就是会受到开辟控件的限制,如果动态开辟数组空间采用read()方法一个一个的读取。
import java.io.File; import java.io.FileInputStream; import java.io.InputStream; public class InputStreamDemo02 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 InputStream input = null; // 字节输入流 input = new FileInputStream(file);// 通过子类进行实例化操作 byte b[] = new byte[(int)file.length()];// 开辟空间接收读取的内容 for(int i=0;i<b.length;i++){ b[i] = (byte)input.read() ; // 一个个的读取数据 } System.out.println(new String(b)); // 输出内容,直接转换 input.close(); // 关闭 } }
4,字符流
字符流与字节流不同就在于使用的char数组 字符流是两个字节两个字节的拿数据对于存取汉字特别方便
4.1 Reader 抽象类 实例化子类是FileReader
方法:读取一组字节 public int read(char[] cbuf) throws IOException
读取一个个字符 public int read() throws IOException
import java.io.File; import java.io.FileReader; import java.io.Reader; public class ReaderDemo01 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 Reader input = null; // 字符输入流 input = new FileReader(file);// 通过子类进行实例化操作 char b[] = new char[1024];// 开辟空间接收读取的内容 int len = input.read(b); // 将内容读入到byte数组中 System.out.println(new String(b, 0, len)); // 输出内容 input.close(); // 关闭 } }
以上完成了资格字符的输入流,那么当然也可以通过循环的方式,一个一个的进行读取操作。
import java.io.File; import java.io.FileReader; import java.io.Reader; public class ReaderDemo02 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 Reader input = null; // 字节输入流 input = new FileReader(file);// 通过子类进行实例化操作 char b[] = new char[(int)file.length()];// 开辟空间接收读取的内容 for(int i=0;i<b.length;i++){ b[i] = (char)input.read() ; // 一个个的读取数据 } System.out.println(new String(b)); // 输出内容,直接转换 input.close(); // 关闭 } }
5字节流与字符流的区别
例1
import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; public class OutputStreamDemo01 { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 OutputStream out = null; // 声明字节输出流 out = new FileOutputStream(file); // 通过子类实例化 String str = "hello world"; // 要输出的信息 byte b[] = str.getBytes(); // 将String变为byte数组 out.write(b); // 写入数据 } }
以上并没有关闭操作 发现可以输出
import java.io.File; import java.io.FileWriter; import java.io.Writer; public class WriterDemo { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 Writer out = null; // 声明字符输出流 out = new FileWriter(file); // 通过子类实例化 String str = "hello world"; // 要输出的信息 out.write(str); // 写入数据 } }
发现并没有输出 但是Writer 有一个方法flush()
import java.io.File; import java.io.FileWriter; import java.io.Writer; public class WriterDemo { public static void main(String[] args) throws Exception { File file = new File("d:" + File.separator + "demo.txt"); // 要操作的文件 Writer out = null; // 声明字符输出流 out = new FileWriter(file); // 通过子类实例化 String str = "hello world"; // 要输出的信息 out.write(str); // 写入数据 out.flush(); // 刷新 } }
实际来讲,最早的造作中并没有刷新,因为使用了关闭 关闭会强制刷新 刷新的是缓冲区 (内存)
结论:字节流---->
字符流---->缓冲区--->文件
综合来讲,在传输或者硬盘上保存的内容都是以字节的形式存在的。但是操作中文 字符流更好使。