您的位置:首页 > 编程语言 > Java开发

Java IO (上)

2015-08-16 16:58 549 查看
一、概述
IO即Input/Output,指输入/输出,IO设备是计算机系统的重要组成部分。Java使用"流"的方式处理IO,对象或者数据要进行传递,需要将对象或者数据转换成某种形式的流,然后通过流的形式传递到目的地,最后再将目的地的流转换成对象或者数据。例如通过网络传递数据,或者将内存中的数据持久化到文件或者数据库中都会涉及到IO操作,另外Java中的RMI和EJB等技术也会默认用到IO操作。


二、IO的特性
IO设备相对于CPU和内存比速度要慢几个数量级。如今JVM在运行优化方面已经前进了一大步,JVM运行字节码的速度已经接近了本地编译代码,也就是说,多数Java应用程序已不再受CPU的束缚,而更多时候是受IO的束缚(等待数据传输)。

三、用户态和内核态


1:用户空间:用户空间是常规进程的所在区域,JVM就处于该区域,该区域的代码不可以直接访问硬件设备。
2:内核空间:操作系统所在区域,该区域属于特权区域,所有的IO操作都必须通过内核区域。
3:读取数据过程:JVM使用read()系统调用,要求填满其缓冲区,之后内核想磁盘控制器硬件发出命令,要求其从磁盘读取数据。磁盘控制器把数据直接写入内核内存缓冲区,这一步通过DMA完成,无需CPU协助。一旦磁盘把缓冲区填满,内核则把内核空间缓冲区的数据拷贝到read()调用时指定的用户空间缓冲区。

四、Java的IO类



看起来很多,分个类吧。
1)根据流向分:输入流和输出流。
2)根据数据传输单位分:字节流和字符流。

五、字节流和字符流区别
1:所有文件的存储都是以字节(byte)为单位的,在磁盘上保存的不是文件的字符,而是先把字符编码成字节,再把这些字节存储到磁盘上。
2:字节流是以字节(8bit)为单位,字符流是以字符为单位读取,一个字符包含2个字节。
3:字节能够处理所有类型的数据,比如图片、电影、mp3等,但是字符只能处理字符类型的数据,例如文本数据。
4:字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。
字节流在操作文件时,即使不关闭资源(close方法),文件也能输出,但是如果字符流不使用close方法的话,则不会输出任何内容,说明字符流用的是缓冲区,并且可以使用flush方法强制进行刷新缓冲区,这时才能在不close的情况下输出内容。

六、序列化
1:序列化的过程是将对象写入字节流和从字节流中读取对象的过程。对象要通过网络传输或者要存储到文件中,必须将对象序列化才可以。
2:Java中对象要支持序列化,必须实现Serializable接口,Serializable接口是标记接口没有任何方法。
3:父类实现了Serializable接口则子类不再需要实现Serializable接口。
4:序列化对象时会将实例对象引用的对象也序列化。
5:static对象和transient关键字修饰的属性不被序列化。
6:writeObject方法和readObject方法,通过这两个方法可以自定义类的序列化,ArrayList就自定义实现了这两个方法。
代码示例:
public class User implements Serializable {
private String str1;
private String str2;
private transient String str3;

public String getStr1() {
return str1;
}

public void setStr1(String str1) {
this.str1 = str1;
}

public String getStr2() {
return str2;
}

public void setStr2(String str2) {
this.str2 = str2;
}

public String getStr3() {
return str3;
}

public void setStr3(String str3) {
this.str3 = str3;
}

}
@Test
public void serialize() throws Exception{
FileOutputStream f = null;
try{
f = new FileOutputStream("e:/tmp.txt");
ObjectOutputStream s = new ObjectOutputStream(f);
User user = new User();
user.setStr1("st1");
user.setStr2("st2");
user.setStr3("st3");
s.writeObject(user);
s.flush();
}finally {
f.close();
}
}
@Test
public void deserialize() throws Exception{
FileInputStream f = null;
try{
f = new FileInputStream("e:/tmp.txt");
ObjectInputStream s = new ObjectInputStream(f);
User user = (User)s.readObject();
System.out.println(user.getStr1());
System.out.println(user.getStr2());
System.out.println(user.getStr3());
}finally {
f.close();
}
}
输出结果:
st1
st2
null

因为str3用transient修饰了。

在User类中加上
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.IOException{
// Write out element count, and any hidden stuff
s.defaultWriteObject();


s.writeObject(str1);
s.writeObject(str2);
s.writeObject(str3);

}

private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();
str1 = (String) s.readObject();
str2 = (String) s.readObject();
str3 = (String) s.readObject();
}
再重新运行上面的代码,则可以看到str3被正确的输出了。


7:如果要自定义对象的序列化可以实现Externalizable接口,实现writeExternal()和readExternal()两个方法。
8:序列化时会将对象的信息序列化进去。
9:一些涉及到资源分配的对象不可以序列化,比如Thread和Socket类。
10:通过序列化可以实现深度复制。
代码示例:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); //构造一个字节输出流
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(value);

byte[] buf = baos.toByteArray();

//------------------------------------
ByteArrayInputStream bais = new ByteArrayInputStream((byte[]) result);
ObjectInputStream ois = new ObjectInputStream(bais);
Object result = ois.readObject();


七、文件IO
1:通过字节流读写文件。
@Test
public void writeFile() throws Exception{
File f = new File("e:/filewriter.txt");
OutputStream out = null;
try {
out = new FileOutputStream(f);
String str="Hello World";
byte[] b=str.getBytes();
out.write(b);//因为是字节流,所以要转化成字节数组进行输出
}finally {
if(out != null)
out.close();
}


}
@Test
public void readFile() throws Exception{
File f = new File("e:/filewriter.txt");
InputStream in = null;
try{
in = new FileInputStream(f);
String str="Hello World";
byte[] b = new byte[(int)f.length()];
in.read(b);
System.out.println(new String(b));
}finally {
if(in != null)
in.close();
}
}

2.通过字符流读写文件。
@Test
public void writeFile() throws Exception{
File f = new File("e:/filewriter.txt");
Writer writer = null;
try {
writer = new FileWriter(f);
String str="Hello World";
writer.write(str);
}finally {
if(writer != null)
writer.close();
}


}
@Test
public void readFile() throws Exception{
File f = new File("e:/filewriter.txt");
Reader reader = null;
try{
reader = new FileReader(f);
char[] ch=new char[100];
int temp=0;
int count=0;
while((temp=reader.read())!=(-1)){
ch[count++]=(char)temp;
}
System.out.println(new String(ch,0,count));
}finally {
if(reader != null)
reader.close();
}

}

3.按行读取文件内容
@Test
public void readFileByLines() {
File file = new File("e:/filewriter.txt");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(file));
String tempString = null;
while ((tempString = reader.readLine()) != null) {
System.out.println(tempString);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
}


4.等待用户输入
public static void main(String[] args) throws Exception{
BufferedReader systemIn=new BufferedReader(new InputStreamReader(System.in));
while(true){
String command = systemIn.readLine();
System.out.println(command);
if("quit".equalsIgnoreCase(command.trim())){
System.exit(0);
}
}
}

5.Scanner
@Test
public void scan() throws Exception{
File file = new File("e:/filewriter.txt");
Scanner sca = null;
try{
sca = new Scanner(file);
}catch(FileNotFoundException e){
e.printStackTrace();
}

while(sca.hasNext()){
String str = sca.next();
System.out.println("从文件中读取的内容是:" + str);
}
}

6.文件压缩
@Test
public void zip() throws Exception{
File file = new File("e:" + File.separator + "filewriter.txt");
File zipFile = new File("e:" + File.separator + "fileWriter.zip");
InputStream input = new FileInputStream(file);
ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(
zipFile));
zipOut.putNextEntry(new ZipEntry(file.getName()));
// 设置注释
zipOut.setComment("hello");
int temp = 0;
while((temp = input.read()) != -1){
zipOut.write(temp);
}
input.close();
zipOut.close();
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: