java之IO流——2
- 获取行号的流
- 操作基本数据的流
- 内存操作流(操作字节数组、字符数组、字符串)
- 打印流
- 标准输入输出流
- 合并流
- 对象的序列化流和反序列化流
- 集合的Properties与IO流的操作
获取行号的流
LineNumberReader:
1.构造方法LineNumberReader(Reader in)
使用默认输入缓冲区的大小创建新的行编号 reader
2.public int getLineNumber():获取行号
3.public void setLineNumber(intlineNumber):设置起始行号
4.String readLine():读取一行
package com.wy.lnr;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.LineNumberReader;
public class LineNumberReaderTest {
public static void main(String[] args) throws IOException {
/*
* * public int getLineNumber():获取行号
* public void setLineNumber(int lineNumber):设置起始行号
*String readLine():读取一行
*案例:读取文件,每次读取一行打印并且加上行号
*/
LineNumberReader lnr = new LineNumberReader(new FileReader("copy.java"));
//FileWriter fw = new FileWriter("copyWithLine.java");
BufferedWriter bw = new BufferedWriter(new FileWriter("copyWithLine.java"));
String s;
int len;
while((s = lnr.readLine())!= null){
bw.write(s);
bw.flush();
}
bw.close();
}
}
操作基本数据的流
可以操作基本类型的流对象。
构造方法:
DataInputStream(InputStream in)DataInputStream:读数据
DataOutputStream:写数据
package com.wy.datastream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamTest {
public static void main(String[] args) throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("dos.txt"));
dos.writeByte(1);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000L);
dos.writeChar(100);
dos.writeFloat(12.34F);
dos.writeDouble(12.34);
dos.writeBoolean(false);
}
}
package com.wy.datastream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class DataStreamTest {
public static void main(String[] args) throws IOException {
/*
* dos.writeByte(1);
dos.writeShort(100);
dos.writeInt(1000);
dos.writeLong(10000L);
dos.writeChar(100);
dos.writeFloat(12.34F);
dos.writeDouble(12.34);
dos.writeBoolean(false);
*/
//根据写的顺序进行数据的读
DataInputStream dis = new DataInputStream(new FileInputStream("dos.txt"));
System.out.println(dis.readByte());
System.out.println(dis.readShort());
System.out.println(dis.readInt());
System.out.println(dis.readLong());
System.out.println(dis.readChar());
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
}
}
运行结果如下图所示:
内存操作流(操作字节数组、字符数组、字符串)
解决临时数据存储的问题。
操作字节数组
ByteArrayInputStream
ByteArrayOutputStream
构造方法:ByteArrayInputStream(byte[] buf)
byte[] toByteArray()
将之前写入内存的流转换成字节数组
package com.wy.bytearraystream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ByteArrayInputStreamTest {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("beautfulgirl".getBytes());
byte[] buf = baos.toByteArray();//调用这个方法,将之前写入内存中的数据存储到字节数组中
ByteArrayInputStream bais = new ByteArrayInputStream(buf);
int by;
while ((by=bais.read())!=-1) {
System.out.print((char)by);
}
//关流
bais.close();
baos.close();
}
}
操作字符数组
CharArrayReader
CharArrayWrite操作字符串
StringReader
StringWriter
构造方法:
StringReader(String s)
StringWriter()
package com.wy.stringreader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
public class StringReaderOrWriterTest {
public static void main(String[] args) throws IOException {
StringWriter sw = new StringWriter();
sw.write("beautifulgirl");
StringBuffer re = sw.getBuffer();
StringReader sr = new StringReader(re.toString());
int ch;
while ((ch = sr.read()) != -1) {
System.out.println((char)ch);
}
sr.close();
sw.close();
}
}
打印流
字节打印流 PrintStream
字符打印流 PrintWriter
特点:
A:只能操作目的地,不能操作数据源
B:可以操作任意类型的数据
C:如果启动了自动刷新,能够自动刷新
D:可以操作文件的流
注意:什么流可以直接操作文件?
看流对象的API,如果其构造方法同时有File和String类型的参数,就可以直接操作文件。
字节打印流代码示例:
package com.wy.print;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintStream;
public class Print {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("copy.java");
PrintStream ps = new PrintStream("printstreamcopy.java");
int ch;
while((ch = fis.read()) != -1){
ps.write(ch);
}
ps.close();
fis.close();
}
}
字符打印流示例代码:
package com.wy.print;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterTest {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("copy.java"));
/*
* 如何启动自动刷新:利用构造
* PrintWriter(OutputStream out, boolean autoFlush)
* PrintWriter(Writer out, boolean autoFlush)
* 如果启用了自动刷新,则只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操作
*/
PrintWriter pw = new PrintWriter(new FileWriter("printWritercopy.java"),true);
String line;
while((line = br.readLine())!= null){
pw.println(line);
}
pw.close();
br.close();
}
}
标准输入输出流
System类下有这样的两个成员变量:
标准输入流:
public static final InputStream in
标准输出流:
public static final PrintStream out
输入流示例代码:
package com.wy.system;
import java.io.IOException;
import java.io.InputStream;
public class SystemIn {
public static void main(String[] args) throws IOException {
/**
* public static final InputStream in
*/
//将键盘录入的数据封装在了输入流中
//Scanner sc = new Scanner(System.in);
InputStream is = System.in;
//将键盘录入的数据从输入流中读取出来
int by;
while ((by=is.read())!=-1) {
System.out.print((char)by);
}
//关流
is.close();
}
}
package com.wy.system;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class SystemIn2 {
public static void main(String[] args) throws IOException {
/**
* 案例2:用IO流实现键盘录入,一次读取一行数据
* InputStream is = System.in;
* InputSreamReader isr = new InputStreamReader(is)
* BufferedReader br = new BufferedReader(isr);
*/
//将上面的分析写为一部
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//一次读取一行数据
System.out.println("请输入你的姓名");
String name = br.readLine();
System.out.println("请输入你的年龄");
String age = br.readLine();
System.out.println(name+":"+age);
}
}
合并流
SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。
构造:
SequenceInputStream(InputStream s1, InputStream s2) :将s1和s2合并成一个输入流,先读取s1后读取s2
package com.wy.sequence;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
public class SequenceTest {
public static void main(String[] args) throws IOException {
/*
* 合并流:SequenceInputStream类可以将多个输入流串流在一起,合并为一个输入流,因此,该流也被称为合并流。
* 构造:
*SequenceInputStream(InputStream s1, InputStream s2) :
*将s1和s2合并成一个输入流,先读取s1后读取s2
*案例1:
*我要把DataStreamDemo.java和ByteArrayStreamDemo.java写到一个文件Copy.java
*数据源:DataStreamDemo.java
*ByteArrayStreamDemo.java
* 目的地:Copy.java
*/
SequenceInputStream sis = new SequenceInputStream(new FileInputStream("copy.java"),new FileInputStream("dos.txt"));
FileOutputStream fos = new FileOutputStream("sequence.txt");
int ch;
while((ch = sis.read())!= -1){
fos.write(ch);
}
fos.close();
sis.close();
}
}
对象的序列化流和反序列化流
- 序列化流:把对象按照流一样的方式写到文件或者在网络中传输。
反序列化流:把文件或者网络中的流对象数据还原对象。
-
- ObjectOutputStream:序列化流
writeObject(Object obj) 将指定的对象写入 ObjectOutputStream。
- ObjectOutputStream:序列化流
ObjectInputStream:反序列化流
Object readObject() 从 ObjectInputStream 读取对象。
注意:如果一个类不是实现Serializable接口无法把实例化,会报异常java.io.NotSerializableException
- 类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
**如何实现序列化?
让对象所属类的实现序列化接口。**
特点:Properties 可保存在流中或从流中加载。-
集合的Properties与IO流的操作
含义:Properties 类表示了一个持久的属性集。属性列表中每个键及其对应值都是一个字符串。
Properties的特有功能:
1. A:添加元素
public Object setProperty(String key,String value)
2. B:获取元素
public String getProperty(String key)
public Set stringPropertyNames()
package com.wy.prop;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Set;
public class PropertiesTest {
/*
* 我有一个文本文件,我知道数据是键值对形式的,但是不知道内容是什么。
*请写一个程序判断是否有“lisi”这样的键存在,如果有就改变其值为”100”
*/
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("data.txt");
Properties prop = new Properties();
prop.load(fis);
Set<String> set= prop.stringPropertyNames();
for (String key : set) {
if(key.equals("lisi")){
prop.setProperty("lisi", "100");
}
prop.store(new FileOutputStream("data.txt"), "some comments");
}
}
}
猜数字游戏实现、
需求如下:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,
超过5次提示:游戏试玩已结束,请付费。
package com.wy.properties;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import java.util.Scanner;
/**
案例:我有一个猜数字小游戏的程序,请写一个程序实现在测试类中只能用5次,
超过5次提示:游戏试玩已结束,请付费。
*
*/
public class GuessNumber {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("playTimes.txt");
Properties prop = new Properties();
prop.load(fis);
if(Integer.parseInt(prop.getProperty("count"))<=4){
String numstr = prop.getProperty("count");
//System.out.println(numstr);
int num = Integer.parseInt(numstr)+1;
String newNum = num+"";
prop.setProperty("count",newNum);
prop.store(new FileOutputStream("playTimes.txt"), "You have played the game");
guessNum();
}else{
System.out.println("游戏试玩已结束,请付费。");
}
}
private static void guessNum() {
int random = (int) (Math.random()*100+1);
System.out.println(random);
System.out.println("Start");
int guess=0;
Scanner sc = new Scanner(System.in);
while(true){
System.out.println("Please input your guess number:");
guess = sc.nextInt();
if(guess == random){
System.out.println("guess right!");
break;
}
else if(guess > random){
System.out.println("too big");
}
else {
System.out.println("too small");
}
}
}
}
最后……
关于java的IO流到此告一段落。IO流学习的重点主要是学习他们的构造方法需要传入什么参数,有时候是一个文件,有时候是一个流;同时转换流在字节流和字符流中间搭建了一个桥梁。字节流可以操作任意类型的流,而字符流只能操作使用记事本打开能看懂的文件。因此在选择的时候,要考虑是什么文件,否则会使得操作的文件部分丢失。