I/O包中的其他类

来源:互联网 发布:sql语句时间格式化 编辑:程序博客网 时间:2024/06/16 00:41

io包中的其他类:


打印流:

======================================PrintStream


import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintStream;

public class PrintStreamDemo {

/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {
/*
* PrintStream:
* 1,提供了打印方法可以对多种数据类型值进行打印。并保持数据的表示形式。 
* 2,它不抛IOException.

* 构造函数,接收三种类型的值:
* 1,字符串路径。
* 2,File对象。
* 3,字节输出流。
*/

PrintStream out = new PrintStream("print.txt");

// int by = read();
// write(by);

// out.write(610);//只写最低8位,

// out.print(97);//将97先变成字符保持原样将数据打印到目的地。 

out.close();

}

}

=========================================PrintWriter

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;


public class PrintWriterDemo {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {
/*
* PrintWriter:字符打印流。
* 构造函数参数:
* 1,字符串路径。
* 2,File对象。
* 3,字节输出流。
* 4,字符输出流。

*/
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));

PrintWriter out = new PrintWriter(new FileWriter("out.txt"),true);//这个true是auto刷新flush,下面的就不用写flush了。既能往文件里写又能自动刷新。

String line =  null;
while((line=bufr.readLine())!=null){
if("over".equals(line))
break;
out.println(line.toUpperCase());
// out.flush();
}

out.close();
bufr.close();
}


}

只有输出流能自动刷新。



序列流

===================================================

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;


public class SequenceInputStreamDemo {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {



/*
* 需求:将1.txt 2.txt 3.txt文件中的数据合并到一个文件中。
*/

需要的是枚举类型的集合。(后来有转换,利用迭代器覆写了enumeration中的两个方法,为什么要换成arrarist因为vector效率低)

// Vector<FileInputStream> v = new Vector<FileInputStream>();
// v.add(new FileInputStream("1.txt"));
// v.add(new FileInputStream("2.txt"));
// v.add(new FileInputStream("3.txt"));
// Enumeration<FileInputStream> en = v.elements();

ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=1; x<=3; x++){
al.add(new FileInputStream(x+".txt"));
}

Enumeration<FileInputStream> en = Collections.enumeration(al);



/*
final Iterator<FileInputStream> it = al.iterator();
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){


@Override
public boolean hasMoreElements() {

return it.hasNext();
}


@Override
public FileInputStream nextElement() {

return it.next();
}

};*/

SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream("1234.txt");

byte[] buf = new byte[1024];

int len = 0;

while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}

fos.close();
sis.close();

}


}

=====================================================

文件分割(利用的是序列流)。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;


/*
 * 文件切割器。
 * 
 * 
 * 
 * 
 */


public class SplitFileDemo {


private static final int SIZE = 1024 * 1024;


/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {


File file = new File("c:\\aa.mp3");


splitFile_2(file);
}


private static void splitFile_2(File file) throws IOException {


// 用读取流关联源文件。
FileInputStream fis = new FileInputStream(file);


// 定义一个1M的缓冲区。
byte[] buf = new byte[SIZE];


// 创建目的。
FileOutputStream fos = null;


int len = 0;
int count = 1;


/*
* 切割文件时,必须记录住被切割文件的名称,以及切割出来碎片文件的个数。 以方便于合并。
* 这个信息为了进行描述,使用键值对的方式。用到了properties对象

*/
Properties prop  = new Properties();




File dir = new File("c:\\partfiles");
if (!dir.exists())
dir.mkdirs();


while ((len = fis.read(buf)) != -1) {


fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buf, 0, len);
fos.close();
}

//将被切割文件的信息保存到prop集合中。
prop.setProperty("partcount", count+"");
prop.setProperty("filename", file.getName());



fos = new FileOutputStream(new File(dir,count+".properties"));

//将prop集合中的数据存储到文件中。 
prop.store(fos, "save file info");


fos.close();
fis.close();


}


public static void splitFile(File file) throws IOException {


// 用读取流关联源文件。
FileInputStream fis = new FileInputStream(file);


// 定义一个1M的缓冲区。
byte[] buf = new byte[SIZE];


// 创建目的。
FileOutputStream fos = null;


int len = 0;
int count = 1;


File dir = new File("c:\\partfiles");
if (!dir.exists())
dir.mkdirs();


while ((len = fis.read(buf)) != -1) {


fos = new FileOutputStream(new File(dir, (count++) + ".part"));
fos.write(buf, 0, len);
}


fos.close();
fis.close();


}


}

===============================================合并

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.SequenceInputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;


public class MergeFile {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {


File dir = new File("c:\\partfiles");

mergeFile_2(dir);
}

public static void mergeFile_2(File dir) throws IOException {

/*
* 获取指定目录下的配置文件对象。
*/
File[] files = dir.listFiles(new SuffixFilter(".properties"));

if(files.length!=1)
throw new RuntimeException(dir+",该目录下没有properties扩展名的文件或者不唯一");
//记录配置文件对象。
File confile = files[0];



//获取该文件中的信息================================================。

Properties prop = new Properties();
FileInputStream fis = new FileInputStream(confile);

prop.load(fis);

String filename = prop.getProperty("filename");
int count = Integer.parseInt(prop.getProperty("partcount"));




//获取该目录下的所有碎片文件。 ==============================================
File[] partFiles = dir.listFiles(new SuffixFilter(".part"));

if(partFiles.length!=(count-1)){
throw new RuntimeException(" 碎片文件不符合要求,个数不对!应该"+count+"个");
}



//将碎片文件和流对象关联 并存储到集合中。 
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for(int x=0; x<partFiles.length; x++){

al.add(new FileInputStream(partFiles[x]));
}



//将多个流合并成一个序列流。 
Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream(new File(dir,filename));

byte[] buf = new byte[1024];

int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}

fos.close();
sis.close();






}


public static void mergeFile(File dir) throws IOException{


ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();

for(int x=1; x<=3 ;x++){
al.add(new FileInputStream(new File(dir,x+".part")));
}

Enumeration<FileInputStream> en = Collections.enumeration(al);
SequenceInputStream sis = new SequenceInputStream(en);

FileOutputStream fos = new FileOutputStream(new File(dir,"1.bmp"));

byte[] buf = new byte[1024];

int len = 0;
while((len=sis.read(buf))!=-1){
fos.write(buf,0,len);
}

fos.close();
sis.close();

}


}

===============================过滤器

import java.io.File;
import java.io.FilenameFilter;


public class SuffixFilter implements FilenameFilter {


private String suffix;

public SuffixFilter(String suffix) {
super();
this.suffix = suffix;
}


@Override
public boolean accept(File dir, String name) {


return name.endsWith(suffix);
}
}

=======================================================操作对象

ObjectInputStream 被操作的对象需要实现Serializable(标记接口)。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;


import cn.itcast.io.p2.bean.Person;


public class ObjectStreamDemo {


/**
* @param args
* @throws IOException 
* @throws ClassNotFoundException 
*/
public static void main(String[] args) throws IOException, ClassNotFoundException {

// writeObj();
readObj();
}


public static void readObj() throws IOException, ClassNotFoundException {

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.object"));
//对象的反序列化。 
Person p = (Person)ois.readObject();

System.out.println(p.getName()+":"+p.getAge());

ois.close();

}


public static void writeObj() throws IOException, IOException {

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.object"));
//对象序列化。  被序列化的对象必须实现Serializable接口。 
oos.writeObject(new Person("小强",30));

oos.close();



}


}

=======================================================

import java.io.Serializable;
/*
 * Serializable:用于给被序列化的类加入ID号。
 * 用于判断类和对象是否是同一个版本。 
 */
public class Person implements Serializable/*标记接口*/ {


/**
* transient:非静态数据不想被序列化可以使用这个关键字修饰。 
*/
private static final long serialVersionUID = 9527l;
private transient String name;
private static int age;


public Person(String name, int age) {
super();
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;
}

}

==========================================关键字

static关键字:



静态的对象值写不进去。

有些值不想写进去,,还不是公共的数据,还是特有的,还不能静态。此时用这个关键字

transient(短暂的,暂时的)

transient:非静态数据不想被序列化可以使用这个关键字修饰。

====================================================


=================================================随机访问文件

随机访问四种模式:


import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;


public class RandomAccessFileDemo {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {


/*
* RandomAccessFile
* 一看这个类名字,纠结。不是io体系中的子类。

* 特点:
* 1,该对象即能读,又能写。
* 2,该对象内部维护了一个byte数组,并通过指针可以操作数组中的元素,
* 3,可以通过getFilePointer方法获取指针的位置,和通过seek方法设置指针的位置。
* 4,其实该对象就是将字节输入流和输出流进行了封装。 
* 5,该对象的源或者目的只能是文件。通过构造函数就可以看出。 


*/

// writeFile();
// readFile();
randomWrite();
}

public static void randomWrite() throws IOException{
RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "rw");

//往指定位置写入数据。
raf.seek(3*8);

raf.write("哈哈".getBytes());
raf.writeInt(108);

raf.close();
}


public static void readFile() throws IOException {

RandomAccessFile raf = new RandomAccessFile("ranacc.txt", "r");

//通过seek设置指针的位置。
raf.seek(1*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);

System.out.println("pos:"+raf.getFilePointer());

raf.close();


}


//使用RandomAccessFile对象写入一些人员信息,比如姓名和年龄。
public static void writeFile() throws IOException{
/*
* 如果文件不存在,则创建,如果文件存在,不创建

*/
RandomAccessFile raf = new RandomAccessFile("ranacc.txt","rw");

raf.write("张三".getBytes());
raf.writeInt(97);
raf.write("小强".getBytes());
raf.writeInt(99);
//
raf.close();
}


}

=================================================管道流

输入流管道和输出流管道可以直接接上。

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;


public class PipedStream {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {


PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream();

input.connect(output);//管道就连上了,一共两种方法,一个是构造函数直接把输出流放进去,第二种是用connect方法。连接。

new Thread(new Input(input)).start();
new Thread(new Output(output)).start();

}


}


class Input implements Runnable{

private PipedInputStream in;
Input(PipedInputStream in){
this.in = in;
}
public void run(){

try {
byte[] buf = new byte[1024];
int len = in.read(buf);

String s = new String(buf,0,len);

System.out.println("s="+s);
in.close();
} catch (Exception e) {
// TODO: handle exception
}

}
}


class Output implements Runnable{
private PipedOutputStream out;
Output(PipedOutputStream out){
this.out = out;
}
public void run(){

try {
Thread.sleep(5000);
out.write("hi,管道来了!".getBytes());
} catch (Exception e) {
// TODO: handle exception
}
}
}

==================================================管道流必须结合多线程才能用


=============================================================


=============================================================操作基本数据类型

(仅仅操作基本数据类型对象就用这对流)

普通的write方法不行,写最低八位

这里就不是了

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataSteamDemo {

/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {

// writeData();
readData();

}

public static void readData() throws IOException {

DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));

String str = dis.readUTF();

System.out.println(str);
}

public static void writeData() throws IOException {

DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));

dos.writeUTF("你好");//这里是utf-8修改表,。只有这个流具备,用转化流你读不出来。


dos.close();

}
}

===============================================操作的是字节数组(0关闭这个流是无效的,因为没用调用底层资源,这里都是调用的内存)



output..自带数组



import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;


public class ByteArrayStreamDemo {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) {


ByteArrayInputStream bis = new ByteArrayInputStream("abcedf".getBytes());//它内部有缓冲区

ByteArrayOutputStream bos = new ByteArrayOutputStream();//它内部有字节数组

int ch = 0;

while((ch=bis.read())!=-1){
bos.write(ch);
}
//bis.close写出来没用,还得在方法上声明抛异常。所以就不写了。
System.out.println(bos.toString());
}

}

================================================编码表


import java.io.IOException;
import java.io.UnsupportedEncodingException;


public class EncodeDemo {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {


/*
* 字符串 --> 字节数组:编码。
* 字节数组 --> 字符串:解码。

* 你好:GBK:  -60 -29 -70 -61

* 你好: utf-8: -28 -67 -96 -27 -91 -67 


* 如果你编错了,解不出来。
* 如果编对了,解错了,有可能有救。
*/

String str = "谢谢";

byte[] buf = str.getBytes("gbk");

String s1 = new String(buf,"UTF-8");

System.out.println("s1="+s1);


byte[] buf2 = s1.getBytes("UTF-8");//获取源字节.

printBytes(buf2);//-17 -65 -67 -17 -65 -67 -17 -65 -67 
//-17 -65 -67 -17 -65 -67 -17 -65 -67 -17 -65 -67
//-48 -69 -48 -69 
String s2 = new String(buf2,"GBK");

System.out.println("s2="+s2);


// encodeDemo(str);



}


/**
* @param str
* @throws UnsupportedEncodingException
*/
public static void encodeDemo(String str)
throws UnsupportedEncodingException {
//编码;
byte[] buf = str.getBytes("UTF-8");

// printBytes(buf);

//解码:
String s1 = new String(buf,"UTF-8");

System.out.println("s1="+s1);
}


private static void printBytes(byte[] buf) {
for(byte b : buf){
System.out.print(b +" ");
}
}


}

=========================================================================

解码失败原理:

用了未知字符去填写,在解码的时候就解不出来了。因为utf可以解一个字节,2个字节,3个字节都能接。


=============================================================联通问题

import java.io.IOException;
import java.io.UnsupportedEncodingException;


public class LianTong {


/**
* @param args
* @throws IOException 
*/



public static void main(String[] args) throws IOException {

String str = "联通";
/*
11000001
10101010
11001101
10101000
*/

byte[] buf = str.getBytes("gbk");

for(byte b :buf){
System.out.println(Integer.toBinaryString(b&255));
}
}

}

========================================utf-8的解码形式

联通正好冲突了,被utf-8用两个字节给解析了,(汉字在u8中都是用三个字节来表示的)


=========================================================练习

import java.io.IOException;




public class Test {


/**
* @param args
* @throws IOException 
*/
public static void main(String[] args) throws IOException {

String str = "ab你好cd谢谢";
// str = "ab琲琲cd琲琲";

// int len = str.getBytes("gbk").length;
// for(int x=0; x<len; x++){
// System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByByte(str, x+1));
// }

int len = str.getBytes("utf-8").length;
for(int x=0; x<len; x++){
System.out.println("截取"+(x+1)+"个字节结果是:"+cutStringByU8Byte(str, x+1));
}



// String str = "琲";
// byte[] buf = str.getBytes("gbk");
// for(byte b : buf){
// System.out.println(b);//-84  105 
// }

}

/*
  在java中,字符串“abcd”与字符串“ab你好”的长度是一样,都是四个字符。
但对应的字节数不同,一个汉字占两个字节。
定义一个方法,按照最大的字节数来取子串。
如:对于“ab你好”,如果取三个字节,那么子串就是ab与“你”字的半个,
那么半个就要舍弃。如果去四个字节就是“ab你”,取五个字节还是“ab你”.


*/

public static String cutStringByU8Byte(String str, int len) throws IOException {

byte[] buf = str.getBytes("utf-8");

int count = 0;
for(int x=len-1; x>=0; x--){
if(buf[x]<0)
count++;
else
break;
}

if(count%3==0)
return new String(buf,0,len,"utf-8");
else if(count%3==1)
return new String(buf,0,len-1,"utf-8");
else 
return new String(buf,0,len-2,"utf-8");

}


public static String cutStringByByte(String str,int len) throws IOException{

byte[] buf = str.getBytes("gbk");

int count = 0;
for(int x=len-1; x>=0; x--){
if(buf[x]<0)
count++;
else
break;
}

if(count%2==0)
return new String(buf,0,len,"gbk");
else
return new String(buf,0,len-1,"gbk");
}
}