FileInputStream和FileOutputStream

显然,这是两种“字节流”,FileInputStream是“文件字节输入流”,FileOutputStream是“文件字节输出流”

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis = new FileInputStream ("文件路径(相对或绝对路径)");
        /*
		FileInputStream类的构造方法可以传入一个File类引用或文件的路径
		这里在创建fis时,会抛出一个FileNotFoundException
		所以需要把这句话放进try catch中或在main方法一开始就throws掉
        */
    }
}

修改后的代码如下:

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis;
		
        /*
		FileInputStream类的构造方法可以传入一个File类引用或文件的路径
		这里在创建fis时,会抛出一个FileNotFoundException
		所以需要把这句话放进try catch中或在main方法一开始就throws掉
        */

		try
		{
			fis = new FileInputStream ("文件路径(相对或绝对路径)");
		}
		catch (FileNotFoundException e)
		{
			e.printStackTrack ();
		}
    }
}

接下来就要读文件

首先准备好一个文件,在里面存入“abcdef”

利用FileInputStream类中的read方法读取数据,会返回一个int类型的数据

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis = null;
		
        /*
		FileInputStream类的构造方法可以传入一个File类引用或文件的路径
		这里在创建fis时,会抛出一个FileNotFoundException
		所以需要把这句话放进try catch中或在main方法一开始就throws掉
        */

		try {
			fis = new FileInputStream ("文件路径(相对或绝对路径)");

			//读
			int i1 = fis.read (); //97
			int i2 = fis.read (); //98
			int i3 = fis.read (); //99
			int i4 = fis.read (); //100
			int i5 = fis.read (); //101
			int i6 = fis.read (); //102
			int i7 = fis.read (); //-1

			System.out.println (i1);
			System.out.println (i2);
			System.out.println (i3);
			System.out.println (i4);
			System.out.println (i5);
			System.out.println (i6);
			System.out.println (i7);

		} catch (FileNotFoundException e) {
			e.printStackTrace ();
		} catch (IOException e) {
            e.printStackTrace ();
        } finally {
            try {
                fis.close ();
            } catch (IOException e) {
                e.printStackTrace;
            }
        }
    }
}

因为read方法会抛出一个IOException,所以将这个异常捕获

read方法一次只读一个字节,英文字母刚好就是一个字节,而a对应的ASCII码是97,所以read返回了97~102的数字。

当文件被读取完时,read方法会返回-1,所以最后的i7是-1

每个流在用完之后都应该关闭,即执行fis.close ()方法,但是close方法会抛出一个IOException异常,故需要捕获。

 

虽然上面的程序可以将文件读完,但是需要提前知道文件的大小,所以利用文件读完后read方法返回-1,引入循环,代码如下:

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis = null;
		
		try {
			fis = new FileInputStream ("文件路径(相对或绝对路径)");
			
			//先将这种循环方法看懂,就更容易理解下面的循环
			/*while (true) {
				int temp = fis.read ();
				if (temp == -1) {
					break;
				}
				System.out.println (temp);
			}*/

			int temp = 0; // 设置temp,记录每次读取文件的返回值,若未读完,则不会返回-1,反之则返回-1
			while ((temp = fis.read ()) != -1) {
				System.out.println (temp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrack ();
		} finally {
			try {
				fis.close ();
			} catch (IOException e) {
				e.printStackTrace;
			}
		}
    }
}

这种方法虽然可以循环读取,但是一次只读一个字节,效率实在是低,而且不停地像硬盘进行读操作也很伤硬盘。

于是又有了下面的操作:

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis = null;
		
		try {
			fis = new FileInputStream ("文件路径(相对或绝对路径)");
			
			//准备一个byte数组
			byte[] bytes = new byte[3]; // 每次只读3个字节

			int i1 = fis.read (bytes); // 该方法与read()无参数方法不同,返回的是读取到的字节数,无参数read()方法返回的是读取到的字节的ASCII码

			System.out.println (new String (bytes)); // 将读取到的byte数组转换为String类型,是abc

			int i2 = fis.read (bytes); // 3
			System.out.println (new String (bytes)); // def
			
			int i3 = fis.read (bytes); // 1
			System.out.println (new String (bytes)); // gef

			int i3 = fis.read (bytes); // -1,与无参数的read()方法类似,当文件读取完后,该方法也会返回-1,后面也可以此来进行循环读取的判断条件
			System.out.println (new String (bytes)); // gef,文件中存储的是abcdefg,每次读三个字节,最后以此只剩下f,read在读取时并不会清空数组再读取,而是直接进行覆盖,所以得到的是gef

		} catch (FileNotFoundException e) {
			e.printStackTrack ();
		} finally {
			try {
				fis.close ();
			} catch (IOException e) {
				e.printStackTrace;
			}
		}
    }
}

这样就解决了效率低的问题,因为一次读取的文件大小,取决于byte数组的大小

下面代码完成循环读取:

public class FileInputStreamTest {

    public static void main (String[] args) {

        //创建文件字节输入流
        FileInputStream fis = null;
		
		try {
			fis = new FileInputStream ("文件路径(相对或绝对路径)");
			
			//准备一个byte数组
			byte[] bytes = new byte[3]; // 每次只读3个字节

			int temp = 0;
			while ((temp = fis.read (bytes)) != -1) {
				System.out.print (new String (bytes, 0, temp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrack ();
		} finally {
			try {
				fis.close ();
			} catch (IOException e) {
				e.printStackTrace;
			}
		}
    }
}

其中打印部分的代码,并不需要每次都打印byte数组的所有数据,就像上面的例子,最后以此只读取了一个g,如果全都打印的话,就会打出gef,显然是不合适的,所以调用String中带有偏移量参数和长度的构造方法,从下标为0的对象开始,打印读取到的字节数即temp个对象。

FileOutputStream与FileInputStream完全类似,只是FileOutputStream用的是write方法,且需要在关闭前调用flush方法,进行刷新,把流中剩余的字节强制写出来。

下面的代码是利用FileInputStream和FileOutputStream进行文件复制:

public class CopyTest {
	
	public static void main (String[] args) throws Exception {
		
		//创建流
		FileInputStream fis = new FileInputStream (原文件地址);
		FileOutputStream fos = new FileOutputStream (新文件地址);

		//边读边写
		byte[] bytes = new byte[1024]; // 每次读取1kb
		int temp = 0;

		whil ((temp = fis.read (bytes)) != -1) {
			fos.write (bytes, 0, temp);
		}

		//刷新
		fos.flush ();

		//关闭流
		fos.close ();
		fis.close ();
	}
}

这里为了方便看清逻辑关系,我在一开始就把异常抛出了,大家不要效仿。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值