字符流    
    既然字节流可以操作所有的文件,为什么还有字符流呢
        如果利用字节流,把文本中的中文,读取到内存中,有可能出现乱码
        如果利用字节流,把中文写到文本文件中,也有可能出现乱码
        如果是英文 可以打印出来,中文就会出现乱码
        如果字节流写入到文本中也会出现乱码
    基础知识:
        计算机存储方式的信息是用二进制数表示的
        按照某种规则,将字符变成二进制,再存储到计算机中,称为编码
        按照同样的规则,将存储在计算机中的二进制数解析显示出来,称为解码
        编码和节码的方式必须一致,否之会导致乱码
    简单理解:
            存储一个字符a,首先再码表中查到对应的数字是97,然后转成二进制进行存储
            读取的时候,先把二进制解析出来,再转成97,通过97查找到对应的字符应该是a
    编码表简单理解:
            ASCII字符集:
                ASCII(American Standard Code for Information Interchanae,美国信息交换标准代码):包括了数字,大小写字符和一些常见的标点符号
                注意:ASCII码表是没有中文的
            GBK:
                window系统默认的码表。兼容了ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字
                注意:GBK是中国的码表,一个中文以两个字节的形式存储,但不包含世界上所有国家的文字
            Unicode码表:
                由国际组织ISO定制,是统一的万国码,计算机科学领域里的一项业界标准,容纳世界上大多数国家所有常见的文字和符号
                但是因为表示的字符太多,所以Unicode码表中的数字不是直接以二进制的形式存储到计算机的
                会先通过UTF-7,UTF-7.5,UTF-8,UTF-16,以及UTF-32进行编码,再存储到计算机,其中最为常见的UTF-8
                注意:Unicode是万国码,以UTF-8编码后一个中文以三个字节的形式存储
            
            重点:windows默认使用的码表为:GBK,一个字符两个字节
                idea和其他工具默认使用Unicode的UTF-8的编码格式,一个中文三个字节
            字节串中的编码节码问题
                编码:
                    byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
                    byte[] getBytes(String charsetName):使用用户指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
                解码:
                    String(byte[] bytes):通过使用平台默认的字符集解码指定的字节数组来构造新的String
                    String(byte[] bytes,String charseName):通过指定的字符集节码指定的字节数组来构造新的String
        代码:

public class test15 {public static void main(String[] args) throws UnsupportedEncodingException {//        编码://        byte[] getBytes():使用平台的默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中//        byte[] getBytes(String charsetName):使用用户指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中//String s="我以后一定会称为高级开发";//利用idea默认的UTF-8将中文编码为一系列的字节byte[] bytes=s.getBytes();System.out.println(Arrays.toString(bytes));//[-26, -120, -111, -28, -69, -91, -27, -112, -114, -28, -72, -128, -27, -82, -102, -28, -68, -102, -25, -89, -80, -28, -72,// -70, -23, -85, -104, -25, -70, -89, -27, -68, -128, -27, -113, -111]byte[] bytes1 = s.getBytes("GBK");System.out.println(Arrays.toString(bytes1));//[-50, -46, -46, -44, -70, -13, -46, -69, -74, -88, -69, -31, -77, -58, -50, -86, -72, -33, -68, -74, -65, -86, -73, -94]//        解码:String(byte[] bytes):通过使用平台默认的字符集解码指定的字节数组来构造新的StringString(byte[] bytes,String charseName):通过指定的字符集节码指定的字节数组来构造新的Stringbyte[] bytes2={-26, -120, -111, -28, -69, -91, -27, -112, -114, -28, -72, -128, -27, -82, -102, -28, -68, -102, -25, -89, -80, -28, -72, -70, -23, -85, -104, -25, -70, -89, -27, -68, -128, -27, -113, -111};byte[] bytes3={-50, -46, -46, -44, -70, -13, -46, -69, -74, -88, -69, -31, -77, -58, -50, -86, -72, -33, -68, -74, -65, -86, -73, -94};//默认使用UTF-8进行解析String s1=new String(bytes2);System.out.println(s1);//我以后一定会称为高级开发//利用只当GBK进行解码String s2=new String(bytes3,"GBK");System.out.println(s2);//我以后一定会称为高级开发}}

字节流读取文本文件出现乱码的原因
        因为字节流一次读一个字节,而不管是GBK还是UTF-8一个中文都是多个字符的,而字节流每次只能读取其中一部分,所以就会出现乱码问题
    字符流读取中文的过程
        字符流=字节流+编码表
    基础知识:
        不管再那张码表中,中文的第一个字节一定是负数
    
小结:
    1.想要进行拷贝,一律使用字节流或者字节缓冲流
    2.想要把文本文件中的数据读取到内存中,请使用字符输入流
      想要把内存中的数据写道文本文件中,请使用字符输出流
     3.GBK码表一个中文两个字节,UTF-8编码格式一个中文三个字节
字符流写数据:
    步骤:1.创建字符输出流对象
          2.写数据
          3.释放资源
    字符流写数据的5中方式
        void write(int c)     写一个字符
        void write(char[] cbuf)    写一个字符数组
        void write(char[] cbuf,int off,int len)   写出字符数组的一部分
        void write(String str)    写一个字符串
        void write(String str,int off,int len)    写一个字符串的一部分
代码:

 public class test16 {public static void main(String[] args) throws IOException {//        步骤:1.创建字符输出流对象//        2.写数据//        3.释放资源//                字符流写数据的5中方式//        void write(int c)     写一个字符//字符流的底层就是字节流//下边两种创建方式都可以//FileWriter fw = new FileWriter(new File("fileIo\\a.txt"));FileWriter fw= new FileWriter("fileIo\\a.txt");//写出数据fw.write(98);fw.write(97);fw.write(99);//释放资源fw.close();//        void write(char[] cbuf)    写一个字符数组char[] chars={97,98,99};fw.write(chars);//        void write(char[] cbuf,int off,int len)   写出字符数组的一部分char[] chars1={97,98,99,100};fw.write(chars1,0,2);//从0所以开始写入三个//        void write(String str)    写一个字符串String s="我很厉害No1";fw.write(s);//        void write(String str,int off,int len)    写一个字符串的一部分fw.write(s,0,2);//每次运行完  切记要关掉流  不然你内存多少G都不够   这坑踩过}}

字符流写数据 注意事项 
          1.创建字符输出流对象
            如果文件不存在,就创建,但是要保证父级路径存在
            如果文件存在就清空
          2.写数据
            写出int类型的整数,实际写出的是整数再码表上对应的字母
            写出字符串数据,是把字符串本身原样写出
          3.释放资源    
            每次释放必须关闭,不然电脑内存会直接溢出,直至没有空间继续写
    flush和close方法
            flush()  刷新流,还可以继续写数据
            close()  关闭流,释放资源,但是在关闭之前会先刷新流,一旦关闭,就不能再写数据
    代码:

public class test17 {public static void main(String[] args) throws IOException {//        flush()  刷新流,还可以继续写数据//        close()  关闭流,释放资源,但是在关闭之前会先刷新流,一旦关闭,就不能再写数据FileWriter fw = new FileWriter("test//a.txt");fw.write("阿星在努力");//这个时候运行并不会打印数据// fw.flush();  //fw.write("666");//fw.flush();fw.close();fw.write("aaa");//Stream close}}

字符流读的两种方式
    单个字符读取:

public class test18 {public static void main(String[] args) throws IOException {//创建字符输入流的对象//底层是字节流+编码表// FileReader fr = new FileReader(new File("test\\a.txt"));FileReader fr = new FileReader("fileIo\\a.txt");//读取数据  一次读取一个字符int ch;while ((ch=fr.read())!=-1){System.out.println((char) ch);}//释放资源fr.close();}}

多个字符读取:

public class test19 {public static void main(String[] args) throws IOException {//一次读取多个字符//创建对象FileReader fr = new FileReader("fileIo\\a.txt");//创建一个数组char[] chars = new char[1024];int len;//read 读取  一次读取多个字符//他把读到的字符都存入到了chars数组//返回值:表示本次读到了多少个字符while ((len=fr.read())!=-1){System.out.println(new String(chars,0,len));}fr.close();}}

写一个练习  
            需求:用户输入的用户名和密码保存到本地实现永久化存储  用户名占一行,密码占一行
        步骤:1.写一个键盘录入用户名和密码
              2.将用户名和密码写到本地文件中
        代码:

public class test20 {public static void main(String[] args) throws Exception {//1.键盘录入用户名和密码Scanner sc=new Scanner(System.in);System.out.println("请录入用户名");String username = sc.next();System.out.println("请录入密码");String password = sc.next();//2.分别把用户名和密码写到本地文件FileWriter fw = new FileWriter("filelo\\a.txt");//将用户名和密码写到文件中fw.write(username);//写出一个回车换行符fw.write("\r\n");fw.write(password);//刷新流fw.flush();//释放资源fw.close();}}

字符缓冲流 
        BufferedWriter:可以将数据高效的写出
        BufferedReader:可以将数据高效的读取到内存
    代码实例:

public class test21 {public static void main(String[] args) throws IOException {//字符缓冲输入流BufferedReader br=new BufferedReader(new FileReader("filelo\\a.txt"));//读取数据char[] chars=new char[1024];int len;while ((len=br.read())!=-1){System.out.println(new String(chars,0,len));}br.close();}}    

字符缓冲输出流
        BufferedWrited:可以将数据高效的写出
        BufferedReader:可以将数据高效的读取到内存
    构造方法:
        BufferedWrited(Writer out);
        BufferedReader(Reader in);
    代码:

public class test22 {public static void main(String[] args) throws Exception {//字符缓冲输出流BufferedWriter bw=new BufferedWriter(new FileWriter("filelo\\a.txt"));//写出数据bw.write(98);char[]  chars=new char[1024];bw.write(chars);bw.write(chars,0,3);bw.write("有梦终会达");String s="adsafsa";bw.write(s,0,3);bw.flush();bw.close();}}

字符缓冲流特有功能
        BufferedWrited:
            void newLine(): 写一行行分隔符,行分隔符字符串由系统属性定义
        BufferedReader:    
            public StringReadLine():读一行文字,结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾以及到达,则为null
    代码实例:

 public class test23 {public static void main(String[] args) throws Exception {//创建对象BufferedWriter bw = new BufferedWriter(new FileWriter("filelo\\a.txt"));//写出数据bw.write("在黑夜里发光");//跨平台的回车换行bw.newLine();bw.write("asdasd");bw.newLine();bw.write("153123");//刷新流 释放资源bw.flush();bw.close();}}

代码实例:
        public class test24 {
            public static void main(String[] args) throws Exception {
                //创建对象
                BufferedReader br=new BufferedReader(new FileReader("filelo\\a.txt"));
                //读取数据
                //在之前,读不到数据返回就是-1,显示现在readLine方法读不到数据就返回null
                String line = br.readLine();
                String line1 = br.readLine();
                String line2 = br.readLine();
                System.out.println(line);
                System.out.println(line1);
                System.out.println(line2);//如果这一行没有数据  就在控制台输出null
                //释放资源
                br.close();
            }
        }
    用循环做一个改进

public class test25 {public static void main(String[] args)throws Exception {//创建对象BufferedReader br=new BufferedReader(new FileReader("filelo\\a.txt"));//读取数据//在之前,读不到数据返回就是-1,显示现在readLine方法读不到数据就返回nullString line;//可以读取一整行数据,一直都,读到回车换行为止//但是他不会读取回车换行符while ((line=br.readLine())!=null){System.out.println(line);}//释放资源br.close();}}

案例:读取文件中的数据排序后再次写到本地  文件中的数据 9 8 2 4 3 1 5 3
    1.读取数据
    2.排序
    3.写到本地
    代码:

public class test26 {public static void main(String[] args) throws Exception {//        1.读取数据BufferedReader br=new BufferedReader(new FileReader("filelo\\a.txt"));这个不能提前创建  如果a.txt 有东西  会直接清空 不能写道BufferedReader定义的下一行//BufferedWriter bw=new BufferedWriter(new FileWriter("filelo\\a.txt"));String line=br.readLine();System.out.println("读取到的数据为"+line);br.close();//        2.排序//按照空格进行切割String[] s = line.split(" ");//把字符串类型的数组变成int类型int[] arr=new int[s.length];//遍历s数组,可以进行类型转换for (int i = 0; i < s.length; i++) {String smallStr= s[i];int number = Integer.parseInt(smallStr);//把转换后的结果存到arr中arr[i] =number;}Arrays.sort(arr);System.out.println(Arrays.toString(arr));//        3.写到本地BufferedWriter bw=new BufferedWriter(new FileWriter("filelo\\a.txt"));for (int i = 0; i < arr.length; i++) {bw.write(arr[i]+" ");bw.flush();}bw.close();}}

I
    转换流:
        转换输入流:InputStreamReader
        转换输出流:OutputStreamWriter
    转换流的使用场景
            JDK11之前,指定编码读写
    之前的方法会产生乱码

public class test27 {public static void main(String[] args) throws IOException {//这个方法直接读取会产生乱码//因为文件时GBK码表//而IDEA 默认时UTF-8  所以两者不一致  就会出现乱码FileReader fr = new FileReader("D:\\a.txt");int ch;while ((ch=fr.read())!=-1){System.out.println((char) ch);}fr.close();}
}

转换流的实例:

public class test27 {public static void main(String[] args) throws IOException {//第二个参数 大小写都可以 指定编码读InputStreamReader isr = new InputStreamReader(new FileInputStream("D\\a.txt"), "GBK");int ch;while ((ch=isr.read())!=-1){System.out.println((char) ch);}isr.close();OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("D\\a.txt"),"GBK");osw.write("我爱学习");osw.close();//JDK11之后,字符流新推出了一个构造,也可以指定编码表FileReader fr = new FileReader("D\\a.txt", Charset.forName("gbk"));int ch1;while ((ch1=isr.read())!=-1){System.out.println((char) ch1);}}
}

对象操作流 
        特点:可以把对象以字节的形式写道本地文件,直接打开文件,是读不懂的,需要再次用对象操作流读到内存中
    对象操作流分为两类:对象操作输入流和对象操作输出流
    对象操作输出流(对象序列化流):就是将对象写到本地文件中,或者网络中传输对象
    对象操作输入流(对象反序列化流):把写到本地文件中的对象读取到内存中,或者接收网络中传输的对象


序列化代码  
    User类:            public class User implements Serializable {
    //如果这个类的对象能被序列化,那么这个类必须要实现一个Serializable接口
    //Serializable  称之为一个标记性接口,里面没有任何抽象方法  只要一个类实现了这个接口,那么就表示这个类的对象可以被序列化

 private String username;private String password;public User() {}public User(String username, String password) {this.username = username;this.password = password;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

测试类代码:

public class test28 {public static void main(String[] args) throws Exception {User user=new User("zhangsan","abc");ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("a.txt"));oos.writeObject(user);oos.close();}
}

对象反序列化

public class test29 {public static void main(String[] args) throws Exception {ObjectInputStream ois=new ObjectInputStream(new FileInputStream("a.txt"));User o = (User) ois.readObject();System.out.println(o);ois.close();}
}

注意点:用对象序列化一个对象后,假如我们修改了对象所属的Javabean类,读取会出现问题
        SerialVersionUID 序列化 
        如果我们自己没有定义,那么虚拟机会根据类中的信息自动计算出一个序列号
        如果我们修改了类中的信息,虚拟机就会再次计算出一个序列号
        第一步  把User对象序列化到本地  虚拟机会创建一个序列号
        第二步  修改了javabean类  导致虚拟机重新创建了一个序列号,两者不一致
        第三步 把文件中的对象读到内存,本地中的序列号和类中的序列号就不一致了
        解决 
        不让虚拟机帮我们计算,我们手动给出,而且这个值不变
        
        在User类中加入  private  static final long serialVerSionUID =1L;

public class User implements Serializable {//如果这个类的对象能被序列化,那么这个类必须要实现一个Serializable接口//Serializable  称之为一个标记性接口,里面没有任何抽象方法  只要一个类实现了这个接口,那么就表示这个类的对象可以被序列化//    SerialVersionUID 序列化
//    如果我们自己没有定义,那么虚拟机会根据类中的信息自动计算出一个序列号
//    如果我们修改了类中的信息,虚拟机就会再次计算出一个序列号
//    第一步  把User对象序列化到本地  虚拟机会创建一个序列号
//    第二步  修改了javabean类  导致虚拟机重新创建了一个序列号,两者不一致
//    第三步 把文件中的对象读到内存,本地中的序列号和类中的序列号就不一致了
//            解决
//    不让虚拟机帮我们计算,我们手动给出,而且这个值不变private  static final long serialVerSionUID =1L;private String username;private String password;public User() {}public User(String username, String password) {this.username = username;this.password = password;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", password='" + password + '\'' +'}';}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}

IO.2(须知少时凌云志,曾许人间第一流)相关推荐

  1. 须知年少凌云志 曾许人间第一流

    我的第一篇博客,新的开始,记录点滴学习历程~ 欢迎你的到来~ 我是(Who am I?) 今年19岁的我,是一名双非院校IT领域(实际的专业是最近几年特别火热的人工智能)的既平凡又普通大二在读本科生: ...

  2. 须知少年凌云志,曾许天下第一流

    岁月如梭,韶光易逝.重回首,去时年,揽尽风雨苦亦甜.夜阑珊,读无眠,听尽春言,每天都是新的一片,不再清闲,望着洒满月光的星星一路向前. 余忆年少时,天真无邪,意气风发,或青衫白马仗剑天涯,或洋洋洒洒, ...

  3. 少时须有凌云志,曾许天下第一流!!!

    About my first blog: a:About myself: 我是来自武工大的一名21级小萌新,对编程有着浓烈的兴趣爱好^^(简单的介绍一下 b:Goal: 目标嘛,想必大家都一样!!(进 ...

  4. 2019科学突破奖揭晓 庄小威陈志坚许晨阳上榜

    来源:科学网 10月17日,科学突破奖(Breakthrough Prize)名单揭晓.总计2200万美元的奖金分别给了婴儿死亡主要遗传因素治疗.超分辨率成像.发现一种新型电子材料以及其他重大突破. ...

  5. 陈玉龙:永怀少年心 不改凌云志

    点击查看活动详情:https://t.csdnimg.cn/L4B8 社区介绍: CSDN高校俱乐部是公益性技术社团,以提升高校大学生技术能力.为行业提供人才储备.为国家数字化战略贡献力量为使命,链接 ...

  6. 拟合算法(模型+代码)

    拟合的结果是得到一个确定的曲线 最小二乘法的几何解释: argmin 存在参数k,b使括号里的值最小 第一种有绝对值,不易求导(求导在求最小值),计算较为复杂:所以我们往往使用第二种定义,也正是最小二 ...

  7. 轻松简单实现Android设备重启的两种方式

    " 须知少时凌云志,曾许人间第一流 " 在<风犬少年的天空>中刘闻钦下线时,嘴里念叨的就是这句,我们何尝不是这样的人呢,年轻时的凌云大志,曾决心要做人间第一流的人物,干 ...

  8. 长大后的我们为何贪恋年少?

    长大后的我们,之所以会再次贪恋年少的日子,是因为我们贪恋的其实不是时间,而是年少时纯粹的灵魂和懵懂的情愫. 最简单的情愫往往震慑心扉,回味起来,温柔又轻盈-- 而这种真切的情愫,在经历了数十年的人生之 ...

  9. 断章取义:时光不负有心人

    知识来源:网络 星光不问赶路人, 时光不负有心人, 你只管努力, 上天自有安排 <易经>有云:"取法乎上,仅得其中:取法乎中,仅得其下:取法其下,无所得矣." 求其上者 ...

最新文章

  1. 教你辨别36k纯数据科学家
  2. PLSQL的DBMS_GETLINE
  3. Button的使用(六):ToggleButton
  4. Py之twisted:Python库之twisted简介、安装、使用方法等详细攻略
  5. if you canget up early
  6. 如何恢复ORACLE数据(冷备份)
  7. relative与absolute相结合
  8. [BAT] 执行xcopy命令后出现Invalid num of parameters错误的解决办法
  9. pyinstaller安装_如何打包Python Web项目,实现免安装一键启动?
  10. mysql工具分页原理_高效的mysql分页方法及原理
  11. Oracle中级篇-物化视图
  12. html ubb c,UBB代码和HTML代码的区别
  13. Ubuntu安装Yafu方法及资料
  14. 怪兽充电启动招股:2020年业绩下滑五成,小米、高瓴参与认购
  15. Zemax操作--7(坐标断点)
  16. 程序员和码农有什么不同?从这三个单词就看得出来
  17. 微信 客服消息 发送 微信会回调三次的问题
  18. 微信扫描PC端二维码跳转到小程序确认登录通过WebSocket来获取用户信息达到PC端登录
  19. 基于angularjs的单页面实例_angularjs网站开发实例
  20. 国产服务器上(银河麒麟)上玩转Golang

热门文章

  1. 在word中制作书签
  2. 强大的Http监控工具Fidder
  3. 垃圾回收你懂,Java垃圾回收你懂吗?
  4. 电子手轮 (位置跟随,X轴或Y轴) 200smart、威纶通触摸屏
  5. 小程序 | mpvue如何启动小程序和各个小程序的配置
  6. Ibatis 大于小于符号
  7. 搞清FT , DFT , DTFT , DFS之间的关系
  8. 使用Spring-Cloud-Config创建配置中心
  9. 固定资产管理系统能帮助企业解决哪些问题?
  10. BEM 命名规范简介