Java IO(java io详解)

  本篇文章为你整理了Java IO(java io详解)的详细内容,包含有java io面试题 java io详解 javaio流分为几种 java io和nio的区别 Java IO,希望能帮助你了解 Java IO。

  可以使用File类进行文件的操作。

  可以使用字符流或字节流操作文件内容,并区分出字符流与字节流的区别。

  掌握内存操作输入、输出流的使用。

  了解线程通讯流--管道流的使用。

  掌握System类对IO的三个支持:System.out、System.err、System.in。

  可以使用打印流方便的打印输出的内容,并可以使用Java新特性格式化输出。

  可以使用BufferedReader类读取缓冲区中的内容。

  了解Java提供的输入工具类Scanner类的使用。

  掌握数据操作流DataInputStream和DataOutputStream类的使用。

  可以使用SequenceInputStream合并两个文件的内容。

  可以使用压缩流完成ZIP文件格式的压缩。

  了解回退流(PushbackInputStream)类的作用及操作原理。

  了解字符的主要编码类型及乱码产生的原因。

  掌握对象序列化的作用以及Serializable接口、Externalizable接口、transient关键字的使用。

  java.io包中最重要的5个类和1个接口:

  5个类:File、OutputStream、InputStream、Writer、Reader

  1个接口:Serializable

  IO操作类:
 

  1.File类

  1.基本介绍

  File类是操作文件的类。

  说明:

  File类是io包中唯一一个与文件本身有关的类。File类可以进行文件的创建、删除等操作。

  File类中的常用方法:

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

   File file = new File(path);

   try{

  // 根据给定的路径创建新文件

   file.createNewFile();

   }catch (IOException e){

   e.printStackTrace();

  

 

 

  注意:在操作文件时一定要使用File.separator表示分隔符。

  因为在程序开发中往往是在Windows下开发好之后上传到Linux中。

  2.删除一个指定的文件

  使用delete()方法

  案例:删除文件

  

import java.io.File;

 

  import java.io.IOException;

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

   File file = new File(path);

   file.delete(); //删除文件

  

 

  注意:正常的逻辑应该是在删除文件前先判断文件是否存在,如果存在则删除。

  判断文件是否存在使用 exists()方法。

  改进代码:

  

import java.io.File;

 

  import java.io.IOException;

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

   File file = new File(path);

   if (file.exists()){

   file.delete(); //删除文件

  

 

  3.创建一个文件夹

  使用mkdir()方法

  案例:创建一个文件夹

  

import java.io.File;

 

  import java.io.IOException;

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test";

   File file = new File(path);

   file.mkdir(); //创建文件夹

  

 

  4.列出指定目录的全部文件

  有两种方法:

  public String[] list():列出全部名称,返回一个字符串数组。

  public File[] listFiles():列出完整的路径,返回一个File对象数组。

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO";

   File file = new File(path);

   String[] list = file.list();

   for (int i = 0; i list.length; i++) {

   System.out.println(list[i]);

  

 

 

  输出:

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO";

   File file = new File(path);

   File[] files = file.listFiles();

   for (int i = 0; i files.length; i++) {

   System.out.println(files[i]);

  

 

 

  输出:

  5.判断一个给定的路径是否是目录

  使用isDirectory()方法。

  案例:判断一个给定的路径是否是目录

  

import java.io.File;

 

  import java.io.IOException;

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO";

   File file = new File(path);

   if (file.isDirectory()){

   System.out.println(file.getPath() + "路径是目录。");

   }else {

   System.out.println(file.getPath() + "路径不是目录。");

  

 

  6.列出指定目录的全部内容

  要求列出全部内容,因为给定的目录下可能还有子文件夹,所以需要递归遍历。

  

import java.io.File;

 

  import java.io.IOException;

  
// 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO";

   File file = new File(path);

   print(file);

   public static void print(File file){

   if (file != null){

   if (file.isDirectory()){

   File[] files = file.listFiles();

   if (files != null){

   for (int i = 0; i files.length; i++) {

   print(files[i]);

   }else {

   System.out.println(file);

  

 

  2.RandomAccessFile类

  随机读写流

  作用:

  对文件的内容进行操作。这个类属于随机读取类,可以随机的读取一个文件中指定位置的数据。

  File类只是针对文件本身进行操作。

  注意:如果要实现随机读取,需要保证每个数据的长度一致。

  RandomAccessFile类的常用操作方法:

  
注意:如果使用rw方式声明RandomAccessFile对象时,要写入的文件不存在,系统将自动进行创建。

  1.使用RandomAccessFile类写入数据

  案例:写入一下三个数据:

  zhangsan 30

  lisi 31

  wangwu 32

  为了保证可以进行随机读取,所有写入的名字都是8个字节,写入的数字是固定的4个字节。

  

import java.io.File;

 

  import java.io.IOException;

  import java.io.RandomAccessFile;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

   File file = new File(path);

  // 声明一个RandomAccessFile对象

   RandomAccessFile rdf = null;

  // 以读写的方式打开文件

   rdf = new RandomAccessFile(file,"rw");

   String name = null;

   int age = 0;

   name = "zhangsan";

   age = 30;

   rdf.writeBytes(name);

   rdf.writeInt(age);

   name = "lisi ";

   age = 31;

   rdf.writeBytes(name);

   rdf.writeInt(age);

   name = "wangwu ";

   age = 32;

   rdf.writeBytes(name);

   rdf.writeInt(age);

   rdf.close(); //关闭文件

  

 

  可以发现年龄age是不显示的

  2.使用RandomAccessFile类读取数据

  读取时直接使用r的模式即可,以只读的方式打开文件。

  读取时所有的字符串只能按照byte数组的方式读取出来,而且所有的长度是8位。

  随机读取

  

import java.io.File;

 

  import java.io.RandomAccessFile;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

   File file = new File(path);

  // 声明一个RandomAccessFile对象

   RandomAccessFile rdf = null;

  // 以只读的方式打开文件

   rdf = new RandomAccessFile(file,"r");

   String name = null;

   int age = 0;

  // 准备空间读取姓名

   byte[] bytes = new byte[8];

   rdf.skipBytes(12);

   for (int i = 0; i bytes.length; i++) {

   bytes[i] = rdf.readByte(); //循环读取前8个内容

   name = new String(bytes); //将读取出来的byte数组变为String

   age = rdf.readInt(); //读取数字

   System.out.println("第二个人的信息-- 姓名:" + name + ";年龄" + age);

   rdf.seek(0); //指针回到文件的开头

   bytes = new byte[8]; //准备空间读取姓名

   for (int i = 0; i bytes.length; i++) {

   bytes[i] = rdf.readByte();

   name = new String(bytes);

   age = rdf.readInt();

   System.out.println("第一个人的信息-- 姓名:" + name + ";年龄" + age);

   rdf.skipBytes(12);

   bytes = new byte[8]; //准备空间读取姓名

   for (int i = 0; i bytes.length; i++) {

   bytes[i] = rdf.readByte();

   name = new String(bytes);

   age = rdf.readInt();

   System.out.println("第三个人的信息-- 姓名:" + name + ";年龄" + age);

   rdf.close(); //关闭文件

  

 

  输出:
 

  程序中可以随机跳过12位读取信息,也可以回到开始点重新读取。

  3.字节流与字符流基本操作

  介绍:

  在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据时要使用输入流读取数据,而当程序需要将一些数据保存起来时,就要使用输出流。

  java.io包中流操作主要有:字节流、字符流两大类,两类都有输入、输出操作。

  输出数据主要使用 OutputStream类完成。

  输入数据主要使用 InputStream类完成。

  
1.字节流

  字节流主要操作byte类型数据,以byte数组为准,主要操作类是:OutputStream类和InputStream类。

  1.字节输入流:OutputStream

  OutputStream是整个IO包中字节输出流的最大父类

  定义: public abstract class OutputStream implements Closeable, Flushable

  注意:OutputStream 类是一个抽象类,要使用这个类就必须先通过子类实例化对象。如果操作的是一个文件可以使用FileOutputStream类。然后向上转型,就可以为OutputStream类实例化。

  OutputStream类中的主要操作方法:

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   OutputStream out = null; //准备好一个输出流对象

   out = new FileOutputStream(file); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "Hello World!!!"; //准备一个字符串

   byte[] bytes = str.getBytes(); //只能输出byte数组,所以将字符串变为byte数组

   out.write(bytes); //将内容输出,保存文件

  // 第四步:关闭流操作

   out.close();

  

 

 

  注意:以上程序在实例化、写、关闭时都会有异常发生,为了方便可以直接在主方法上使用throws。

  当文件不存在时,会进行自动创建。

  以上是通过将一个字符串转换成byte数组,然后将byte数组直接写入到文件中,当然也可以通过循环把每一个字节一个个地写入到文件之中。

  使用write(int t)的方式写入文件内容。

  

import java.io.File;

 

  import java.io.FileOutputStream;

  import java.io.OutputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   OutputStream out = null; //准备好一个输出流对象

   out = new FileOutputStream(file); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "Hello World!!!"; //准备一个字符串

   byte[] bytes = str.getBytes(); //只能输出byte数组,所以将字符串变为byte数组

   for (int i = 0; i bytes.length; i++) {

   out.write(bytes[i]); //将内容输出,保存文件

  // 第四步:关闭流操作

   out.close();

  

 

  2.追加新内容

  之前的操作如果重新执行会覆盖文件中已有的内容。

  用法:

  可以使用FileOutputStream类中的另外一个构造方法进行实例化:
 

  public FileOutputStream(String name,boolean append)throws FileNotFoundException

  将append的值设置为true,则表示在文件的末尾追加内容。

  

import java.io.File;

 

  import java.io.FileOutputStream;

  import java.io.OutputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   OutputStream out = null; //准备好一个输出流对象

   out = new FileOutputStream(file,true); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "Hello World!!!"; //准备一个字符串

   byte[] bytes = str.getBytes(); //只能输出byte数组,所以将字符串变为byte数组

   for (int i = 0; i bytes.length; i++) {

   out.write(bytes[i]); //将内容输出,保存文件

  // 第四步:关闭流操作

   out.close();

  

 

  如何增加换行?

  使用\r\n增加换行

  3.字节输入流InputStream

  作用:

  从文件中把内容读取出来。

  InputStream类定义:

  public abstract class InputStream implements Closeable

  从文件中读取:

  可以使用InputStream的子类FileIuputStream类。

  FileIuputStream类的构造方法

  public FileInputStream(File file) throws FileNotFoundException

  InputStream类中的常用方法:

  
public abstract int read() throws IOException 方法的详解:

  一是这个方法的返回值是int类型;二是在这个方法每次从数据源中读取一个byte并返回.很多初次接触Java的读者在看到这里时都会产生下面的疑问,就是这个方法读取的byte是如何以int的形式返回的。在计算机中,所有的文件都是以二进制的形式存储的,换句话说,每个文件不管是什么类型,在计算机中的形式都是一串0和1。而read()方法在读的时候是每次读取8个二进制位,这8个0或1就是我们所谓的一个byte(字节)。read()这个方法完成的事情就是从数据源中读取8个二进制位,并将这8个0或1转换成十进制的整数,然后将其返回。

  
public int read(byte b[]) throws IOException方法详解:
 

  这个方法使用一个byte的数组作为一个缓冲区,每次从数据源中读取和缓冲区大小(二进制位)相同的数据并将其存在缓冲区中。当然byte数组中存放的仍然是0-255的整数,将二进制转换为十进制这个过程仍然是read方法实现的。
 

   需要注意的是,虽然我们可以指定缓冲区的大小,但是read方法在读取数据的时候仍然是按照字节来读取的。在utf-8等变长编码中,一个复杂字符(比如汉字)所占字节往往大于1,并且长度往往是不固定的。(参照UTF-8编码规则)按照字节读取数据会将字符割裂,这就导致我们在使用read(byte[] b)方法读取文件时,虽然指定了缓冲区的大小,但是仍然会出现乱码。

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   InputStream input = null; //准备好一个输入流对象

   input = new FileInputStream(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   byte[] bytes = new byte[1024]; //将所有内容读到此数组中

   input.read(bytes); //把内容取出,内容读到byte数组中

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(bytes));

  

 

 

  输出:

  出现的问题1:内容虽然读取出来了但是后面会有很多空格。这是因为开辟的byte数组的空间为1024,超出了文件的内容大小。

  解决方法1

  read()方法有一个返回值,此返回值表示向数组中写入了多少个数据。

  改进代码:

  

import java.io.File;

 

  import java.io.FileInputStream;

  import java.io.InputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   InputStream input = null; //准备好一个输入流对象

   input = new FileInputStream(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   byte[] bytes = new byte[1024]; //将所有内容读到此数组中

   int len = input.read(bytes); //把内容取出,内容读到byte数组中

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(bytes,0,len));

  

 

  new String(bytes,0,len))可以将byte数组中指定范围中的内容变成字符串。

  出现的问题2:如果文件的内容小的话,会造成很多空间的浪费。

  解决方法:根据文件的数据量来选择开辟空间的大小。使用 File类中的length()方法,此方法可以取得文件的大小。

  改进代码:开辟指定大小的byte数组。

  

import java.io.File;

 

  import java.io.FileInputStream;

  import java.io.InputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   InputStream input = null; //准备好一个输入流对象

   input = new FileInputStream(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   byte[] bytes = new byte[(int)file.length()]; //将所有内容读到此数组中,数组的大小由文件决定

   input.read(bytes); //把内容取出,内容读到byte数组中

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(bytes));

  

 

  也可以通过循环从文件中一个个地把内容读取出来,直接使用read()方法即可。

  使用read()通过循环读取

  

import java.io.File;

 

  import java.io.FileInputStream;

  import java.io.InputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   InputStream input = null; //准备好一个输入流对象

   input = new FileInputStream(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   byte[] bytes = new byte[(int)file.length()]; //将所有内容读到此数组中,数组的大小由文件决定

   for (int i = 0; i bytes.length; i++) {

   bytes[i] = (byte) input.read(); //把内容取出

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(bytes));

  

 

  注意: 以上都是已经知道了具体数组大小的情况下开展的,如果不知道要输入的内容有多大,可以通过判断是否读到文件末尾的方式来读取文件。

  

import java.io.File;

 

  import java.io.FileInputStream;

  import java.io.InputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   InputStream input = null; //准备好一个输入流对象

   input = new FileInputStream(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   int len = 0; //用于记录读取的数据个数

   byte[] bytes = new byte[1024]; //将所有内容读到此数组中

   int temp = 0; //接收读取的每一个内容

   while((temp = input.read()) != -1){

   //将每次读取的内容交给temp变量,如果temp的值不是-1,则表示文件没有读完

   bytes[len] = (byte) temp;

   len++;

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(bytes,0,len));

  

 

  文件读到末尾了,则返回的内容为-1

  2.字符流

  说明:

  在程序中一个字符等于两个字节,Java提供了Reader和Writer两个专门操作字符流的类。

  1.字符输出流Writer

  Writer类的定义:
 

  public abstract class Writer implements Appendable, Closeable, Flushable

  关于Appendable接口的说明:

  此接口定义如下:

  

public interface Appendable {

 

   Appendable append(CharSequence csq) throws IOException;

   Appendable append(CharSequence csq, int start, int end) throws IOException;

   Appendable append(char c) throws IOException;

  

 

  此接口表示的是:内容可以被追加,接收的参数是CharSequence,实际上String类就是实现了此接口,所以可以直接通过此接口的方法向输出流中追加内容。

  Writer是抽象类,如果是向文件中写入内容,可以使用FileWriter类。

  FileWriter类构造方法:

  public FileWriter(File file) throws IOException

  Writer类的常用方法:

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Writer out = null; //准备好一个输出流对象

   out = new FileWriter(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   String str = "Hello World!!!";

   out.write(str);

  // 第四步:关闭流操作

   out.close();

  

 

 

  优点:

  可以直接输出字符串,而不用将字符串变为byte数组之后在输出。

  2.使用FileWriter追加文件的内容

  使用FileWriter类中的构造方法:

  public FileWriter(String fileName, boolean append) throws IOException

  将append的值设置为true,表示追加。

  追加文件内容:

  

import java.io.File;

 

  import java.io.FileWriter;

  import java.io.Writer;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Writer out = null; //准备好一个输出流对象

   out = new FileWriter(file,true); //通过对象多态性进行实例化

  // 第三步:进行读操作

   String str = "Hello World!!!";

   out.write(str);

  // 第四步:关闭流操作

   out.close();

  

 

  3.字符输入流Reader

  Reader是使用字符的方式从文件中读取数据,Reader类定义如下:

  public abstract class Reader implements Readable, Closeable

  要是从文件中读取内容可以使用: FileReader类。

  FileReader类构造方法:

  public FileReader(File file) throws FileNotFoundException

  Reader类常用方法:

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Reader input = null; //准备好一个输入流对象

   input = new FileReader(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   char[] chars = new char[1024]; //所有的内容读到这个数组当中

   int len = input.read(chars);

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(chars,0,len));

  

 

 

  注意:如果不知道数据的长度,也可以使用循环的方式进行内容的读取。

  使用循环的方式读取内容

  

 

 

  import java.io.File;

  import java.io.FileReader;

  import java.io.Reader;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Reader input = null; //准备好一个输入流对象

   input = new FileReader(file); //通过对象多态性进行实例化

  // 第三步:进行读操作

   int len = 0;

   char[] chars = new char[1024]; //所有的内容读到这个数组当中

   int temp = 0;

   while ((temp = input.read()) != -1) {

   chars[len] = (char) temp;

   len++;

  // 第四步:关闭流操作

   input.close();

   System.out.println("内容为: " + new String(chars,0,len));

  

 

  3.字节流与字符流的区别

  字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区在操作文件。

  案例:使用字节流和字符流进行写文件操作,并且不关闭输出流。

  使用字节流,并且不关闭

  

 

 

  import java.io.File;

  import java.io.FileOutputStream;

  import java.io.OutputStream;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   OutputStream out = null; //准备好一个输出流对象

   out = new FileOutputStream(file); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "kangwei";

   byte[] bytes = str.getBytes();

   out.write(bytes);

  // 第四步:关闭流操作

  // out.close(); 此时没有关闭

  

 

  输出:

  此时没有关闭字节流操作,但是文件中存在了输出的内容,证明字节流是直接操作文件本身的。

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Writer out = null; //准备好一个输出流对象

   out = new FileWriter(file); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "kangwei";

   out.write(str);

  // 第四步:关闭流操作

  // out.close(); 此时没有关闭

  

 

 

  输出:

  程序运行后发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而在关闭字符流的时候会强制性的将缓冲区中的内容进行输出,但是如果字符流没有关闭,则缓冲区中的内容是无法输出的。

  注意:如果想在不关闭字符流的同时将内容输出,可以使用Writer类中的flush()方法。

  使用flush()方法

  

 

 

  import java.io.File;

  import java.io.FileWriter;

  import java.io.Writer;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Writer out = null; //准备好一个输出流对象

   out = new FileWriter(file); //通过对象多态性进行实例化

  // 第三步:进行写操作

   String str = "kangwei";

   out.write(str);

   out.flush(); //强制性清空缓冲区中的内容

  // 第四步:关闭流操作

  // out.close(); 此时没有关闭

  

 

  输出:

  
缓冲区可以简单的理解为一段内存区域。

  ​ 在某些情况下,如果一个程序频繁的操作一个资源(如文件或者数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。

  ​ 在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存中,所以使用了缓冲区暂存数据。

  
使用字节流好。

  ​ 所有的文件在硬盘或传输中都是以字节的方式进行的,包括图片等都是按照字节的方式存储的,而字符只在内存中才会形成,所以在开发中,字节流使用较广泛。

  4.转换流--OutputStreamWriter类与InputStreamReader类

  字节流--字符流的转换流

  OutputStreamWriter:是Writer的子类,将输出的字符流变为字节流,将一个字符流的输出对象变为字节流的输出对象。

  public OutputStreamWriter(OutputStream out)

  
InputStreamReader:是Reader的子类,将输入的字节流变为字符流,将一个字节流的输入对象变为字符流的输入对象。

  以文件操作为例:内存中的字符数据需要通过OutputStreamWriter变为字节流才能保存在文件中,读取时需要将读入的字节流通过InputStreamReader变为字符流。

  不管怎么操作,最终都是以字节的形式保存在文件中。

  案例1:将字节输出流变为字符输出流

  

 

 

  import java.io.*;

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Writer out = null; //准备好一个输出流对象

   out = new OutputStreamWriter(new FileOutputStream(file)); //字节流变为字符流

  // 第三步:进行写操作

   String str = "kangwei";

   out.write(str);

  // 第四步:关闭流操作

   out.close();

  

 

  
// 直接抛出异常,程序中可以不用在进行处理

   public static void main(String[] args)throws Exception {

  // 拼凑出可以符合操作系统的路径

   String path = "D:" + File.separator + "DLU" + File.separator + "studyNode" +

   File.separator + "java" + File.separator + "IO" + File.separator + "test.txt";

  // 第一步:使用File类找到一个文件

   File file = new File(path);

  // 第二步:通过子类实例化父类对象(使用流打开文件)

   Reader reader = null; //准备好一个输入流对象

   reader = new InputStreamReader(new FileInputStream(file)); //字节流变为字符流

  // 第三步:进行写操作

   char[] chars = new char[1024];

   int len = reader.read(chars);

  // 第四步:关闭流操作

   reader.close();

   System.out.println("内容: " + new String(chars,0,len));

  

 

 

  FileWriter和FileReader说明:

  从JDK文档中可以知道: FileOutputStream 是 OutputStream 的直接子类,FileInputStream 也是 InputStream 的直接子类,但是在字符流中文件的两个操作类有些特殊,FileWriter不是Writer的直接子类,而是InputStreamWriter的直接子类。 FileReader不是 Reader的直接子类,而是 InputStreamReader的直接子类。从这两个类的继承关系可以看出,不管使用的是字节流还是字符流实际上最终都是以字节的形式操作输入/输出流的。

  5.内存操作流

  前面所写的程序中的输出和输入都是从文件中来的,也可以将输入和输出的位置设置在内存上。此时就要使用ByteArrayInputStream和 ByteArrayOutputStream来完成内存的输入和输出。

  注意: 输入和输出都是针对于内存来说的。

  
 

  案例:使用内存操作流完成一个大写字母转换为小写字母的程序。

  

import java.io.*;

 

  public class Demo04 {

   public static void main(String[] args) {

   String str = "HELLOWORLD";

   ByteArrayInputStream bis = null; //声明一个内存的输入流

   ByteArrayOutputStream bos = null; //声明一个内存的输出流

   bis = new ByteArrayInputStream(str.getBytes()); //向内存中输入内容

   bos = new ByteArrayOutputStream(); //准备从ByteArrayInputStream中读取数据

   int temp = 0;

   while((temp = bis.read()) != -1){

   char c = (char) temp; //将读取的数字变为字符

   bos.write(Character.toLowerCase(c)); //将字符变为小写

   String newStr = bos.toString();

   try{

   bis.close();

   bos.close();

   }catch (IOException e){

   e.printStackTrace();

   System.out.println(newStr);

  

 

  以上全部的操作都是在内存中完成的。

  内存操作流的使用

  内存操作流一般在生成一些临时信息时才会使用,如果将这些临时信息保存在文件中,则代码执行完成后还需要删除这个临时文件,这就比较麻烦,这时使用内存操作流是最合适的。

  6.管道流

  作用:

  进行两个线程间的通信。

  管道输出流 PipedOutputStream

  管道输入流 PipedInputStream

  注意:如果要进行管道输。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: