# Day15-Java基础
Day15-Java
文章目录
- Day15-Java
- 1、字符编码
- 1.1 常用字符编码
- 1.2 乱码产生分析
- 2、内存流基本操作
- 3、打印流
- 3.1 格式化文本信息
- 4、 System类
- 4.1 系统输出
- 4.2 系统输出
- 4.3 系统输入
- 5、BufferedReader类
- 6、Scanner
- 7、对象序列化
- 7.1 对象序列化的概念
- 7.2 实现序列化和反序列化
- 7.3 transient关键字(了解)
1、字符编码
1.1 常用字符编码
在计算机的世界之中,所有的显示文字都是按照其指定的数字编码进行保存的,如果没有正确的解码,那么就坑你产生乱码,如果要想清楚解决乱码问题,就要了解经常见到一些常见的编码:
GBK/GBK2312:表示国标中文编码,其中GBK是包含简体中文和繁体中文,而GB2312只有简体;
ISO 8859-1:是一种国际通用编码,可以表示任何文字,但是对于中国文字需要进行转码;
UNICODE:使用十六进制完成的编码,可以准确的表示出任何的语言文字;
UTF-8:部分编码使用UNICODE,而一些编码继续使用像ISO 8859-1,类型的编码,适合于网络传输,在以后的所有的项目开发之中,都必须采用此编码。可是考虑到日后学习的方便,几乎都会使用命令行进行操作,所以命令行只支持GBK编码,UTF不支持,一旦程序设置了UTF编码,那么通过命令行查看就是乱码。
在开发之中经常会遇见乱码的问题,所谓的乱码的核心在于编码和解码不统一。如果要想正确的避免项目之中出现的乱码,那么首先就应该知道环境之中所支持的编码是什么。
1.2 乱码产生分析
读取Java运行属性
package com.day15.demo;public class ListDemo {public static void main(String[] args) {System.getProperties().list(System.out);}
}
这个时候显示出来的信息是很多的,这里面有专门的编码选项“file.encoding=GBK”,也就是说如果没有任何的意外,所有的文字编码都是GBK。
改变编码
package com.day15.demo;import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;public class ListDemo {public static void main(String[] args) throws Exception{OutputStream out = new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "hello.txt"),true);out.write("世界和平".getBytes());out.close();}
}
2、内存流基本操作
在讲解之前首先来思考一个问题:就是如果现在某个操作必须发生IO,但有不希望有一些临时文件产生的话,那么现在肯定无法使用之前的文件操作流,所以为了解决这样的问题,提供了内存操作流,即:以内存进行操作的终端,以发生IO操作关系。
对于内存操作流也分为两组:
**字节内存操作流:**内存输入流(ByteArrayInputStream)内存输出流(ByteArrayOutputStream)
**字符内存操作流:**内存输入流(CharArrayReader)内存输出流(CharArrayWriter)
ByteArrayInputStream | ByteArrayOutputStream |
---|---|
java.lang.Object java.io.InputStream java.io.ByteArrayInputStream |
java.lang.Object java.io.OutputStream java.io.ByteArrayOutputStream |
public ByteArrayInputStream(byte[] buf) | public ByteArrayOutputStream() |
输出流
输入流
通过内存实现大小写转换的操作
package com.day15.demo;import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream;public class MemoryDemo {public static void main(String[] args) throws Exception{String str = "Hello,World!";InputStream in = new ByteArrayInputStream(str.getBytes());OutputStream out = new ByteOutputStream();int temp = 0;while((temp = in.read())!=-1){out.write(Character.toUpperCase(temp));}in.close();out.close();System.out.println(out.toString());}
}
此过程我们发现没有文件的产生,而此过程只不过是产生了临时文件。
3、打印流
如果说想在要想输出数据,肯定使用OuputStream或者是Writer,那么请问,这两个操作类在执行输出的时候你认为它好用吗?
打印流主要解决的就是OutputStream缺陷,属于OutputStream加强版,如果现在操作不是二进制的数据,只是通过程序向终端目标输出信息。OutputStream并不方便。
缺点一:所有的数据必须变为字节数组
缺点二:只支持String类型,输出int、double就不方便
如果现在要想输出字符串,使用Writer可以直接输出,而使用OutputStream还需要将字符串变为字节数组,那么如果现在要想输出数字(int型或double型),还需要将这些数据先变为字符串,之后再变为字节数组输出,多以,如果用户直接调用OutputStream或Writer输出的时候本身并不方便,所以在这个时候可以想办法将OutputStream或Writer变得加强一些,定义一个专门的工具类:PrintUtil.java。
编写一个输出功能类PrintUtil类
package com.day15.demo;import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;class PrintUtil{OutputStream out;public PrintUtil(OutputStream out){this.out=out;}public void print(String str) throws Exception{this.out.write(str.getBytes());}public void println(String str) throws Exception{this.print(str.concat("\r\n"));}public void print(int num) throws Exception{this.print(String.valueOf(num));}public void println(int num) throws Exception{this.println(String.valueOf(num));}
}
public class PintUtilDemo {public static void main(String[] args) throws Exception {PrintUtil printUtil = new PrintUtil(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")));printUtil.println("姓名:" + "张麻子");printUtil.print("年龄");printUtil.print(19);}
}
以后使用PrintWriter的使用率挺高,但是这两者的使用形式相同的。首先观察这两个类的继承结构和构造方法:
首先来观察一下PrintStream,PrintWriter的继承结构和构造方法:
PrintStream | PrintWriter |
---|---|
java.lang.Object java.io.OutputStream java.io.FilterOutputStream java.io.PrintStream |
java.lang.Object java.io.Writer java.io.PrintWriter |
public PrintStream(OuputStream out) | public PrintWriter(Writer out) |
看见以上的结构,可能第一反应就属于代理设计模式,但它并不是代理,代理设计模式的特点:以接口为使用原则,用户调用代理主题方法的时候依然是接口之中定义的方法。而此时PrintStream类调用的绝对不是OutputStream类之中定义的一系列write()方法。虽然PrintStream在外表操作上产生了变化,但实际上依然执行的是OutputStream累哦所定义的操作,所以本质没有发生变化,只是提供了一些更加方便的功能支持,多以这种设计模式上讲称为装饰设计模式。
3.1 格式化文本信息
在JDK1.5之后,打印流也进行了更新,增加了一个新的方法,格式化输出:
格式化输出:public PrintStream printf(String format,Object… args)
当看到此方法名称的时候首先想到的是C语言中的输出,而现在Java也具备了同样的功能,而输出的时候可以使用一些标记表示要输出的内容,例如:字符串(%s),数字(%d)小数(%m.nf),字符(%c)等。
观察格式化输出
package com.day15.demo;import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;public class PrintWriterDemo {public static void main(String[] args) throws Exception{PrintWriter pu = new PrintWriter(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")),true);String name = "张麻子";int age=23;double score=8123219.127456;pu.printf("姓名:%s 年龄:%d 成绩:%7.2f",name,age,score);}
}
而在JDK1.5之后增加字符串格式化操作类不光有PrintStream,还有String类,String类也提供了一个格式化字符串的操作方法:public static String format(String format,Object… args)
格式化字符串
package com.day15.demo;import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;public class PrintWriterDemo {public static void main(String[] args) throws Exception{PrintWriter pu = new PrintWriter(new FileOutputStream(new File("f:" + File.separator + "test" + File.separator + "test.txt")),true);String name = "张麻子";int age=23;double score=8123219.127456;String str = String.format("姓名:%s 年龄:%d 成绩:%7.2f",name,age,score);System.out.println(str);}
}
虽然格式化字符串可以执行准确的四舍五入操作,但是这种处理完的数据都是String型,而实际工作中,如果要四舍五入,肯定还是要编写BigDecimal类完成。
以后只要是程序输出数据的操作,都使用PrintStream类。
4、 System类
在我们学习完了PrintWriter、PrintStream之后我们会发现里面的方法都很熟悉,例如print()、println()输出就利用我们的IO流模式完成的。在System类中实际上定义有三个操作的常量。
public static final PrintStream out | 标准输出 |
---|---|
public static final PrintStream err | 错误输出 |
public static final InputStream in | 标准输出 |
4.1 系统输出
系统输出我们发现一共有两个常量:out、err,而且这两个常量所表示的都是PrintSream的对象。从
Java设计的本质上来讲这样的输出有以下设计的目的。out是希望输出的用户可以看见的内容
,err是希望输出用户不能够看见的内容。
package com.day15.demo;public class PrintDemo {public static void main(String[] args) throws Exception{try{Integer.valueOf("abc");}catch(Exception e){System.err.println(e);System.out.println(e);}}
}/*
java.lang.NumberFormatException: For input string: "abc"
java.lang.NumberFormatException: For input string: "abc"
*/
4.2 系统输出
系统输出是将所有的信息输出到指定的输出设备上——显示器。而System.out本身是属于PrintStream对象,而PrintStream是OutputStream子类,所以现在实际上可以利用System.out为OutputStream类执行实例化操作。
package com.day15.demo;import java.io.OutputStream;
public class PrintDemo {public static void main(String[] args) throws Exception {String str ="hello,world";OutputStream output = System.out;//System.out为OutputStream实例化output.write(str.getBytes());}
}
本程序没有任何的意义,而讲解的主要目的就希望可以理解:OutputStream会根据实例化它的子类或对象的不同,输出的位置也不同。
4.3 系统输入
系统输入针对于标准的输入设备——键盘,也就是俗称的键盘输入数据,但是System.in返回的是InputStream型的数据,所以下面编写一个操作由键盘输入数据。
package com.day15.demo;import java.io.IOException;
import java.io.InputStream;public class inDemo {public static void main(String[] args) throws Exception {InputStream input = System.in;System.out.println("请输入!");byte data[] = new byte[1024];int len = input.read(data);System.out.println(new String(data,0,len));}
}
除了实例化InputStream类的对象不同之外,其他的地方和之前文件输入数据没有任何区别,但是这个程序本身有问题,已经开辟的空间大小是1024,如果输入的数据超过1024呢?发现只会接收满足指定长度的数据,程序有bug,那么最好的解决方法是不设置长度,输入一个读取一个,一直到用户不输入为止。
package com.day15.demo;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;public class inDemo {public static void main(String[] args) throws Exception {InputStream input = System.in;//为父类实例化ByteArrayOutputStream bos = new ByteArrayOutputStream();byte data[] = new byte[10];//开辟一个空间System.out.println("请输入!");int temp = 0;while((temp = input.read(data))!=-1){//数据读取到字节数//这里面要用户自己来处理换行问题bos.write(data,0,temp);//保存在内存输出流if(temp < data.length){break;}}System.out.println(new String(bos.toByteArray()));}
}
简化操作,但是中文无法识别
package com.day15.demo;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;public class inDemo {public static void main(String[] args) throws Exception {InputStream input = System.in;//为父类实例化StringBuffer buf = new StringBuffer();System.out.println("请输入!");int temp = 0;while((temp = input.read())!=-1){//数据读取到字节数//这里面要用户自己来处理换行问题if(temp == '\n'){break;}buf.append((char)temp);}System.out.println(buf);}
}
通过以上比较可以感受到System.in的支持度原本不高,对于英文的操作是支持,但是对于中文是不太友好的,对于中文的输出还必须借助内存流来实现的。
5、BufferedReader类
BufferedReader属于一个缓冲的输入流,而且是一个字符流的操作对象。但是必须清楚一点就是对于我们的缓存流定义有两类:字节缓冲流( BufferedInputStream )、字节缓冲流( BufferedReader )。
如果说想在把所有的输入数据放在一起了,一次性读取出来,那么这个时候肯定就能够避免中文问题了,而这一操作就必须依靠缓冲区操作流完成。对于缓冲区的读取在IO包中定义了两种类:BufferedInputStream,BufferedReader,但是考虑到本次操作有中文的问题,肯定使用BufferedReader类完成操作。下面就需要观察一下BufferedReader类的继承结构,构造方法,操作方法:
继承结构: |
java.lang.Object java.io.Reader java.io.BuffereedReader |
---|---|
构造方法: | public BuffereedReader(Reader in) |
读取操作: | public String readLine() throws IOException |
之所以选择BufferReader类操作提供的readLine()方法,这个方法可以读取一行数据以回车为准。
使用BufferedReader进行数据读取
package com.day15.demo;import java.io.BufferedReader;
import java.io.InputStreamReader;public class BufferReaderDemo {public static void main(String[] args) throws Exception{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入");//默认的换行模式是BufferReader最大的缺点String str = bufr.readLine();//接受输入信息,默认使用回车换行System.out.println(str);}
}
对输入的数据进行验证,判断是否是数字
package com.day15.demo;import java.io.BufferedReader;
import java.io.InputStreamReader;public class BufferReaderDemo {public static void main(String[] args) throws Exception{BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入年龄");//默认的换行模式是BufferReader最大的缺点String str = bufr.readLine();//接受输入信息,默认使用回车换行if(str.matches("\\d{1,3}"))System.out.println(str);elseSystem.out.println("输入数据有误!");}
}
6、Scanner
这个类是作为了一个工具类出现的,在Scanner之中定义两个如下的一些方法:
public Scanner(InputStream sourse); | 构造方法 |
---|---|
public Boolean hasNextXxx(); | 判断是否有数据 |
public 数据类型 nextXxx(); | 取得数据 |
public Scanner useDelimiter(String partern); | 定义分隔符 |
以后调用的时候在执行nextXxx()之前一定要首先使用hasNextXxx()判断是否有指定格式的数据出现。
通过Scanner类进行数据的输入
package com.day15.demo;import java.util.Scanner;public class ScannerDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入数据:");if(sc.hasNext()){//现在有输入的内容,不能判断空字符串System.out.println(sc.next());}sc.close();}
}
使用Scanner类判断输入数据是否是int型数据
package com.day15.demo;import java.util.Scanner;public class ScannerDemo {public static void main(String[] args) {System.out.println("请输入数据:");Scanner sca=new Scanner(System.in);if(sca.hasNextInt()){int date=sca.nextInt();System.out.println("输入的数据是:"+date);}else{System.out.println("输入的不是数字");}}
}
在Scaner类之中,useDelimiter()方法的输入针对于字符串,但是其他的数据类型并不方便使用。
使用Scanner类判断用户输入的是不是生日
package com.day15.demo;import java.util.Scanner;public class ScannerDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入生日:");if(sc.hasNext("\\d{4}-\\d{2}-\\d{2}")){//现在有输入的内容,不能判断空字符串String bir = sc.next("\\d{4}-\\d{2}-\\d{2}");System.out.println(bir);}sc.close();}
}
Scanner读取文件内容
package com.day15.demo;import java.io.File;
import java.io.FileInputStream;
import java.util.Scanner;public class ScannerDemo {public static void main(String[] args) throws Exception{Scanner sc = new Scanner(new FileInputStream(new File("f:" + File.separator + "test" + File.separator + "hello.txt")));sc.useDelimiter("\n");if(sc.hasNext()){//现在有输入的内容,不能判断空字符串System.out.println(sc.next());}sc.close();}
}
除了二进制文件拷贝处理之外,只要针对于程序的信息输出都使用打印流,对于信息的输入都是Scanner。
7、对象序列化
所有的项目都一定有序列化的概念。
7.1 对象序列化的概念
所谓的对象序列化是指在内存中保存的对象变为二进制流的形式进行传输,或者将其保存在文本中。但是我们并不意味着所有对象都可以被序列化,严格来讲,我们需要被实例化的类对象往往需要传输使用,同时这个类 必须实现java.io.Serializable接口。但是这个接口没有任何方法定义,所以只是一个标识。
package com.day15.demo;import java.io.Serializable;class Person implements Serializable{private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}
public class SerializableDemo {}
序列化对象是所需要保存的就是对象中的属性所以默认情况下对象的属性将被转为二进制数据流存储。
7.2 实现序列化和反序列化
如果要想进行对象的序列化和反序列话的手工操作,在java之中提提供了两个操作类:ObjectOutputStream,ObjectInputStream,而这两个类的继承结构,构造方法,操作方法定义如下:
ObjectOutputStream | ObjectInputStream |
---|---|
java.lang.Object java.io.OutputStream java.io.ObjectOutputStream |
java.lang.Object java.io.InputStream java.io.ObjectInputStream |
public ObjectOutputStream(OutputStream out) throws IOException |
public ObjectInputStream(InputStream in) throws IOException |
public final void writeObject(Object obj) throws IOException |
public final Object readObject() throws IOException,ClassNotFoundException |
实现对象的序列化操作
package com.day15.demo;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;class Person implements Serializable{private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}
}
public class SerializableDemo{public static final File FILE = new File("F:" + File.separator + "test" + File.separator + "person.txt");public static void ser(Object o) throws Exception {ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(FILE));outputStream.writeObject(o);outputStream.close();}public static void dser() throws Exception {ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(FILE));System.out.println(inputStream.readObject());inputStream.close();}public static void main(String[] args) throws Exception{//序列化//ser(new Person("张麻子",20));//反序列化dser();}
}
如果出现com.day15.demo.Person@6d311334这个情况的主要原因是因为实体类没有进行toString()方法的重写。
7.3 transient关键字(了解)
实际上序列化的处理在Java.io有两类,Serializable是使用最多的序列化接口,这种操作采用自动化的模式完成,默认情况下所有的属性都会进行序列化。有一个Externalizable接口需要用户手动序列化处理。
由于默认情况Serializable会将对象中的所有属性进行保存,但是如果现在有某些属性不希望被保存了,那么可以使用transient关键字。
使用transient
package com.day15.demo;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Arrays;class Person implements Serializable{private transient String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}
}
public class SerializableDemo{public static final File FILE = new File("F:" + File.separator + "test" + File.separator + "person.txt");public static void ser(Object o) throws Exception {ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(FILE));outputStream.writeObject(o);outputStream.close();}public static void dser() throws Exception {ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(FILE));System.out.println(inputStream.readObject());inputStream.close();}public static void main(String[] args) throws Exception{ser(new Person("张麻子",20));dser();}
}
/*
Person [name=null, age=20]
*/
发现此处name没有进行序列化操作。使用序列化往往在简单java类上使用,其他类上使用序列化的使用很少,但是在简单java类中基本上不去使用transient。
# Day15-Java基础相关推荐
- day15 java基础(Collection类,List类,Object类)
-----------------------------------day15 总结------------------------------------------------- 1:对象数组( ...
- Java基础day15
Java基础day15 Java基础day15-集合2 1.Set集合 1.1Set集合概述和特点 1.2哈希值 1.3HashSet集合概述和特点 1.4HashSet集合保证元素唯一性源码分析 1 ...
- Java基础入门语法和安装
1. Java概述 1.1 Java语言背景介绍(了解) 语言:人与人交流沟通的表达方式 计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言 Java语言是美国Sun公司(Stanford Un ...
- Java笔记整理-02.Java基础语法
1,标识符 由英文字母.数字._(下划线)和$组成,长度不限.其中英文字母包含大写字母(A-Z)和小写字母(a-z),数字包含0到9. 标识符的第一个字符不能是数字(即标识符不能以数字开头). 标识符 ...
- java基础(十三)-----详解内部类——Java高级开发必须懂的
java基础(十三)-----详解内部类--Java高级开发必须懂的 目录 为什么要使用内部类 内部类基础 静态内部类 成员内部类 成员内部类的对象创建 继承成员内部类 局部内部类 推荐博客 匿名内部 ...
- Java基础概念性的知识总结
属于个人的所学的知识总结,不是全面的 1.JDK.JRE和JVM三者的区别 01.JDK:(Java Development ToolKit)Java开发工具包,是整个Java的核心.包括了Java的 ...
- 我的面试标准:第一能干活,第二Java基础要好,第三最好熟悉些分布式框架!...
点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:hsm_computer www.cnblogs.com/J ...
- 叮!您收到一份超值Java基础入门资料!
摘要:Java语言有什么特点?如何最大效率的学习?深浅拷贝到底有何区别?阿里巴巴高级开发工程师为大家带来Java系统解读,带你掌握Java技术要领,突破重点难点,入门面向对象编程,以详细示例带领大家J ...
- java重要基础知识点_必看 | 新人必看的Java基础知识点大梳理
原标题:必看 | 新人必看的Java基础知识点大梳理 各位正在认真苦学Java的准大神,在这烈日炎炎的夏季里,老九君准备给大家带来一个超级大的"冰镇西瓜,"给大家清凉一下,压压惊. ...
- Java基础-Date类常用方法介绍
Java基础-Date类常用方法介绍 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.毫秒值概念 我们在查阅Date类的API文档时,会发现这样的一句话:"The cl ...
最新文章
- python2018上海脱产_python接口自动化27-urlencode编码%E6%82%A0%E6%82%A0与解码
- flex buider 4.6 打开设计模式(designer)时提示内存不足错误的解决办法
- 学C++的你今天鄙视PHP了吗?
- linux查看消息队列的状态,linux – 如何知道某个时间点在消息队列中收到的消息数...
- 1022: [SHOI2008]小约翰的游戏John - BZOJ
- MAC下安装和管理java
- 阿里云飞天洛神:高性能网络软硬件一体化技术实践 | 凌云时刻
- python内置的字典dict中元素_Python内置字典;dict ,set
- 图的深度优先遍历和广度优先遍历
- 夜深人静写算法——01背包(动态规划)
- 微信刷票怎么查实_怎么检查“微信公众平台投票”是否有刷票?
- 基于PaddleX构建专属行车助手,为交通安全保驾护航
- TP5 生成微信小程序海报图
- php上传公众号临时素材-微信开发素材管理6
- Neutron OVS-DVR
- thinkpad T480 ubuntu 16.04安装无线网卡rtl8821ce驱动
- 基于51单片机十字路口交通信号灯(启动按键+绿灯同亮报警)
- Opencv或python中图像与三维数组原理
- linux 中的 ln 命令,Linux ln命令操作指南
- 英语发音规则---E字母常见的发音组合有哪些