IO_03_字节流

原创 2016年08月21日 09:52:35
字符流底层也是用的字节流的缓冲区


两者的区别就是:字节流可以既可以操作文本文件,也可以操作非文本文件,如一些二进制数据(图片,视频,对象),
而字符流只能操作文本。这也是两者的适用情况,如何决定该使用哪种数据流读写取决于要读写的数据类型,若是文本本件,
当然选择字符流,因为我们都知道字符流每次处理的单元为2个字节的Unicode字符,而字节流每次处理的是一个,若是非文本文件,
那么就只能用字节流了,这个时候就不能单纯的看谁的效率高了


对于我们常用的GBK中,英文是占用1个字节,中文是2个 
对于UTF-8,英文是1个,中文是3个 

对于Unicode,英文中文都是2个

字节流读取文件和写入文件

class  FileStream
{
	public static void main(String[] args) throws IOException
	{
		readFile_3();
		readFile_2();
		readFile_1();
		readFile_1();
	}
	/**
	 * 定义刚刚好的缓冲区,不用再循环(用于知道文件的大小,慎用,只是用于文件小的)
	 * @throws IOException
	 */
	public static void readFile_3()throws IOException
	{
		FileInputStream fis = new FileInputStream("src\\com\\fileStream\\ref\\fos.txt");
		
//		int num = fis.available();
		byte[] buf = new byte[fis.available()];//定义一个刚刚好的缓冲区。不用在循环了。

		fis.read(buf);

		System.out.println(new String(buf));

		fis.close();
	}

	/**
	 * 定义一个1024的字节数据读取
	 * @throws IOException
	 */
	public static void readFile_2()throws IOException
	{
		FileInputStream fis = new FileInputStream("src\\com\\fileStream\\ref\\fos.txt");

		byte[] buf = new byte[1024];
		int len = 0;
		while((len=fis.read(buf))!=-1)
		{
			System.out.println(new String(buf,0,len));
		}

		fis.close();
		
	}


	/**
	 * 字节流读文件,一个一个读
	 * @throws IOException
	 */
	public static void readFile_1()throws IOException
	{
		FileInputStream fis = new FileInputStream("src\\com\\fileStream\\ref\\fos.txt");

		int ch = 0;

		while((ch=fis.read())!=-1)
		{
			System.out.println((char)ch);
		}

		fis.close();
	}
	/**
	 * 字节流写文件
	 * @throws IOException
	 */
	public static void writeFile()throws IOException
	{
		FileOutputStream fos = new FileOutputStream("src\\com\\fileStream\\ref\\fos.txt");
		

		fos.write("abcde".getBytes());

		fos.close();
		
	}
}
复制一个图片

思路:
1,用字节读取流对象和图片关联。
2,用字节写入流对象创建一个图片文件。用于存储获取到的图片数据。
3,通过循环读写,完成数据的存储。
4,关闭资源。

class  CopyPic
{
	public static void main(String[] args) 
	{
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try
		{
			fos = new FileOutputStream("src\\com\\fileStream\\ref\\copy\\devOps.png");
			fis = new FileInputStream("src\\com\\fileStream\\ref\\devOps.png");
			/**定义一个1024的字节数据来缓冲*/
			byte[] buf = new byte[1024];

			int len = 0;

			while((len=fis.read(buf))!=-1)
			{
				fos.write(buf,0,len);
			}
		}
		catch (IOException e)
		{
			throw new RuntimeException("复制文件失败");
		}
		finally
		{
			try
			{
				if(fis!=null)
					fis.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(fos!=null)
					fos.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入关闭失败");
			}
		}
	}
}

自定义缓冲区

class MyBufferedInputStream
{
	private InputStream in;

	private byte[] buf = new byte[1024*4];
		
	private int pos = 0,count = 0;
	
	MyBufferedInputStream(InputStream in)
	{
		this.in = in;
	}

	//一次读一个字节,从缓冲区(字节数组)获取。
	public int myRead()throws IOException
	{
		//通过in对象读取硬盘上数据,并存储buf中。
		if(count==0)
		{
			count = in.read(buf);
			if(count<0)
				return -1;
			pos = 0;
			byte b = buf[pos];

			count--;
			pos++;
			return b&255;
		}
		else if(count>0)
		{
			byte b = buf[pos];

			count--;
			pos++;
			return b&0xff;
		}
		return -1;

	}
	public void myClose()throws IOException
	{
		in.close();
	}
}


/*
11111111-111111110000000000101001001010100101010010101001010


byte: -1  --->  int : -1;
00000000 00000000 00000000 11111111  255

11111111 11111111 11111111 11111111


11111111  -->提升了一个int类型 那不还是-1吗?是-1的原因是因为在8个1前面补的是1导致的。
那么我只要在前面补0,即可以保留原字节数据不变,又可以避免-1的出现。
怎么补0呢?

 11111111 11111111 11111111 11111111                        
&00000000 00000000 00000000 11111111 
------------------------------------
 00000000 00000000 00000000 11111111 

0000-0001
1111-1110
000000001
1111-1111  -1


结论:
字节流的读一个字节的read方法为什么返回值类型不是byte,而是int。
因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.
那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。
所以,为了避免这种情况将读到的字节进行int类型的提升。
并在保留原字节数据的情况前面了补了24个0,变成了int类型的数值。


而在写入数据时,只写该int类型数据的最低8位。


*/
复制Mp3

class  CopyMp3
{
	public static void main(String[] args) throws IOException
	{
		long start = System.currentTimeMillis();
		copy_2();
		long end = System.currentTimeMillis();

		System.out.println((end-start)+"毫秒");
		
		
		start = System.currentTimeMillis();
		copy_1();
		end = System.currentTimeMillis();

		System.out.println((end-start)+"毫秒");
	}

	public static void copy_2()throws IOException
	{
		/**
		 * 自定义缓冲
		 */
		MyBufferedInputStream bufis = new MyBufferedInputStream(new FileInputStream("src\\com\\fileStream\\ref\\cengjideni.mp3"));
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("src\\com\\fileStream\\ref\\copy\\cengjideni.mp3"));
		
		int by = 0;

		//System.out.println("第一个字节:"+bufis.myRead());

		while((by=bufis.myRead())!=-1)
		{
			bufos.write(by);
		}

		bufos.close();
		bufis.myClose();
	}

	//通过字节流的缓冲区完成复制。
	public static void copy_1()throws IOException
	{
		BufferedInputStream bufis = new BufferedInputStream(new FileInputStream("src\\com\\fileStream\\ref\\cengjideni.mp3"));
		BufferedOutputStream bufos = new BufferedOutputStream(new FileOutputStream("src\\com\\fileStream\\ref\\copy\\cengjideni.mp3"));
		
		int by = 0;

		while((by=bufis.read())!=-1)
		{
			bufos.write(by);
		}

		bufos.close();
		bufis.close();

		
	}
}


读取键盘录入。
System.out:对应的是标准输出设备,控制台。
System.in:对应的标准输入设备:键盘。




需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。
如果录入的数据是over,那么停止录入。


class  ReadIn
{
	public static void main(String[] args) throws IOException
	{
		InputStream in = System.in;
		StringBuilder sb = new StringBuilder();

		while(true)
		{
			int ch = in.read();
			if(ch=='\r')
				continue;
			if(ch=='\n')
			{
				String s = sb.toString();
				if("over".equals(s))
					break;
				System.out.println(s.toUpperCase());
				sb.delete(0,sb.length());
			}
			else
				sb.append((char)ch);

		}
	}
}


将系统信息保存到文件

class  SystemInfo
{
	public static void main(String[] args) throws IOException
	{
		Properties prop = System.getProperties();

		//System.out.println(prop);
		prop.list(new PrintStream("src\\com\\fileStream\\ref\\sysinfo.txt"));
	}
}

将异常信息保存到文件

class  ExceptionInfo
{
	public static void main(String[] args)throws IOException 
	{
		try
		{
			int[] arr = new int[2];
			System.out.println(arr[3]);
		}
		catch (Exception e)
		{
			
			try
			{
				Date d = new Date();
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				String s = sdf.format(d);

				PrintStream ps = new PrintStream("src\\com\\fileStream\\ref\\exeception.log");
				ps.println(s);
				System.setOut(ps);

				
			}
			catch (IOException ex)
			{
				throw new RuntimeException("日志文件创建失败");
			}
			e.printStackTrace(System.out);
		}
	}
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

IO-03字节流字符流

JAVA iO

Java IO操作——字节流(OutputStream、InputStream)和字符流(Writer、Reader)

支持原创,谢谢原作者! 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序中需要数据的时候就用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成...

java-IO流2(输出字节流)

输出字节流 :——–| OutputStream 是所有输出字节流 的父类。 (抽象类) ———–| FileOutStream 向文件输出数据的输出字节流。FileOutputStream使用...

黑马程序员----JAVASE之IO流操作【字节流】

-------------- android培训、java培训、期待与您交流! --------------- 1.字节流       在处理字节流使用的基类:InputStream,Outp...

IO流基础(字节流)

字节流: InputStream:是表示字节输入流的所有类的超类。      |--- FileInputStream:操作文件从文件系统中的某个文件中获得输入字节。哪些文件可用取决于主机环境。Fil...

java中的IO流之字节流详解(二)

学习IO流首先要了解IO流的体系架构 IO流分类 •IO流的分类: IO流相对于JVM来说,根据传输方向划分为 •输入流 •输出流 IO流根据流的传输数据类型 •字节流(按字节传输) •字符流(按字...

io字节流复制媒体文件

用字符流读取一个图片(媒体)的数据可以吗? 因为文字有对应的码表对应, 但你读到的字节数据有肯能在码表用没有对应的数据,所以码表就哪一些未知的符号的表示, 这样图片(媒体编辑器就无法打开...

Java的IO之字节流(stream)

IO流(IO流概述及其分类) 1.概念IO流用来处理设备之间的数据传输 Java对数据的操作是通过流的方式 Java用于操作流的类都在IO包中 流按流向分为两种:输入流,输出流。 流按操作类型分为两种...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)