字符流和字节流

在这里插入图片描述
这下面一个博客讲解的是关于转换问题的解法套路:
https://blog.csdn.net/z69183787/article/details/8179889

为什么要用buffer

https://www.cnblogs.com/zhaoyanjun/p/6376937.html

也挺好的认识几个缓存的

https://blog.csdn.net/qq_31617121/article/details/79110699

自己的认识

有了字符流为什么还要有字节流呢,字符流是人类所能识别的,而字节流是电脑能识别的,在我们对文件进行输入输出里面只是文字的时候可以用字符流这样就可以不用频繁的耗内存,而当对图片音频进行输入输出的时候就要用字节流,不能用字符流了,当既有图片又有文字只能是字节流了。
我们的汉字都是两个字节的,所以要用字节流进行读取的话就得对文件进行字符的转换,才能在打印台显示出来,否则就会是一堆乱码。则在我们对图片进行读取的时候要用字节缓冲流进行缓存就是BufferedInputStream,对于图片字节流读取的,字符流是无法读取的。每个数字都是一个字节(Byte,8位),所以如果读取英文的话,用字节流,然后用(char)强制转化一下就行了,但如果有中文等双字节语言或者说需要指定字符编码集的情况,就必须用到InputStreamReader将字节流转化为字符流了。
我们有必要知道不带缓冲的操作,每读一个字节就要写入一个字节,由于涉及磁盘的IO操作相比内存的操作要慢很多,所以不带缓冲的流效率很低。带缓冲的流,可以一次读很多字节,但不向磁盘中写入,只是先放到内存里。等凑够了缓冲区大小的时候一次性写入磁盘,这种方式可以减少磁盘操作次数,速度就会提高很多!

Java中字节流和字符流的read()方法返回的值是int类型

详解:
https://blog.csdn.net/daijunjian/article/details/7316275
字符流中读取到的char是直接当作int使用, 例如读取到一个’a’也就是97的时候, 那么就相当于返回了一个int的97
而在read()方法中内部将读取到的所有字节高位补0转为int返回, 这样做所有的数据都会是正数
这时就可以用-1表示流末尾了而改变后的数据只要强转回byte, 就可以得到原有数据。

在这里面的read的底层代码中为:

b.length是指这个数组的大小
在这里插入图片描述
在这里插入图片描述

在进行从控制台输入的时候只能是以字节的形式进行设置缓存大小应为System.in是首先我们需要知道System.in到底是什么?,所以不能直接字符进行读文件的读取。

直接输出System.in我们可以发现它是一个BufferedInputStream

那么BufferedInputStream.read()是如何运作的?
说明在整体的进行信息的读取。
详解在下面的博客中:
https://blog.csdn.net/u012345283/article/details/39027745

所以最直接的对文件的读取是:
java的读写操作是学java开发的必经之路,下面就来总结下java的读写操作。

从上图可以开出,java的读写操作(输入输出)可以用“流”这个概念来表示,总体而言,java的读写操作又分为两种:字符流和字节流。

什么是流?

流是一个抽象的概念。当Java程序需要从数据源读取数据时,会开启一个到数据源的流。数据源可以是文件,内存或者网络等。同样,当程序需要输出数据到目的地时也一样会开启一个流,数据目的地也可以是文件、内存或者网络等。流的创建是为了更方便地处理数据的输入输出。

那么字节流和字符流又有什么区别呢?

1.字节流也称为原始数据,需要用户读入后进行相应的编码转换。而字符流的实现是基于自动转换的,读取数据时会把数据按照JVM的默认编码自动转换成字符。

2.字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。

所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的。

3.字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串,字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以;

基于以上的区别,那么什么情况下用字符流,什么情况下用字节流呢?

如果是音频文件、图片、歌曲,就用字节流好点;如果是中文(文本)的,用字符流更好;

说了这么多,字节流和字符流处理文件到底怎么用呢?

稍安勿躁,让我们先来看看在java中,输入输出操作的步骤是什么?

1 使用File类打开一个文件

2 通过字节流或字符流的子类,指定输出的位置,注,

3 进行读/写操作

4 关闭输入/输出

IO操作属于资源操作,一定要记得关闭
1.初学者一般很容易搞混,或者弄不清inputstream和outpustream到底哪个是读数据,哪个是写数据,这里要说明的是,“读和写”是相对于程序本身而言的,主要记清楚一点即可,那就是凡是需要提供给程序处理的数据就是输入数据,当然就是inputstream,这里的in是要in到程序里面去,那么数据从哪里来呢,自然是从外界(网络,内存或者文件),那么针对文件而言,inputstream就是读文件了。反之,凡是程序已经处理过的数据,当然要流出程序啦,那就是out咯,所以outputstream就是输出的,那么从程序中流出,只能到外界(网络、内存或者文件),针对文件而言,就是写操作啦!(同样的道理可以针对字符流的操作)

【简言之,针对程序而言,in是入,out是出;这对文件而言,in是读,out是写!】

2.inputstream和OutputStream都是抽象类,不能实例化,使用时必须实例化一个子类(其中FileInputStream和FileOutputStream使用最多)对象来进行相关操作。

3.InputStream inputStream = new FileInputStream(fileName);当使用这个命令时,系统会提示有异常抛出,因为我们上面定义的文件程序认为是有可能存在,有可能不存在的,所以在eclipse中,给出了两个解决办法,一个是直接抛出异常声明,由系统自己解决;另一个是用try,catch结构处理异常!

===============================================================================================================

转载:https://blog.csdn.net/liyuxing6639801/article/details/69487712
Java FileWriter无法编码utf-8 转换方法
原本想通过文件追加的方式,向.txt或者.json文件(其他也类似)结尾添加新的文本,开始通过FileWriter追加,但是中文追加后却成了乱码。
查了一圈下来结论是:Java FileWriter 默认是用(ISO-8859-1 or US-ASCII)西方编码的,而FileWriter类没有setEncoding的方法。希望通过设置编码方式的计划破灭了。
那么就换一种方法吧:

BufferedWriter writer = new BufferedWriter (new OutputStreamWriter (new FileOutputStream (filePath,true),“UTF-8”));
不需要改动原来的代码,只需要用上面的代码替换原来的

FileWriter writer = new FileWriter(filePath,true);
运行代码,打开文本文件,中文又回来了!!!

转载:http://cii001.iteye.com/blog/1825760

PrintWriter和FileWriter这两个类有什么区别(转)
写文件最佳组合
PrintWriter out = new PrintWriter(
new BufferedWriter(
new FileWriter(filename)))
PrintWriter 提供print系方法
BufferedWriter 提供缓冲,用以加速
FileWriter 用于写文件

====================================

PrintWriter以字符为单位,支持汉字,
OutputStreamWriter以字节为单位,不支持汉字,

====================================‘
FileReader、FileWriter分别是对文本文件的读写使用的封装了一些字符集操作。FileInputStream/FileOutputStream是集成InputStream/OutputStream的文件读写流,用于读写任何文件,可以作为构造其他InputStream/OutputStream的基础

嗯嗯

什么是字符流和字节流:
了解二进制文件和文本文件。
1,能存储的数据类型不同
文本文件只能存储char型字符变量。二进制文件可以存储char/int/short/long/float/……各种变量值。
2,每条数据的长度
文本文件每条数据通常是固定长度的。以ASCII为例,每条数据(每个字符)都是1个字节。进制文件每条数据不固定。如short占两个字节,int占四个字节,float占8个字节……。比如21345在文本文件中的是占用5个字节但在二进制文件中占用两个字节。
3,读取的软件不同
文本文件编辑器就可以读写。比如记事本、NotePad++、Vim等。二进制文件需要特别的解码器。比如bmp文件需要图像查看器,rmvb需要播放器……
4,文件在磁盘上的存储方式都是二进制形式,所以,文本文件其实也应该算二进制文件。先从他们的区别来说,虽然都是二进制文件,但是二进制代表的意思不一样。打个比方,一个人,我们可以叫他的大名,可以叫他的小名,但其实都是代表这个人。二进制读写是将内存里面的数据直接读写入文本中,而文本呢,则是将数据先转换成了字符串,再写入到文本中。
5,记事本支持文本文件而不支持二进制文件,所以如果你用记事本打开文本文件那么一切正常,如果打开的是二进制文件就会出现乱码。但也有不乱码的地方,你会注意到那些地方都是字符编码的,而对于int、double等类型所对应的值都是乱码的,这是由于记事本只能够识别字符类型,而无法识别其他类型。
当用记事本打开docx文件的时候会出现乱码的情况,
在这里插入图片描述

(1)、二进制文件是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放,也就是说存放的是数据的原形式。

(2)、文本文件是把数据的终端形式的二进制数据输出到磁盘上存放,也就是说存放的是数据的终端形式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

会通过FileOutStream(File file)来对对象进行进行创建

public class Text {
	public static void main(String[] args) {
      try {
		FileInputStream fileInputStream = new FileInputStream("D:\\a.docx");
		FileOutputStream fileOutputStream = new FileOutputStream("D:\\b.docx");
		byte [] car =new byte[1024];
		int length=0;//这是真正在车里装载多少个字节,当载到最后没有的时候就会返回-1值;
		while((length=fileInputStream.read(car))!=-1) {
			fileOutputStream.write(car,0,length);
		}
      }catch(Exception e) {
    	  e.printStackTrace();
      }finally{
			if (inputStream != null) {
		}
			try {
				inputStream.close();//关闭并释放资源
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		if (outputStream != null) {
			try {
				outputStream.close();//关闭并释放资源
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}	
}	

当你在字符流中转二进制文件是能创建文件但打不开文件的。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
QzOTUyNjEw,size_16,color_FFFFFF,t_70)

**4,**数据流

public class T822 {
	public static void main(String[] args) {
		//数据流:方便程序中数据存入文件
		//DataOutputStream是用来把数据进入文件,他也有一个相当于一个字节的缓冲流。
		double x=10;
		try {
			DataOutputStream dataOutputStream=new DataOutputStream(new FileOutputStream("D:\\a.docx"));
			dataOutputStream.writeDouble(11);
			dataOutputStream.writeDouble(10);
//			dataOutputStream.writeUTF("Tom");
			dataOutputStream.flush();//在输出流中最好都有flush进行刷新数据使数据进行的完全输出
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		try {
			DataInputStream dataInputStream=new DataInputStream(new FileInputStream("D:\\a.docx"));
//			double p= dataInputStream.readDouble();
//			System.out.println(p);
//			String y=dataInputStream.readUTF();
//			System.out.println(y);
			while(true) {
				double p= dataInputStream.readDouble();
				System.out.println(p);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}
}

在这里插入图片描述
在这里面会有个end of file异常的输出则是在说读取信息完了,但这种的异常是不能避免的,因为数据流自身原因,他不能完全的有Object类型的直接输入多种类型,只能一种一种输出,一种一种的读取,其他类型也不能输出其他类型的,在存入多个数据在读取多个数据的时候只能是一一对应的否则就会不再往下面读出数据了。

关于读取文件中的内容可以用以下格式进行:

package com.jd;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
//read会读取并且还能还自带返回值当流中读取到一个字符时, read()方法内部就会当作int返回, 如果读到流末尾, 直接返回-1
public class IOTest {//在输出图片和音频的时候直接用字节流就可以了
//在创建buffer时候会创建一个内部缓冲区数组,在读取或跳过流中的字节时,可根据需要从包含的输入流再次填充内部缓冲区,一次填充多个字节,reset操作使得在从
public static void main(String[] args) throws IOException {
//使用buffer进行文件读写,这里面的BufferedInputStream是字节的缓冲流,而bufferedReader是字节的缓冲流
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(new File("E:\\新建文件夹\\摄图网_400854135.jpg ")));
File newFile = new File("D:\\wang.jpg");
newFile.createNewFile();
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(newFile));
byte[] bytes= new byte[1024];
int length = 0;
while ((length=bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,length);
}
}
}

对于读取音频或者是图片的时候用的只能是字节流了,字节是对于汉字2字节产生的读取方法的。
当对于一个纯文本文件的时候有以下4中进行读取
1,用字符流进行读取,其中包括一个字节一个字节的进行读取文件。


package com.jd;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class Io1 {
	public static void main(String[] args) throws IOException {
		FileReader fr = new FileReader("D:\\笔记.txt"); 
		FileWriter fw =new FileWriter("D:\\\\笔记1.txt",true); 
		BufferedReader br =new BufferedReader(fr);
		BufferedWriter br1 =new BufferedWriter(fw);


		int value=fr.read(); //在这里面中他会把读取的字符进行转化为int型,read()是一个字符去读取的
		while(value!=-1){ /		br1.write(value);//在这里面的write是进行对int型强制性转换为char类型进行读取的 ,在这里是一个一个进行读取的这里的whiel会走多少个字符多少遍
		br1.flush(); 
		value=br.read(); 
		}
		
		 char [] chars = new char[1024]; 
		 int len =br.read(chars); //这是先把读取的字符放入到缓存区
		 while(len!=-1){ 
		 br1.write(chars, 0, len); 
		 br1.flush(); 
		 len =br.read(chars); //这个的作用就是把文件最后那个-1给读取出来所以当char字节小于1024的时候会while就走两次
		 } 
		 
		 String string;
         while (null != (string = br.readLine())) {//在这里是在文件中有多少行的就进行多少次再加上1次,因为最后要判断null。
        	 br1.write(string+"\n");//这里加的\n是进行行的跳转的这样是为了方便行的读取的,
        	 br1.flush();
             System.out.println(string);
         }
		 fr.close(); 
		 fw.close(); 
		 }
		 }

当文件中的内容是英文或者是数字的时候,就可以直接用子节流进行读取就可以了。下面的读取是先是字节流在转换成字符流进行读取的。

	    //读取字节流
	    //InputStream in = System.in;//读取键盘的输入。
		InputStream in = new FileInputStream("D:\\笔记1.txt");//读取文件的数据。
	    //将字节流向字符流的转换。要启用从字节到字符的有效转换,
	    //可以提前从底层流读取更多的字节.
	    InputStreamReader isr = new InputStreamReader(in);//读取
	    //综合到一句。
	    //InputStreamReader isr = new InputStreamReader(
	    //new FileInputStream("D:\\demo.txt"));
	    char []cha = new char[1024];
	    int len = isr.read(cha);
	    System.out.println(new String(cha,0,len));
	    isr.close();

使用缓冲流进行读取,在这里面和上面区别就是加入了缓存流,数据就可以快速进行读取或者存储,不用直接访问自己的磁盘进行信息的存储,也就像我们的内存的使用情况。

	    //读取字节流
	    //InputStream in = System.in;//读取键盘上的数据
	    InputStream in = new FileInputStream("D:\\笔记1.txt");//读取文件上的数据。
	    //将字节流向字符流的转换。
	    InputStreamReader isr = new InputStreamReader(in);//读取
	    //创建字符流缓冲区
	    BufferedReader bufr = new BufferedReader(isr);//缓冲
	    //BufferedReader bufr = new BufferedReader(
	    //new InputStreamReader(new FileInputStream("D:\\demo.txt")));可以综合到一句。
	    /*int ch =0;
	    ch = bufr.read();
	    System.out.println((char)ch);
	    */
	    String line;
	    while((line = bufr.readLine())!=null){
	      System.out.println(line);
	    }
	    isr.close();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值