——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
一、流的操作规律:
1,明确源和目的(汇)
源:InputStream Reader
目的:OutputStream Writer
2,明确数据是否是纯文本数据。
源:是纯文本:Reader;否:InputStream
目的:是纯文本 Writer;否:OutputStream
3,明确具体的设备。
源设备:
硬盘:File;键盘:System.in
内存:数组;网络:Socket流
目的设备:
硬盘:File;控制台:System.out
内存:数组;网络:Socket流
4,是否需要其他额外功能。
需要高效(缓冲区)—-加上buffered.
需要转换—InputStreamReader,OutputStreamWriter
5,举例:读取键盘录入数据,显示在控制台上。
源—-键盘:System.in
目的—-控制台:System.out
需要转换,需要高效
BufferedReader br= null;
br =new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw= null;
bw =new BufferedWriter(new OutputStreamReader(System.out));
二、其他常用流
1,打印流
PrintWriter可以将各种数据类型的数据都原样打印
PrintStream:字节打印流
2,序列流
SequenceInputStream
对多个流进行合并
需求1:将多个文件合并
import java.io.*;
import java.util.*;
class SequenceDemo {
public static void main(String[] args) throws IOException {
// 新建Vector对象
Vector v = new Vector();
// 将流对象添加到集合中
v.add(new FileInputStream("e:\\Java练习\\1.txt"));
v.add(new FileInputStream("e:\\Java练习\\2.txt"));
v.add(new FileInputStream("e:\\Java练习\\3.txt"));
// 返回此向量的组件的枚举。返回到Enumeration中
Enumeration en = v.elements();
// 如果需要传入2个以上的流对象 SequenceInputStream(Enumeration extends InputStream>
// e)可以实现
// 需要传入Enumeration 而Vector可以获取Enumeration
// 因此需要新建Vector对象
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("e:\\Java练习\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
构造方法摘要
SequenceInputStream(Enumeration
import java.io.*;
import java.util.*;
class SequenceDemo {
public static void main(String[] args) throws IOException {
// 新建Vector对象
Vector v = new Vector();
// 将流对象添加到集合中
v.add(new FileInputStream("e:\\Java练习\\1.txt"));
v.add(new FileInputStream("e:\\Java练习\\2.txt"));
v.add(new FileInputStream("e:\\Java练习\\3.txt"));
// 返回此向量的组件的枚举。返回到Enumeration中
Enumeration en = v.elements();
// 如果需要传入2个以上的流对象 SequenceInputStream(Enumeration extends InputStream>
// e)可以实现
// 需要传入Enumeration 而Vector可以获取Enumeration
// 因此需要新建Vector对象
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("e:\\Java练习\\4.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = sis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
sis.close();
}
}
需求2:切割文件
import java.io.*;
import java.util.*;
class SplitFile {
public static void main(String[] args) {
// splitFile();
merge();
}
public static void merge()
{
ArrayList al = new ArrayList();
for(int x=1;x<=5;x++)
{
al.add(new FileInputStream("e:\\Java练习\\"+(x++)+".part"))
}
Iterator it = al.iterator();
Enumeration en = new Enumeration()
{
public boolean hasMoreElements()
{
return it.hasNext();
}
public FileInputStream nextElement()
{
return it.next();
}
};
SequenceInputStream sis = new SequenceInputStream(en);
FileOutputStream fos = new FileOutputStream("e:\\Java练习\\1.mp3");
byte[] buf = new byte[1024];
int len = 0;
while((len=sis.read())!=-1)
{
fos.write(buf,0,len)
}
fos.close();
sis.close();
}
public static void splitFile()
{
FileInputStream fis = new FileInputStream("e:\\Java练习\\0.mp3");
FileOutputStream fos = null;
byte[] buf = new byte[1024*1024];
int len = 0;
int x = 1;
while((len=fis.read(buf))!=-1)
{
fos = new FileOutputStream("e:\\Java练习\\"+(x++)+".part")
fos.write(buf,0,len);
fos.close();
}
fis.close();
}
}
3,RandomAccessFile,
随机访问文件,自身具备读写的方法
通过skipBytes(int x),seek(int x)来达到随机访问
该类不算是IO体系中的子类,而是直接继承自Object。但是它是IO包中成员,因为它具备读和写功能内部封装了一个数组,而且通过指针对数组的元素进行操作,可以通过getFilePointer获取指针位置。同时可以通过seek改变指针的位置其实完成读写的原来就是内部封装了字节输入流和输出流
操作文件还有模式 :只读 r 读写rw等。如果模式为只读r 不会创建文件,回去读取一个已存在的文件,如果该文件不存在,则会出现异常
如果模式为rw 操作的文件不存在,会自动创建,如果存在则不会覆盖
import java.io.*;
class RandomAccessFileDemo {
public static void main(String[] args)throws IOException
{
//writeFile();
//readFile();
writeFile_2()
}
public static void readFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "r");
// 调整对象指针
raf.seek(8);
// 跳过指定的字节数
raf.skipBytes(8);// 只能往前跳 不能往后跳
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name=" + name);
System.out.println("age=" + age);
raf.close();
}
public static void writeFile_2() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.seek(8 * 3);
// raf.seek(8*0);//会对数据进行覆写
raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();
}
public static void writeFile() throws IOException {
RandomAccessFile raf = new RandomAccessFile("ran.txt", "rw");
raf.write("李四".getBytes());
// raf.write(258);//write只写出最低八位,超出八位的话会数据丢失
raf.writeInt(97);// writeInt(int v) 按四个字节将 int 写入该文件,先写高字节
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
}
4,管道流
PipedInputStream和PipedOutputStream
输入输出可以直接进行连接,通过结合线程使用
操作基本数据类型:
DataInputStream与DataOutputStream
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
操作字符数组
CharArrayReader与CharArrayWriter
操作字符串
StringReader与StringWriter
5,DataInputStream与DataOutputStream
可以用于操作基本数据类型的流对象
import java.io.*;
class DataStreamDemo {
public static void main(String[] args) throws IOException {
writeData();
// readData()
}
public static void readData() throws IOException {
DataInputStream dos = new DataIntputStream(new FileIntputStream("data.txt"));
int num = dis.readInt();
boolean b = dis.readBoolean();
double d = dis.readDouble();
System.out.println("num=" + num);
System.out.println("b=" + b);
System.out.println("d=" + d);
dis.close();
}
public static void writeData() throws IOException {
DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));
dos.writeInt(234);
dos.writeBoolean(true);
dos.writeDouble(9007.543);
dos.close();
}
}
操作字节数组
ByteArrayInputStream与ByteArrayOutputStream
用于操作字节数组的流对象
ByteArrayInputStream在构造的时候,需要接受数据源,而且数据源是一个字节数组
ByteArrayOutputStream在够在的时候,不用定义数据目的,因为该对象中已经封装了
可变长度的字节数组,这就是数据目的地,因为这两个流对象都操作的数组,并没有使用系统资源。所以,不用进行close关闭
三、字符编码
字符流的出现为了方便操作字符,更重要的是加入了编码转换,通过子类转换流来完成
InputStreamReader
OutputStreamWriter
在两个对象进行构造的时候可以加入字符集编码表的由来,计算机只能识别二进制数据,早起由来是电信号。为了方便应用计算机,让它可以识别各个国家的文字,就将各个国家的文字用数字来表示,并一一对应,形成一张表这就是编码表
常见的编码表:
ASCII:没过标准信息交换码。
用一个字节的7位可以表示
ISO08859-1:拉丁码表。欧洲码表
用一个字节的8位表示
GB2312: 中国的中文编码表
GBK:中国的中文编码表升级,融合了更多的中文文字符号
Unicode:国际标准码,融合了多种文字
所有文字都用两个字节来表示,java语言使用的就是unicode
UTF-8:最多用三个字节来表示一个字符转换流的编码应用
可以将字符以指定编码格式存储
可以对文本数据指定编码格式来解读
指定编码表的动作由构造函数完成
import java.io.*;
class EncodeStream {
public static void main(String[] args) throws IOException {
writeText();
}
public static void readText() throws IOException {
InputStreamReader isr = new InputStreamReade(new FileInputStream("gbk.txt"), "gbk");
char[] buf = new char[10];
int len = isr.read(buf);
String str = new String(buf, 0, len);
System.out.println(str);
isr.close();
}
public static void writeText() throws IOException {
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk.txt"), "gbk");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("utf.txt"), "UTF-8");
osw.write("你好");
osw.close();
}
}
编码:字符串变成字节数组
解码:字节数组变成字符串
String–>byte[] str.getBytes(charsetName)
byte[]–>String new String(byte[],charsetName)
import java.util.*;
class EncodeDemo {
public static void main(String[] args) throws Exception {
String s = "你好";
byte[] b1 = s.getBytes("GBK");// 用GBK编码
String s1 = new String(b1, "ISO8859-1");// 用ISO8859-1解码
// System.out.println(s1);
// System.out.println(Arrays.toString(b1));
byte[] b2 = s1.getBytes("ISO8859-1");
System.out.println(Arrays.toString(b2));
String s2 = new String(b2, "gbk");
System.out.println("s2=" + s2);
}
}
练习题:有五个学生,每个学生有3门课的成绩从键盘输入以上数据(包括姓名,三门课成绩)输入格式如:张三,30,40,60计算出总成绩,并把学生的信息和计算出的总分数高低顺序存放在磁盘文件“stud.txt”
1.描述学生对象
2.定义一个可操作学生对象的工具类
思想
1.通过获取键盘录入一行数据,并将该行中的信息取出封装成学生对象
2.因为学生有很多,那么就需要存储,使用到集合。因为要对学生总分排序,所以可以使用TreeSet
3.将集合的信息写入到一个文件中
import java.io.*;
import java.util.*;
class Student implements Comparable {
private String name;
private int ma, cn, en;
private int sum;
Student(String name, int ma, int cn, int en) {
this.name = name;
this.ma = ma;
this.cn = cn;
this.en = en;
sum = ma + cn + en;
}
public int compareTo(Student s) {
int num = new Integer(this.sum).compareTo(new Integer(s.sum));
if (num == 0)
return this.name.compareTo(s.name);
return num;
}
public String getName() {
return name;
}
public int getSum() {
return sum;
}
public int hashCode() {
return name.hashCode() + sum * 78;
}
public boolean equals(Object obj) {
if (!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student) obj;
return this.name.equals(s.name) && this.sum == s.sum;
}
public String toString() {
return "student[" + name + ", " + ma + ", " + cn + ", " + en + "]";
}
}
class StudentInfoTool {
public static Set getStudents() throws IOException {
return getStudents(null);
}
public static Set getStudents(Comparator cmp) throws IOException {
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
String line = null;
Set stus = null;
if (cmp == null)
stus = new TreeSet();
else
stus = new TreeSet(cmp);
while ((line = bufr.readLine()) != null) {
if ("over".equals(line))
break;
String[] info = line.split(",");
Student stu = new Student(info[0], Integer.parseInt(info[1]), Integer.parseInt(info[2]), Integer.parseInt(info[3]));
stus.add(stu);
}
bufr.close();
return stus;
}
public static void write2File(Set stus) throws IOException {
BufferedWriter bufw = new BufferedWriter(new FileWriter("stuinfo.txt"));
for (Student stu : stus) {
bufw.write(stu.toString() + "\t");
bufw.write(stu.getSum() + "");
bufw.newLine();
bufw.flush();
}
bufw.close();
}
}
class StudentInfoTest {
public static void main(String[] args) throws IOException {
Comparator cmp = Collections.reverseOrder();
Set stus = StudentInfoTool.getStudents(cmp);
StudentInfoTool.write2File(stus);
}
}