IO流的学习-字节流

1.流

流要以程序,项目为主体。

程序到文件 =》输出(Output)

文件到程序 =》输入(Input)



2.字节输出流OutputStream

      OutputStream此抽象类是表示输出字节流的所有类的超类。操作的数据都是字节,定义了输出字节流的基本共性功能方法。

  输出流中定义都是写write方法,如下图:



3.FileOutputStream类

此类继承于OutputStream类:



拥有父类的方法,也有子类自己独有的方法。如下



注意:

1.一个字节等于8个二进制位。相当于写入一个字节,就再操作8个进制位。

2.FileOutputStream可以创建文件,如果文件存在,则会覆盖。(覆盖之后原先的内容消失)

3.FileOutputStream会抛异常,异常是文件路径不存在。

4.write(int b)方法也会抛异常,异常是文件不能写入。

5.write(int b)的参数对应的是ASCII码表。写入的int值,会去ASCII码表找对应的值。

6.write(byte[] b)是写数组,数组中的每个值都是一个字节。

一个汉字 = 两个字节(负数字节为汉字,如果只有一个字节,那么汉子缺失,显示'?',问号)

一个数字 = 一个字节

7.write(byte[] b, int off, int len) :将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流。

8.String类型可以调用getBytes()方法,获取字符串的字节。


			/*
			 *   FileOutputStream
			 *   写入数据文件,学习父类方法,使用子类对象
			 *   
			 *   子类中的构造方法: 作用:绑定输出的输出目的
			 *     参数:
			 *       File    封装文件
			 *       String  字符串的文件名
			 *   
			 *   流对象使用步骤
			 *     1. 创建流子类的对象,绑定数据目的
			 *     2. 调用流对象的方法write写
			 *     3. close释放资源
			 *     
			 *    流对象的构造方法,可以创建文件,如果文件存在,直接覆盖
			 */
			public class FileOutputStreamDemo {
				public static void main(String[] args)throws IOException {
					FileOutputStream fos = new FileOutputStream("c:\\a.txt");
					//流对象的方法write写数据
					//写字节数组
					byte[] bytes = {65,66,67,68};
					fos.write(bytes);
					
					//写字节数组的一部分,开始索引,写几个
					fos.write(bytes, 1, 2);
					
					//写入字节数组的简便方式
					//写字符串
					fos.write("hello".getBytes());

					//关闭资源
					fos.close();
					
				}
			}


4.FileOutputStream 文件的续写和换行问题

续写使用如下构造。

   
   
FileOutputStream(File file, boolean append) 
file - 为了进行写入而打开的文件。
append - 如果为 true,则将字节写入文件末尾处,而不是写入文件开始处 file - 为了进行写入而打开的文件。

换行使用:/r/n

    
    


    
    


    
    


    
    


    
    


    
    


   
   
示例:
/*
 *  FileOutputStream 文件的续写和换行问题
 *  续写: FileOutputStream构造方法, 的第二个参数中,加入true
 *  在文件中,写入换行,符号换行  \r\n
 *  \r\n 可以写在上一行的末尾, 也可以写在下一行的开头
 */
public class FileOutputStreamDemo1 {
	public static void main(String[] args)throws IOException {
		File file = new File("c:\\b.txt");
		FileOutputStream fos = new FileOutputStream(file,true);
		fos.write("hello\r\n".getBytes());
		fos.write("world".getBytes());
		fos.close();
	}
}


5.IO流的异常处理

/*
 *   IO流的异常处理
 *   try catch finally
 *   
 *   细节:
 *     1. 保证流对象变量,作用域足够
 *     2. catch里面,怎么处理异常
 *         输出异常的信息,目的看到哪里出现了问题
 *         停下程序,从新尝试
 *     3. 如果流对象建立失败了,需要关闭资源吗
 *         new 对象的时候,失败了,没有占用系统资源
 *         释放资源的时候,对流对象判断null
 *         变量不是null,对象建立成功,需要关闭资源
 */
public class FileOutputStreamDemo3 {
	public static void main(String[] args) {
		//try 外面声明变量,try 里面建立对象
		FileOutputStream fos = null;
		try{
			fos = new FileOutputStream("s:\\a.txt");
			fos.write(100);
		}catch(IOException ex){
			System.out.println(ex);
			throw new RuntimeException("文件写入失败,重试");
		}finally{
			try{
				if(fos!=null)
			      fos.close();
			}catch(IOException ex){
				throw new RuntimeException("关闭资源失败");
			}
		}
	}
}

6.字节输入流InputStream



 int read():读取一个字节并返回,没有字节返回-1.
 int read(byte[]): 读取一定量的字节数,并存储到字节数组中,返回读取到的字节数。


7.FileInputStream类读取数据read方法

如下是继承结构:


API:在读取文件中的数据时,调用read方法,实现从文件中读取数据




注意:
1.read()方法字节读取完,就是-1,可以利用循环读。
2.每次调用read方法,就会读取下一个,所以要用赋值一个变量的方法,去判断。不能每次都去读取,会造成数据丢失。
3.read()读取的是int值,对应的ASCII表。如果要看到对应的字幕,转char类型。

public class FileInputStreamDemo {
	public static void main(String[] args) throws IOException{
		FileInputStream fis = new FileInputStream("c:\\a.txt");
		//读取一个字节,调用方法read 返回int
		//使用循环方式,读取文件,  循环结束的条件  read()方法返回-1
		int len = 0;//接受read方法的返回值
	
		while( (len = fis.read()) != -1){
			System.out.print((char)len);
		}
    	//关闭资源
		fis.close();
	}
}


7.FileInputStream类读取数据read(byte[])方法

在读取文件中的数据时,调用read方法,每次只能读取一个,太麻烦了,于是我们可以定义数组作为临时的存储容器,这时可以调用重载的read方法,一次可以读取多个字符。


原理:

当执行io流的时候,程序会去找JVM,JVM会去让系统(os)去执行。这里定义数组为2,那么一次就读取2个字节。因为文档为abcde,5个字节多出一个,当读到第3次的时候,数组0角标会被e覆盖,角标1因为没有值,所有没有被覆盖,这里的len值,代表的是读取的有效字节。因此,第三次读出来的值为ed。而一个文档当没有值时候,会在最后有个结束标记,系统会把这个结束标记给jvm,jvm就返回一个-1。原理图如下:


注意:
1.数组定义的长度,不要过大,虽然可以增加读取的速度,但是因为要创建这么大的数据,需要耗费不少的内存。
2.String里有两个方法

以下方法,是直接解析byte数组,并且去比对ASCII码表,转换后显示出来。
String(byte[] bytes) 
          通过使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String。

以下方法,是放入数组,读取数据的offset到length长度。我们通常都是把read读出的值,放到length上,这样就只可以读取到有效的值了。
String(byte[] bytes, int offset, int length) 
          通过使用平台的默认字符集解码指定的 byte 子数组,构造一个新的 String。

3.以下案例len为有效值个数,String方法可以查找API具体了解。


public class FileInputStreamDemo2 {
	public static void main(String[] args) throws IOException {
		/*
		 * 演示第二个读取方法, read(byte[]);
		 */
		File file = new File("c:\\file.txt");
		// 创建一个字节输入流对象,必须明确数据源,其实就是创建字节读取流和数据源相关联。
		FileInputStream fis = new FileInputStream(file);		
		//创建一个字节数组。
		byte[] buf = new byte[1024];//长度可以定义成1024的整数倍。		
		int len = 0;
		while((len=fis.read(buf))!=-1){
			System.out.println(new String(buf,0,len));
		}
		fis.close();
	}
}

8.文件复制原理

复制的原理,就是读取数据源,写入数据目标。
扩展:通过服务器io流上传和下载。



9.复制文件实现

原理:读取一个已有的数据,并将这些读到的数据写入到另一个文件中。读一个字节,写一个字节,这种效率底。

/*
			 *  将数据源 c:\\a.txt
			 *  复制到 d:\\a.txt  数据目的
			 *  字节输入流,绑定数据源
			 *  字节输出流,绑定数据目的
			 *  
			 *  输入,读取1个字节
			 *  输出,写1个字节
			 */
			public class Copy {
				public static void main(String[] args) {
					//定义两个流的对象变量
					FileInputStream fis = null;
					FileOutputStream fos = null;
					try{
						//建立两个流的对象,绑定数据源和数据目的
						fis = new FileInputStream("c:\\t.zip");
						fos = new FileOutputStream("d:\\t.zip");
						//字节输入流,读取1个字节,输出流写1个字节
						int len = 0 ;
						while((len = fis.read())!=-1){
							fos.write(len);
						}
					}catch(IOException ex){
						System.out.println(ex);
						throw new RuntimeException("文件复制失败");
					}finally{
						try{
							if(fos!=null)
								fos.close();
						}catch(IOException ex){
							throw new RuntimeException("释放资源失败");
						}finally{
							try{
								if(fis!=null)
									fis.close();
							}catch(IOException ex){
								throw new RuntimeException("释放资源失败");
							}
						}
					}
				}
			}


创建字节缓冲区,这样能够提神效率。
			/*
			 *  字节流复制文件
			 *   采用数组缓冲提高效率
			 *   字节数组
			 *   FileInputStream 读取字节数组
			 *   FileOutputStream 写字节数组
			 */
			public class Copy_1 {
				public static void main(String[] args) {
					long s = System.currentTimeMillis();
					FileInputStream fis = null;
					FileOutputStream fos = null;
					try{
						fis = new FileInputStream("c:\\t.zip");
						fos = new FileOutputStream("d:\\t.zip");
						//定义字节数组,缓冲
						byte[] bytes = new byte[1024*10];
						//读取数组,写入数组
						int len = 0 ; 
						while((len = fis.read(bytes))!=-1){
							fos.write(bytes, 0, len);
						}
					}catch(IOException ex){
						System.out.println(ex);
						throw new RuntimeException("文件复制失败");
					}finally{
						try{
							if(fos!=null)
								fos.close();
						}catch(IOException ex){
							throw new RuntimeException("释放资源失败");
						}finally{
							try{
								if(fis!=null)
									fis.close();
							}catch(IOException ex){
								throw new RuntimeException("释放资源失败");
							}
						}
					}
					long e = System.currentTimeMillis();
					System.out.println(e-s);
				}
			}


扩展:
通过long e = System.currentTimeMillis();读取当前毫秒值,在程序的开头,和结尾都定义,相减就是程序运行时间。1000毫秒=1秒。



10.字符编码表

我们知道计算机底层数据存储的都是二进制数据,而我们生活中的各种各样的数据,如何才能和计算机中存储的二进制数据对应起来呢?

这时老美他们就把每一个字符和一个整数对应起来,就形成了一张编码表,老美他们的编码表就是ASCII表。其中就是各种英文字符对应的编码。

编码表:其实就是生活中字符和计算机二进制的对应关系表。

1ascii: 一个字节中的7位就可以表示。对应的字节都是正数。0-xxxxxxx

2iso-8859-1:拉丁码表latin,用了一个字节用的8位。1-xxxxxxx  负数。

3GB2312:简体中文码表。包含6000-7000中文和符号。用两个字节表示。两个字节第一个字节是负数,第二个字节可能是正数

   GBK:目前最常用的中文码表,2万的中文和符号。用两个字节表示,其中的一部分文字,第一个字节开头是1,第二字节开头是0

    GB18030:最新的中文码表,目前还没有正式使用。

1、unicode:国际标准码表:无论是什么文字,都用两个字节存储。

l Java中的char类型用的就是这个码表。char c = 'a';占两个字节。

l Java中的字符串是按照系统默认码表来解析的。简体中文版 字符串默认的码表是GBK。

5UTF-8:基于unicode,一个字节就可以存储数据,不要用两个字节存储,而且这个码表更加的标准化,在每一个字节头加入了编码信息(后期到api中查找)

能识别中文的码表:GBKUTF-8;正因为识别中文码表不唯一,涉及到了编码解码问题。

对于我们开发而言;常见的编码 GBK  UTF-8  ISO-8859-1(服务器上的语言)

文字--->(数字):编码。 “abc”.getBytes()  byte[]

(数字)--->文字  :解码。 byte[] b={97,98,99}  new String(b) 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值