一:基本概念:

i:input输入(读取)
o:output输出(写入)
流:数据(字符,字节)。1个字符=2个字节,一个字节=8个二进制位。
输入:把硬盘中的数据,读取到内存中使用。
输出:把内存中的数据,写入硬盘中保存。
IO流分类:字符输入流(Reader),字符输出流(Writer),字节输入流(InputStream),字节输出流(OutputStream)。

二:File类的使用

(1)基础:

java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关。
File能新建、删除、重命名文件和目录,但File不能访问访问文件内容本身。如果需要访问文件内容本身,则需要使用输入/输出流。
想要在JAVA程序中表示一个真实存在的文件或目录,那么必须有一个File对象,但是JAVA程序中的一个File对象,可能没有一个真实存在的文件或目录。
File对象可以作为参数传递给流的构造器。

(2)File类的常用构造器

  1. import java.io.File;
  2. /**
  3. * File类的使用
  4. *
  5. * 1.File类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
  6. * 2.File类声明在java.io包下
  7. * 3.File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,
  8. * 并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用IO流来完成。
  9. * 4.后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的“终点”。
  10. */
  11. /**
  12. * File类的常用构造器
  13. *
  14. * 1.public File(String pathname);
  15. * 以pathname为路径创建File对象, 可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
  16. * 绝对路径:是一个固定的路径,从盘符开始。
  17. * 相对路径:是相对于某个位置开始。
  18. * 2.public File(String parent,String child);
  19. * 以parent为父路径,child为子路径创建File对象。
  20. * 3.public File(File parent,String child);
  21. * 根据一个父File对象和文件路径创建File对象。
  22. */
  23. public class FileTest {
  24. public static void main(String[] args) {
  25. //构造器1
  26. File file1 = new File("hello.txt");//相对于当前module
  27. File file2 = new File("D:\\hgk111\\abc.txt");
  28. //构造器2
  29. File file3 = new File("D:\\hgk1","aaa");
  30. //构造器3
  31. File file4 = new File(file3,"bbb.txt");
  32. }
  33. }

(3)File类中的常用方法

  1. /**
  2. * 一:File类的获取功能
  3. * 1.public String getAbsolutePath();获取绝对路径
  4. * 2.public String getPath();获取路径
  5. * 3.public String getName();获取名称
  6. * 4.public String getParent();获取上层文件目录路径,若无,返回null
  7. * 5.public long length();获取文件长度(即字节数)。不能获取目录的长度
  8. * 6.public long lastModified();获取最后一次的修改时间,毫秒值
  9. * 7.public String[] list();获取指定目录下的所有文件或者文件目录的名称数组
  10. * 8.public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组
  11. * 二:File类的重命名功能
  12. * public boolean renameTo(File dest):把文件重命名为指定的文件路径.
  13. * 例如,file1.renameTo(file2)
  14. * 要想保证返回true,需要保证file1在硬盘中是存在的,且file2不能在硬盘中存在。
  15. * 三:File类的判断功能
  16. * 1.public boolean isDirectory();判断是否是文件目录
  17. * 2.public boolean isFile();判断是否是文件
  18. * 3.public boolean exists();判断是否存在
  19. * 4.public boolean canRead();判断是否可读
  20. * 5.public boolean canWrite();判断是否可写
  21. * 6.public boolean isHidden();判断是否隐藏
  22. */
  1. public boolean createNewFile()://真正的在硬盘中创建文件。若文件存在,则不创建,返回false。
  2. public boolean mkdirs()://创建文件目录。如果此文件目录存在,就不创建了。如果上层文件目录不存在,也不创建了。
  3. public boolean mkdirs()://创建文件目录。如果上层文件目录不存在,一并创建。
  4. 创建注意事项:如果创建文件或者文件目录没有写盘符,那么,默认在项目路径下。
  5. public boolean delete()://删除文件或者文件夹
  6. 删除注意事项:java中的删除不走回收站。要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录。

三:IO流原理及流的分类

(1)原理:

  1. I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件、网络通讯等。
  2. JAVA程序中,对于数据的输入/输出操作以“流(Stream)”的方式进行。
  3. java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过标准的方法输入或输出数据。
  4. 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  5. 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中。

    (2)流的分类

  6. 按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)

  7. 按数据流的流向不同分为:输入流、输出流
  8. 按流的角色不同分为:节点流、处理流

    (3)流的体系结构

    1. 抽象基类 节点流(或文件流) 缓冲流(处理流)
    2. InputStream FileInputStream BufferedInputStream
    3. OutputStream FileOutputStream BufferedOutputStream
    4. Reader FileReader BufferedReader
    5. Writer FileWriter BufferedWriter

四:节点流(或文件流)

(1)FileReader读入数据的基本操作

  1. /**
  2. * 将io下的hello.txt文件内容读入程序中,并输出到控制台
  3. * 1.read():返回读入的一个字符,如果达到文件末尾,返回-1.
  4. * 2.为了保证流资源一定可以执行关闭操作,需要执行try-catch-finally处理。
  5. * 3.读入的文件一定要存在,否在就会报“文件不存在”异常。
  6. */
  7. public static void test(){
  8. FileReader fr = null;
  9. try {
  10. //1.实例化File类对象,指明要操作的文件
  11. File file = new File("D:\\hello.txt");
  12. //2.提供具体的流
  13. fr = new FileReader(file);
  14. //3.数据的读入
  15. //3.1--read():返回读入的一个字符,如果达到文件末尾,返回-1.
  16. /* int data;
  17. while ((data=fr.read()) != -1){
  18. System.out.print((char) data);
  19. }*/
  20. //3.2--对read()操作升级:使用read的重载方法
  21. char[] cbuf = new char[1024];//字符数组
  22. //byte bytes = new byte[1024];//字节数组
  23. int len;
  24. //read(char[] cbuf):返回每次读入到cbuf数组中的字符的个数,如果达到文件末尾,返回-1.
  25. while((len = fr.read(cbuf)) != -1){
  26. System.out.println(new String(cbuf,0,cbuf.length));
  27. }
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. }finally {
  31. //4.关闭流
  32. try {
  33. //以防File并没有被实例化
  34. if (fr != null){
  35. fr.close();
  36. }
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }

(2)FileWriter写出数据的操作

  1. /**
  2. * 从内存中写出数据到硬盘的文件里
  3. * 说明:
  4. * 1.如果文件不存在,在输出的过程中,会自动创建此文件。
  5. * File对应的硬盘文件如果存在,
  6. * 如果流使用的构造器是:FileWriter(file,false)/FileWriter(file),对原有文件的进行覆盖
  7. * 如果流使用的构造器是:FileWriter(file,true):不会对原有文件覆盖,而是在原有的基础上追写
  8. */
  9. public static void testFileWriter() {
  10. //1.提供File类的对象,指明写到的文件
  11. FileWriter fw = null;
  12. try {
  13. File file = new File("hello1.txt");
  14. //2.提供FileWriter的对象,用于数据的写出
  15. fw = new FileWriter(file);
  16. //3.写出的操作
  17. fw.write("I hava a Dream!!!\n");
  18. fw.write("我有一个梦想!!!");
  19. } catch (IOException e) {
  20. e.printStackTrace();
  21. } finally {
  22. //4.流资源的关闭
  23. if (fw!=null){
  24. try {
  25. fw.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. }
  31. }

(3)使用FileReader和FileWriter实现文本复制

  1. public static void testFileReaderFileWriter() {
  2. FileReader fr = null;
  3. FileWriter fw = null;
  4. try {
  5. //1.创建File对象,指明读入和写出的对象
  6. File file1 = new File("hello1.txt");
  7. File file2 = new File("hello2.txt");
  8. //2.创建输入流和输出流对象
  9. fr = new FileReader(file1);
  10. fw = new FileWriter(file2, true);//在原文件后面追加续写
  11. //3.数据的读入和写出操作
  12. char[] chars = new char[1024];
  13. int len;
  14. while ((len = fr.read(chars)) != -1) {
  15. //每次写出len个字符
  16. fw.write(chars, 0, len);
  17. }
  18. }catch (IOException e){
  19. e.printStackTrace();
  20. }finally {
  21. //4.关闭流资源
  22. try {
  23. if (fw != null){
  24. fw.close();
  25. }
  26. }catch (IOException e){
  27. e.printStackTrace();
  28. }
  29. try {
  30. if (fr != null){
  31. fr.close();
  32. }
  33. }catch (IOException e){
  34. e.printStackTrace();
  35. }
  36. }
  37. }

五:缓冲流

  1. /**
  2. * 案例:使用字节缓冲流实现非文本文件的复制.
  3. * 缓冲流的作用
  4. * 1.提高流的读取、写入的速度
  5. * 提高读写速度的原因:内部提供了一个缓冲区。
  6. * 2.处理流:就是“套接”在已有的流的基础之上。
  7. */
  8. public static void BufferedStreamTest(){
  9. BufferedInputStream bis = null;
  10. BufferedOutputStream bos = null;
  11. try {
  12. //1.创建File对象,指明读入和写出的对象
  13. File file1 = new File("D:\\测试\\小说.zip");
  14. File file2 = new File("D:\\测试\\小小说1.zip");
  15. //2.造流
  16. //2.1:创建字节流
  17. FileInputStream is = new FileInputStream(file1);
  18. FileOutputStream os = new FileOutputStream(file2);
  19. //2.2:创建缓冲流
  20. bis = new BufferedInputStream(is);
  21. bos = new BufferedOutputStream(os);
  22. //3.数据的读入和写出操作
  23. byte[] bytes = new byte[1024];
  24. int len;
  25. while ((len = bis.read(bytes)) != -1) {
  26. //每次写出len个字符
  27. bos.write(bytes, 0, len);
  28. }
  29. }catch (IOException e){
  30. e.printStackTrace();
  31. }finally {
  32. //4.关闭流资源
  33. //要求:先关闭外层的流,再关闭内层的流
  34. //说明:关闭外层流的同时,内层流也会自动的进行关闭,因此关于内层流的关闭,可以省略
  35. try {
  36. if (bos != null){
  37. bos.close();
  38. }
  39. }catch (IOException e){
  40. e.printStackTrace();
  41. }
  42. try {
  43. if (bis != null){
  44. bis.close();
  45. }
  46. }catch (IOException e){
  47. e.printStackTrace();
  48. }
  49. }
  50. }
  1. /**
  2. * 案例:使用字符缓冲流实现文本文件的复制.
  3. */
  4. public static void BufferedReaderWriterTest(){
  5. BufferedReader br = null;
  6. BufferedWriter bw = null;
  7. try {
  8. //1.造流
  9. br = new BufferedReader(new FileReader(new File("D:\\测试\\1.txt")));
  10. bw = new BufferedWriter(new FileWriter(new File("D:\\测试\\3.txt")));
  11. //2.数据的读入和写出操作
  12. //方式一:使用char[]数组
  13. /*char[] chars = new char[1024];
  14. int len;
  15. while ((len = br.read(chars)) != -1) {
  16. //每次写出len个字符
  17. bw.write(chars, 0, len);
  18. }*/
  19. //方式二:使用String
  20. String data;
  21. //readLine():字符缓冲流中的方法,一次读取一行
  22. while ((data=br.readLine())!=null){
  23. bw.write(data+"\n");//data中不包含换行符
  24. bw.newLine();//提供换行的操作
  25. }
  26. }catch (IOException e){
  27. e.printStackTrace();
  28. }finally {
  29. //3.关闭资源
  30. try {
  31. if (br != null){
  32. br.close();
  33. }
  34. }catch (IOException e){
  35. e.printStackTrace();
  36. }
  37. try {
  38. if (bw != null){
  39. bw.close();
  40. }
  41. }catch (IOException e){
  42. e.printStackTrace();
  43. }
  44. }
  45. }

六:转换流

字节流中的数据都是字符时,转成字符流操作更高效。
很多时候我们使用转换流来处理文件乱码问题,实现编码和解码的功能。

  1. /**
  2. * 处理流之二:转换流(属于字符流)
  3. * 1.作用:
  4. * 转换流提供了在字节流和字符流之间的转换。
  5. * 2.类型:
  6. * InputStreamReader:将InputStream转换为Reader(解码)
  7. * OutputStreamWriter:将Writer转换为OutputStream(编码)
  8. * 3.解码:字节、字节数组 ---> 字符数组、字符串
  9. * 编码:字符数组、字符串 ---> 字节、字节数组
  10. * 4.字符集:
  11. * 编码表的由来:计算机之只能识别二进制数据,早期由来是电信号,为了方便应用计算机,让它可以识别各个国家的
  12. * 的文字。就将各个国家的文字用数字来表示。并一一对应,形成一张表,这就是编码表。
  13. * 常见的编码表:
  14. * ASCLL:美国标准信息交换码,用一个字节的7位可以表示。
  15. * GBK:中国的中文编码表,最多两个字节编码所有字符
  16. * UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。
  17. *
  18. */
  19. public class InputStreamReaderTest {
  20. public static void main(String[] args) {
  21. test1();
  22. }
  23. public static void test1(){
  24. InputStreamReader isr = null;
  25. OutputStreamWriter osw = null;
  26. try {
  27. FileInputStream fis = new FileInputStream("D:\\测试\\故事.txt");
  28. isr = new InputStreamReader(fis,"utf-8");//如果第二个参数不写,则使用系统默认的字符集,utf-8.
  29. FileOutputStream fos = new FileOutputStream("新的故事.txt");
  30. osw = new OutputStreamWriter(fos,"gbk");
  31. //根据什么选择用什么字符集解码?这要根据当初文本文件当初存的时候用的什么字符集编码。
  32. //读、写操作
  33. char[] chars = new char[200];
  34. int len;
  35. while ((len=isr.read(chars))!=-1){
  36. System.out.println(new String(chars,0,len));
  37. osw.write(chars,0,len);
  38. }
  39. } catch (IOException e) {
  40. e.printStackTrace();
  41. } finally {
  42. if (isr != null){
  43. try {
  44. isr.close();
  45. } catch (IOException e) {
  46. e.printStackTrace();
  47. }
  48. }
  49. if (osw != null){
  50. try {
  51. osw.close();
  52. } catch (IOException e) {
  53. e.printStackTrace();
  54. }
  55. }
  56. }
  57. }

七:标准输入、输出流

  1. /**
  2. * 标准的输入、输出流:
  3. * 1:
  4. * System.in:标准的输入流,默认从键盘输入
  5. * System.out:标准的输出流,默认从控制台输出
  6. * 2:
  7. * System类的setIn(InputStream is)/setOut(OutputStream os)方式重新指定输入和输出的流。
  8. * 3:练习
  9. * 从键盘输入字符串,要求将读取到的整行字符串转换成大写输出,然后继续进行输入操作,直到输入“e"或者"exit"时,退出程序。
  10. * 方式一:使用Scanner实现,调用next()返回一个字符串。
  11. * 方式二:使用System.in实现。
  12. * System.in --> 转换流 ——> BufferedReader的readLine().
  13. */
  14. public static void test1(){
  15. BufferedReader br = null;
  16. try {
  17. InputStreamReader isr = new InputStreamReader(System.in);
  18. br = new BufferedReader(isr);
  19. while (true){
  20. System.out.println("请输入字符串:");
  21. String data = br.readLine();
  22. if ("e".equalsIgnoreCase(data) || "exit".equalsIgnoreCase(data)){
  23. System.out.println("程序结束!");
  24. break;
  25. }
  26. String s = data.toUpperCase();
  27. System.out.println(s);
  28. }
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. } finally {
  32. try {
  33. if (br != null){
  34. br.close();
  35. }
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }

八:打印流

  1. /**
  2. * 打印流:
  3. * 实现将基本数据类型的数据格式转化为字符串输出
  4. * 打印流:PrintStream 和 PrintWriter
  5. * 提供了一系列重载的print()和println()方法,用于多种数据类型的输出。
  6. */
  7. System.SetOut();重新指定一个位置,打印到那里

九:数据流

  1. /**
  2. * 数据流:
  3. * 1.DataInputStream和DataOutputStream
  4. * 2.作用:用于读取或写出基本数据类型的变量或字符串
  5. * 3.注意点:读取不同类型的数据要与当初写入文件时保存的数据的顺序一致!!
  6. *
  7. */
  8. public static void test1(){
  9. DataOutputStream dos = null;
  10. DataInputStream dis = null;
  11. try {
  12. dos = new DataOutputStream(new FileOutputStream("D:\\abc.txt"));
  13. dis = new DataInputStream(new FileInputStream("D:\\abc.txt"));
  14. //写数据
  15. dos.writeUTF("哈哈哈");
  16. dos.flush();
  17. dos.writeInt(100);
  18. dos.flush();
  19. dos.writeBoolean(true);
  20. dos.flush();
  21. //读数据
  22. String name = dis.readUTF();
  23. int age = dis.readInt();
  24. boolean isMale = dis.readBoolean();
  25. System.out.println("name=" +name);
  26. System.out.println("age=" +age);
  27. System.out.println("isMale=" +isMale);
  28. } catch (IOException e) {
  29. e.printStackTrace();
  30. } finally {
  31. try {
  32. if (dos!=null){
  33. dos.close();
  34. }
  35. } catch (IOException e) {
  36. e.printStackTrace();
  37. }
  38. }
  39. try {
  40. if (dis!=null){
  41. dis.close();
  42. }
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }

十:对象流

  1. /**
  2. * 对象流:ObjectInputStream;ObjectOutputStream
  3. * 1.作用:用于存储和读取基本数据类型数据或对象的处理流,它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
  4. * 2.注意:ObjectInputStream和ObjectOutputStream不能序列化static和transient修饰的成员变量。
  5. * 3.对象需要满足什么条件,才能被序列化?
  6. * (1)需要实现接口:Serializable接口。
  7. * (2)需要提供一个全局常量:serialVersionUID
  8. * 如:public static final long serialVersionUID=478529578257275L;
  9. * (3)除了当前的要序列化的类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。
  10. * 默认情况下,基本数据类型也是可序列化的。
  11. * 4.序列化机制(重点)
  12. * 对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,
  13. 或通过网络将这种二进制流传输到另一个网络节点。当其他程序获取了这种二进制流,就可以恢复成原来的Java对象。
  14. */
  15. public class ObjectInOutputStream {
  16. public static void main(String[] args) {
  17. test1();
  18. test2();
  19. }
  20. /**
  21. * 序列化过程:用ObjectOutputStream类保存基本数据类型或对象的机制。
  22. * 换句话说,就是将内存中的java对象保存到磁盘中或通过网络传输出去。
  23. */
  24. public static void test1(){
  25. ObjectOutputStream oos = null;
  26. try {
  27. oos = new ObjectOutputStream(new FileOutputStream("D:\\ccc.txt"));
  28. oos.writeObject(new String("给我一首歌的时间。"));
  29. oos.flush();//刷新操作
  30. } catch (IOException e) {
  31. e.printStackTrace();
  32. } finally {
  33. if (oos != null){
  34. try {
  35. oos.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }
  42. /**
  43. * 反序列化:用ObjectInputStream类读取基本数据或对象的机制。
  44. * 换句话说,就是将磁盘文件中的对象还原为内存中的一个java对象。
  45. */
  46. public static void test2(){
  47. ObjectInputStream ois = null;
  48. try {
  49. ois = new ObjectInputStream(new FileInputStream("D:\\ccc.txt"));
  50. Object o = ois.readObject();
  51. String str = (String)o;
  52. System.out.println(str);
  53. } catch (IOException | ClassNotFoundException e) {
  54. e.printStackTrace();
  55. } finally {
  56. if (ois != null){
  57. try {
  58. ois.close();
  59. } catch (IOException e) {
  60. e.printStackTrace();
  61. }
  62. }
  63. }
  64. }
  65. }