后台用printwriter输出javascript代码_标准输入输出流以及序列化

标准输入流http://System.in

源数据源是标准输入设备(键盘、鼠标、触摸屏)等输入设备。在java中用http://System.in 得到一个InputStream字节输入流。

例如,在控台输入一句话,然后原样输出。

public static void main(String[] args) throws IOException {
  // 需求:输入一句话,然原样输出
  InputStream in = System.in;
  
  byte[] buf = new byte[1024];
  int len;
  // buf中包含回车和换行
  len = in.read(buf);
  
  String str = new String(buf, 0, len);
  // System.out.println(Arrays.toString(buf));
  System.out.println(str);
 }

System 类包含一些有用的类字段和方法。它不能被实例化。 里面提供的方法都是静态方法。

注意: 标准输入流以字节流流入内存,如果在控制台中输入字符,字符以默认编码(win简体:gbk)编码成字节进入标准输入流。win7系统的话默认编码为GBK。Linux系统则为UTF-8。

也可以用http://System.in来高效的读取一行数据。

  InputStream in = System.in;
  InputStreamReader reader = new InputStreamReader(in, "GBK");
  BufferedReader br = new BufferedReader(reader);

标准输出流(PrintStream)

数据目的地是标准输出设备(显示器)等输出设备。在java中用System.out得到一个PrintStream 字节输出流(字节打印流)。提供了更强大的 print、println 打印方法用于打印各种数据类型。

比如读取某个文件的内容并打印出来,显示到标准的输出设备。

public static void main(String[] args) throws IOException {
  
  File file = new File("d:javatestk.txt");
  
  FileReader reader = new FileReader(file);
  BufferedReader br = new BufferedReader(reader);
  
  PrintStream ps = System.out;
  
  String line;
  while( (line=br.readLine())!=null ) {
   ps.println(line);
  }
 }

注意:PrintStream打印的所有字符都用默认字符编码转换为字节。

public class Test03 {
	public static void main(String[] args) throws IOException {
		
		
		String str = "hello中国";
		byte[] buf = str.getBytes("utf-8");
		
		PrintStream ps = System.out;
		ps.write(buf);
		
	}
}

因为我用的是win10系统,所以默认的编码为GBK,程序中的buf使用的是UTF-8编码集,程序输出后得到的结果如下图

5c87767082c65a5ca5473f707d417502.png

所以进行解码后会出现乱码的现象。

PrintWriter

PrintWriter继承于Writer,所以可以得知PrintWriter是一个字符打印输出流。查API得知,此类实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法。

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class Test01 {
	public static void main(String[] args) throws FileNotFoundException {
		File file = new File("e:javateste.txt");
		PrintWriter pw = new PrintWriter(file);
		pw.write("hello java");
		
		pw.flush();
		pw.close();
	}

}

可以通过write来对文件进行写入。和其他的字符输入流一样需要flush刷新。

如果想要写入以UTF-8的字符集写入文件,构造方法也提供了

938e91d54f2f3e7eb86f54ad1c769fd2.png

也可以直接用print来打印到后台显示,如下代码

import java.io.FileNotFoundException;
import java.io.PrintWriter;

public class Test01 {
	public static void main(String[] args) throws FileNotFoundException {
		PrintWriter pw = new PrintWriter(System.out);
		pw.print(10);
		pw.close();
	}

}

序列化

把内存中的对象永久保存到硬盘的过程称为对象序列化,也叫做持久化。

把硬盘持久化的内存恢复的内存的过程称为对象反序列化。

Serializable接口

类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化,并抛出异常

Exception in thread "main" java.io.NotSerializableException: cn.sxt05.serializable.Student
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
 at cn.sxt05.serializable.Test01.main(Test01.java:22)

假如要序列化Student对象,必须让Student类实现Serializable接口。它相当于一个标记,并没有明确指定的方法需要去实现。

public class Student implements Serializable{
// 。。。

ObjectIntPutStream和ObjectOutPutStream

ObjectIntPutStream和ObjectOutPutStream可以对对象进行序列化和反序列化。

ObjectOutputStream 继承于OutputStream,专门用于把对象序列化到本地。提供了

writeXXX

writeObject() 用于写入一个对象

public static void main(String[] args) throws IOException {
  
  Student stu = new Student("001", "大狗", 20, Gender.男);
  
  File file = new File("d:javatestl.txt");
  FileOutputStream out = new FileOutputStream(file);
  ObjectOutputStream oos = new ObjectOutputStream(out);
  
  oos.writeObject(stu);
  
  oos.close();
  out.close();
 }

ObjectInputStream 继承于InputStream ,专门用于把本地持久化内容反序列化到内存,提供了

readXXX

readObject() 用于读取一个序列化内容并返回一个对象。

比如我可以读取到stu对象序列化内容里学生的ID,名字,年龄和性别。

public static void main(String[] args) throws IOException, ClassNotFoundException {
  
  File file = new File("d:javatestl.txt");
  
  
  FileInputStream in = new FileInputStream(file);
  ObjectInputStream ois = new ObjectInputStream(in);
  
  Student student = (Student) ois.readObject();
  System.out.println(student.getId());
  System.out.println(student.getName());
  System.out.println(student.getAge());
  System.out.println(student.getGender());
  
  ois.close();
  in.close();
 }

一般序列化完成后,如果对Student类的代码更改了,再次反序列化时就会出现异常。

Exception in thread "main" java.io.InvalidClassException: cn.sxt05.serializable.Student; local class incompatible: stream classdesc serialVersionUID = -6288733824962181189, 
local class serialVersionUID = 1690603786167234505

异常原因:序列化流的serialVersionUID和升级后类的版本不匹配。

Sutdent类进行版本更新后,JVM会再自动给该类进行版本号的更新,此时与旧的版本号不一致,就会出现反序列化失败。所以要对版本号始终保持一致。

f6fbd6a661ce266048a4c47bb772e611.png
Eclipse给出解决方案:
public class Student implements Serializable {
 
 private static final long serialVersionUID = -1003763572517930507L;

这里我选择默认给定的一个版本号,可以发现要用静态常量来修饰。也可以自己写一个版本号,记得写过以后不要再去修改,否则反序列化将会再次失败。

如果说开发过程中,有一些用户的隐私比如密码啥的不希望在反序列化后忽略掉,可以用到关键字transient去修饰。

public class Student implements Serializable {
 
 private static final long serialVersionUID = 7222966748321328300L;
 
 private String id;
 private transient String name;
 private transient int age;
 private Gender gender;
 private String phone;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值