IO编程之输入流

来源:互联网 发布:ubuntu如何卸载qq 编辑:程序博客网 时间:2024/04/30 16:02

------- android培训、java培训、期待与您交流! ----------


IO编程(1)

1       Input 输入概述

       输入流分为字符流和字节流,计算机内部存贮的都是字节流,是字符流的底层,由于码表的存在,在字节数据的基础上进行包装得到字节流。主要的输入设备有键盘,磁盘,光盘等。数据的输入为程序提供初始化的数据,比如tomcat的服务器,用户通过配置文件的方法为 tomcat 设置内存上线等,而这些配置文件基本上位于磁盘上,因而需要将其从磁盘读取,这就需要用到 I/O编程了,当然I/O编程远远不止这些。

1.1 输出流的层次结构

1.2  字符数据的编码问题

     ASCII 数据可以采用一个字节的方式就可以存贮,但是由于世界上的字符数据众多,一个字节难以全部表示,所以要拓展到用两个字节表示。全部用两个字节,就有些浪费空间。实际中,ASCII 采用一个字节表示,GBK等编码用两个字节表示。

2  字符输入流的基本用法

package cn.gxufe;import java.io.*;/** * Reader 的基本用法 * 演示读取单个字符,和多个字符的用法 * @author 荣英洁 */public class ReaderDemo {public static void main(String[] args) {//单个字符readSingleCharacter();//多个字符readPluralityCharacter();}/** * 读取单个字符 */public static void  readSingleCharacter(){FileReader reader = null;try {//指定要读取的文件对象reader = new FileReader("E:/hm/aaa.txt");//出入所用到的字符集System.out.println("字符集编码:"+reader.getEncoding());int temp;//读到文件末尾,返回 -1 表示结束//读取到数据类型  int , 通过  强制类型转换(根据系统的码表查找)成 单个字符while((temp=reader.read())!=-1){System.out.print((char)temp);}} catch (Exception e) {e.printStackTrace();}finally{if(reader!=null)try {reader.close();} catch (IOException e) {e.printStackTrace();}}}/** * 读取多个字符 */public static void  readPluralityCharacter(){FileReader reader = null;try {reader = new FileReader("E:/hm/aaa.txt");//出入所用到的字符集System.out.println("字符集编码:"+reader.getEncoding());//记录读取到的字符个数int len;//每次最多读取的字符数char b[] = new char[20];/** * 如果读取的到的字符长度为 0 表示没有可读数据 */while((len=reader.read(b))>0){System.out.print(new String(b,0,len));}} catch (Exception e) {e.printStackTrace();}finally{if(reader!=null)try {reader.close();} catch (IOException e) {e.printStackTrace();}}}}

2.2基于单个字符的读取,实现对字符数据逐行读取

package cn.gxufe;import java.io.File;import java.io.FileNotFoundException;import java.io.FileReader;import java.io.IOException;/** * 基于 字符流  FileReader 的单个字符读取方法, * 采用迭代模式实现,对数据进行读取 * @author 荣英洁 */public class MyReader{private FileReader fileReader = null;private String line="";public MyReader(File file) throws FileNotFoundException {fileReader = new FileReader(file);}public MyReader(String s) throws FileNotFoundException{fileReader = new FileReader(s);}public String getMyReadLine(){return this.line;}/** * 判断是否还有下一行数据 * @return */public boolean hasNextLine(){/** * window 系统的的换行符号是 \r\n 所以在遇到 ‘\r’字符时,继续循环 * 遇到'\n' 表示读取一行的数据结束  *///数据的缓存StringBuffer buffer = new StringBuffer();this.line = "";//记录每行读取到的数据int temp=0;//记录每次读取到的单个字符try {while((temp = fileReader.read())!=-1){char a = (char)temp;if(a=='\r')continue;else if(a=='\n'){line = buffer.toString();return true;}else{buffer.append(a);}}} catch (IOException e) {e.printStackTrace();try {this.close();} catch (IOException ea) {ea.printStackTrace();}}line = buffer.toString();if(line.equals("")){return false;}else{return true;}}public void close() throws IOException{if(this.fileReader!=null)this.fileReader.close();}}


3  字节输入流的用法

3.1  InputStream 的基本用法

package cn.gxufe;import java.io.*;/** * @author 荣英洁 * */public class InputSreamDemo {public static void main(String[] args) throws Exception {//单个字节的读取readSingleByte();System.out.println();//多个字节的读取readNumberBytes();}/** * 按照逐个字节的方式读取字符数据 * @throws Exception */public static void readSingleByte() throws Exception{InputStream inputStream = new FileInputStream("E:/hm/aaa.txt");/* *len=inputStream.read()  用于读取每次得到的字节数据 * 由 AScii 表可知 0-127 属于 AScii 字符数据 * 如果拿到的 int 数据不再这个范围,则表明是非 AScii 字符,即GBK编码。 * 而   AScii 采用一个字节,GBk用两个字节。 */int data;//用于保存读取到的 每个字节的数据byte b[] = new byte[2]; //用于保存读取的相邻的GBK数据的字节int i=0;//用户标记b 保存了几个数据while((data=inputStream.read())!=-1){//  大于 127 则说明是 GBK数据if(data>127){b[i] = (byte)data;if (i==1){System.out.print(new String(b));i=0;}else{i++;}}else{ // ASCII 数据System.out.print(((char)data));}}inputStream.close();}/** * 按照多个字节的方式读取字符数据 * @throws Exception */public static void readNumberBytes() throws Exception{InputStream inputStream = new FileInputStream("E:/hm/aaa.txt");int len;//用于保存读取到的 每个字节的数据byte data[] = new byte[4]; //用于保存读取的相邻的GBK数据的字节StringBuffer buffer = new StringBuffer();while((len=inputStream.read(data))>0){String s = new String(data,0,len);buffer.append(s);}System.out.println(buffer.toString());inputStream.close();}}

     基于多个字节读取的方式,如果遇到中文,有可能会产生中文乱码问题,例如:所要读取的字符串 是 “fds股份 ” ,而每次读取四个字节,那么第一次读取的时,只能读到 “股” 的第一个字节,读不到第二个字节,这就引起了乱码,“fds股份 ” 采用上述基于多个字节的方式读取 会得到的结果是“fds?煞?”。要解决这个问题,就要注意所读取到的字节是否是 ASCII 数据。非 ASCII 就要用两个字节表示一个字符。

3.2 基于逐个字节数据的读取,实现对字符数据逐行读取

package cn.gxufe.input;import java.io.*;/** * 采用迭代模式,基于单个字节的读取,实现对数据逐行读取 * @author 荣英洁 */public class MyInputStream {public static void main(String[] args) throws FileNotFoundException {MyInputStream inputStream = new MyInputStream("E:/hm/aaa.txt");//判断是否有一行数据while (inputStream.hasLine()) {System.out.println(inputStream.getMyReadLine());}}private InputStream inputStream = null;private String line="";public MyInputStream(String path) throws FileNotFoundException{inputStream = new FileInputStream(path);}public MyInputStream(File file) throws FileNotFoundException{inputStream = new FileInputStream(file);}/** * 判断是否还有数据 * @return */public boolean hasLine(){StringBuffer buffer = new StringBuffer();line="";try {int temp;byte b[] = new byte[2];//中文字符,字节缓存区int i=0;while((temp = inputStream.read())!=-1){//读到有两个字节表示的非 ASCII 字符if(temp>127){b[i]=(byte)temp;if(i==1){i=0;buffer.append(new String(b));}elsei++;}//Ascii 字符else{if((char)temp =='\r')continue;if((char)temp =='\n'){this.line = buffer.toString();return true;}elsebuffer.append((char)temp);}}} catch (IOException e) {e.printStackTrace();}this.line = buffer.toString();if(!this.line.equals("")){return true;}return false;}/** * 返回当前行数据 * @return */public String getMyReadLine(){return this.line;}}



4  总结

    通过对上述的基本操作,明白了数据的存储形式,以及底层的实现方式是基于对单个字节操作,在此基础上实现对字符的操作,为之后学习的各种包装流夯实了基础,以及加强了对编码了的理解。

 

0 0
原创粉丝点击