JAVA操作IO流四部曲,简单好记

当我们需要从文本文件中读取内容,或者需要写入内容到文件中的时候,就需要用到JAVA中的流。

流包括输入流和输出流,读:使用输入流,写:使用输出流。为了方便记忆,分别拆分成以下4个步骤。

一、读取

1、新建文件输入流 FileInputStream (字节流,只能读取一个字节,fis.read())

FileInputStream fis = new FileInputStram(filePath);

2、新建一个 字符输入流InputStramReader ,(字符流,只能读取一个字符,isr.read())

InputStramReader isr = new InputStramReader(fis,"UTF-8");

3、新建一个 缓冲输入流BufferedReader (可读取一行字符,)

BufferedReader br=new BufferedReader(isr);

4、读取行

while((line=br.readLine())!=null){

System.out.println(line);

}

二、写入

1、新建文件输出流 FileOutputStream (字节流 )

FileOutputStream fos = new FileOutputStream(filePath);

2、新建一个 字符输出流OutputStreamWriter

OutputStreamWriter osw = new OutputStreamWriter(fos ,"UTF-8");

3、新建一个 缓冲输出流BufferedWriter (可写入一行字符,)

BufferedWriter bw=new BufferedWriter(osw);

4、写入行

ArrayList<String> popertiesLines = new ArrayList<String>();

for(String line:popertiesLines){

  bw.write(line);

  bw.newLine(); //换行

}

记忆路线(瞎扯):

读:FileInputStream -> InputStreamReader -> BufferedReader -> br.readLine();

写: FileOutputStream-> OutputStreamWriter -> BufferedWriter -> bw.write(line);

口诀:出写入读(都出血了,太恶毒),三流一操作


1、读写文件,当然首先想到文件(File),所以用到的是文件流:FileInputStream 、 FileOutputStream

          用到文件流,那文件路径在哪儿? 所以需指定文件路径。

          格式: new FileInputStream(fileRealPath);

2、有了文件流,要做啥操作,读or写 ? 想到 Reader,Writer。那就是  InputStreamReader 、 OutputStreamWriter

          读写操作哪个文件? 所以需指定第1步创建的文件流,

          读写操作使用那种字符? 所以需指定字符。

          格式: new InputStreamReader(fis, "utf-8");

3、什么都不是一步到位的,需要一定的缓冲,想到 buffered,那就是 BufferedReader、BufferedWriter

          读缓冲还是写缓冲? 所以需指定第2步创建的“读写流”。

          格式:new BufferedReader(isr);

4、三流已备齐,开搞。

        读 ? br.readLine();

        写 ? bw.write(line);  写了一行记得换行啊:  bw.newLine(); 

示例(修改一个配置文件):

	/**
	 * 修改properties配置文件,保留原有注释。
	 * @param fileRealPath 文件绝对路径,
Linux: /root/iov_main/ly.mp.iov.login.main/bin
window:E:\后台开发工作空间\iov\ly.mp.iov.example.common\src\main\resources\domainname.properties
	 * @param keyName 键 ,如键不存在,则新增在后尾
	 * @param value 值
	 */
	public static boolean SetPropetyValue(String fileRealPath,String keyName,String value){
		ArrayList<String> popertiesLines = new ArrayList<String>();
		boolean hasKey=false;
		BufferedReader br=null;
		BufferedWriter bw=null;
		try {
			//1、读取配置文件
			FileInputStream  fis = new FileInputStream(fileRealPath);
			InputStreamReader isr = new InputStreamReader(fis, "utf-8");
			br = new BufferedReader(isr);
			String line = "";
			while ((line=br.readLine()) != null){
				// 找到该key,重新赋值(修改value)
				if(line.startsWith(keyName, 0)){
					hasKey=true;
					popertiesLines.add(keyName+"="+value);
					logger.info("SetPropetyValue----->line.startsWith:"+keyName+",line:"+line);
				}else{ //不是该key的行,直接追加
					popertiesLines.add(line);
				}
			}
			
			//全部没有找到,追加key
			if(!hasKey){
				popertiesLines.add(keyName+"="+value);
			}
			
			//2、重新写入配置文件
			OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fileRealPath),"UTF-8");
			 bw= new BufferedWriter(osw);
			
			for(String lin:popertiesLines){
				bw.write(lin);
				bw.newLine();
			}
			bw.flush();
			
			return true;
		} catch (FileNotFoundException e) {
			logger.error("SetPropetyValue FileNotFoundException---->exception info:" + e.toString());
			return false;
		} catch (IOException e) {
			logger.error("SetPropetyValue IOException---->exception info:" + e.toString());
			return false;
		}finally{
			//关闭流
			if(br!=null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			
			if(bw!=null){
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}	

知识点:

关于路径的分隔斜杠。

Windows:

    “/”表示参数,“\” 表示本地路径。

Linux和Unix:

    “/” 表示路径,“\”表示转义,“-”和“--”表示参数。

 网络:

    由于网络使用Unix标准,所以网络路径用“/”。

1、InputStream、OutputStream

处理字节流的抽象类

InputStream 是字节输入流的所有类的超类,一般我们使用它的子类,如FileInputStream等.

OutputStream是字节输出流的所有类的超类,一般我们使用它的子类,如FileOutputStream等.

InputStream能从來源处读取一個一個byte,所以它是最低级的。

2.InputStreamReader  OutputStreamWriter

处理字符流的抽象类

InputStreamReader 是字节流通向字符流的桥梁,它将字节流转换为字符流.

OutputStreamWriter是字符流通向字节流的桥梁,它将字符流转换为字节流.

 InputStreamReader封裝了InputStream在里头,它以较高级的方式,一次读取一个一个字符,初始化时需指定字符。

3.BufferedReader BufferedWriter

BufferedReader 由Reader类扩展而来,提供通用的缓冲方式文本读取,readLine读取一个文本行,

从字符输入流中读取文本,缓冲各个字符,从而提供字符、数组和行的高效读取。

BufferedWriter  由Writer 类扩展而来,提供通用的缓冲方式文本写入, newLine使用平台自己的行分隔符,

将文本写入字符输出流,缓冲各个字符,从而提供单个字符、数组和字符串的高效写入。

BufferedReader则是比InputStreamReader更高级,它封裝了StreamReader类。

我们都知道计算机能识别的只有0和1,数据是以字节为单位存储的。

    a.故在java中,我们若想要从文件中读取一个字符,首先我们需要有一个文件(数据源),于是我们就使用到了File类来制定一个文件;

    b. 因为数据在计算机中都是0和1代码,以字节为单位,所以我们所指定的file对象就需要先转化成字节流,所以需要用到InputStream类;

    c. 这时候,如果在java中只是以字节来读取文件的话,就足够了。但是如果想要以字符来读取文件的话,还需要对字节流进行以某种方式编码,因为不同的字符采用不同的编码方式,如果仍然使用字节流的话,可能会达不到我们想要的效果。我们可以指定字符编码方式,这个通过在InputStreamReader相关类的构造器中指定并实例化,默认下是Unicode编码方式。到了这里,我们已经用到了InputStreamReader。

    d. 经过了上面三个步骤,我们已经可以从文件中读取到一个字符了,但是每次只读取一个字符又不能满足我们读取大数据的需求,这时候BufferedReader就派上用场了。从名字中的Buffer我们可以推测出它具有缓冲的作用,事实也是如此,它可以一次读取多个字符,一次性读取的字符数目还可以自由设置。

猜你喜欢

转载自blog.csdn.net/u012660464/article/details/81877527