`
wtfypm
  • 浏览: 11115 次
  • 性别: Icon_minigender_1
  • 来自: 陕西
社区版块
存档分类
最新评论

JAVA之精髓IO流!

    博客分类:
  • JAVA
阅读更多
彻底明白Java的IO系统

一. Input和Output

1. stream代表的是任何有能力产出数据的数据源,或是任何有能力接收数据的接收源。在Java的IO中,所有的stream(包括Input和Out stream)都包括两种类型:

1.1 以字节为导向的stream

以字节为导向的stream,表示以字节为单位从stream中读取或往stream中写入信息。以字节为导向的stream包括下面几种类型:

1) input stream:

1) ByteArrayInputStream:把内存中的一个缓冲区作为InputStream使用

2) StringBufferInputStream:把一个String对象作为InputStream

3) FileInputStream:把一个文件作为InputStream,实现对文件的读取操作

4) PipedInputStream:实现了pipe的概念,主要在线程中使用

5) SequenceInputStream:把多个InputStream合并为一个InputStream

2) Out stream

1) ByteArrayOutputStream:把信息存入内存中的一个缓冲区中

2) FileOutputStream:把信息存入文件中

3) PipedOutputStream:实现了pipe的概念,主要在线程中使用

4) SequenceOutputStream:把多个OutStream合并为一个OutStream

1.2 以Unicode字符为导向的stream

以Unicode字符为导向的stream,表示以Unicode字符为单位从stream中读取或往stream中写入信息。以Unicode字符为导向的stream包括下面几种类型:

1) Input Stream

1) CharArrayReader:与ByteArrayInputStream对应

2) StringReader:与StringBufferInputStream对应

3) FileReader:与FileInputStream对应

4) PipedReader:与PipedInputStream对应

2) Out Stream

1) CharArrayWrite:与ByteArrayOutputStream对应

2) StringWrite:无与之对应的以字节为导向的stream

3) FileWrite:与FileOutputStream对应

4) PipedWrite:与PipedOutputStream对应

以字符为导向的stream基本上对有与之相对应的以字节为导向的stream。两个对应类实现的功能相同,字是在操作时的导向不同。如CharArrayReader:和ByteArrayInputStream的作用都是把内存中的一个缓冲区作为InputStream使用,所不同的是前者每次从内存中读取一个字节的信息,而后者每次从内存中读取一个字符。

1.3 两种不现导向的stream之间的转换

InputStreamReader和OutputStreamReader:把一个以字节为导向的stream转换成一个以字符为导向的stream。

2. stream添加属性

2.1 “为stream添加属性”的作用

运用上面介绍的Java中操作IO的API,我们就可完成我们想完成的任何操作了。但通过FilterInputStream和FilterOutStream的子类,我们可以为stream添加属性。下面以一个例子来说明这种功能的作用。

如果我们要往一个文件中写入数据,我们可以这样操作:

FileOutStream fs = new FileOutStream(“test.txt”);

然后就可以通过产生的fs对象调用write()函数来往test.txt文件中写入数据了。但是,如果我们想实现“先把要写入文件的数据先缓存到内存中,再把缓存中的数据写入文件中”的功能时,上面的API就没有一个能满足我们的需求了。但是通过FilterInputStream和FilterOutStream的子类,为FileOutStream添加我们所需要的功能。

2.2 FilterInputStream的各种类型

2.2.1 用于封装以字节为导向的InputStream

1) DataInputStream:从stream中读取基本类型(int、char等)数据。

2) BufferedInputStream:使用缓冲区

3) LineNumberInputStream:会记录input stream内的行数,然后可以调用getLineNumber()和setLineNumber(int)

4) PushbackInputStream:很少用到,一般用于编译器开发

2.2.2 用于封装以字符为导向的InputStream

1) 没有与DataInputStream对应的类。除非在要使用readLine()时改用BufferedReader,否则使用DataInputStream

2) BufferedReader:与BufferedInputStream对应

3) LineNumberReader:与LineNumberInputStream对应

4) PushBackReader:与PushbackInputStream对应

2.3 FilterOutStream的各种类型

2.2.3 用于封装以字节为导向的OutputStream

1) DataIOutStream:往stream中输出基本类型(int、char等)数据。

2) BufferedOutStream:使用缓冲区

3) PrintStream:产生格式化输出

2.2.4 用于封装以字符为导向的OutputStream

1) BufferedWrite:与对应

2) PrintWrite:与对应

3. RandomAccessFile

1) 可通过RandomAccessFile对象完成对文件的读写操作

2) 在产生一个对象时,可指明要打开的文件的性质:r,只读;w,只写;rw可读写

3) 可以直接跳到文件中指定的位置

4. I/O应用的一个例子

import java.io.*;

public class TestIO{

public static void main(String[] args)

throws IOException{

//1.以行为单位从一个文件读取数据

BufferedReader in =

new BufferedReader(

new FileReader("F:\\nepalon\\TestIO.java"));

String s, s2 = new String();

while((s = in.readLine()) != null)

s2 += s + "\n";

in.close();

//1b. 接收键盘的输入

BufferedReader stdin =

new BufferedReader(

new InputStreamReader(System.in));

System.out.println("Enter a line:");

System.out.println(stdin.readLine());

//2. 从一个String对象中读取数据

StringReader in2 = new StringReader(s2);

int c;

while((c = in2.read()) != -1)

System.out.println((char)c);

in2.close();

//3. 从内存取出格式化输入

try{

DataInputStream in3 =

new DataInputStream(

new ByteArrayInputStream(s2.getBytes()));

while(true)

System.out.println((char)in3.readByte());

}

catch(EOFException e){

System.out.println("End of stream");

}

//4. 输出到文件

try{

BufferedReader in4 =

new BufferedReader(

new StringReader(s2));

PrintWriter out1 =

new PrintWriter(

new BufferedWriter(

new FileWriter("F:\\nepalon\\ TestIO.out")));

int lineCount = 1;

while((s = in4.readLine()) != null)

out1.println(lineCount++ + ":" + s);

out1.close();

in4.close();

}

catch(EOFException ex){

System.out.println("End of stream");

}

//5. 数据的存储和恢复

try{

DataOutputStream out2 =

new DataOutputStream(

new BufferedOutputStream(

new FileOutputStream("F:\\nepalon\\ Data.txt")));

out2.writeDouble(3.1415926);

out2.writeChars("\nThas was pi:writeChars\n");

out2.writeBytes("Thas was pi:writeByte\n");

out2.close();

DataInputStream in5 =

new DataInputStream(

new BufferedInputStream(

new FileInputStream("F:\\nepalon\\ Data.txt")));

BufferedReader in5br =

new BufferedReader(

new InputStreamReader(in5));

System.out.println(in5.readDouble());

System.out.println(in5br.readLine());

System.out.println(in5br.readLine());

}

catch(EOFException e){

System.out.println("End of stream");

}

//6. 通过RandomAccessFile操作文件

RandomAccessFile rf =

new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");

for(int i=0; i<10; i++)

rf.writeDouble(i*1.414);

rf.close();

rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");

for(int i=0; i<10; i++)

System.out.println("Value " + i + ":" + rf.readDouble());

rf.close();

rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");

rf.seek(5*8);

rf.writeDouble(47.0001);

rf.close();

rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");

for(int i=0; i<10; i++)

System.out.println("Value " + i + ":" + rf.readDouble());

rf.close();

}

}

关于代码的解释(以区为单位):

1区中,当读取文件时,先把文件内容读到缓存中,当调用in.readLine()时,再从缓存中以字符的方式读取数据(以下简称“缓存字节读取方式”)。

1b区中,由于想以缓存字节读取方式从标准IO(键盘)中读取数据,所以要先把标准IO(System.in)转换成字符导向的stream,再进行BufferedReader封装。

2区中,要以字符的形式从一个String对象中读取数据,所以要产生一个StringReader类型的stream。

4区中,对String对象s2读取数据时,先把对象中的数据存入缓存中,再从缓冲中进行读取;对TestIO.out文件进行操作时,先把格式化后的信息输出到缓存中,再把缓存中的信息输出到文件中。

5区中,对Data.txt文件进行输出时,是先把基本类型的数据输出屋缓存中,再把缓存中的数据输出到文件中;对文件进行读取操作时,先把文件中的数据读取到缓存中,再从缓存中以基本类型的形式进行读取。注意in5.readDouble()这一行。因为写入第一个writeDouble(),所以为了正确显示。也要以基本类型的形式进行读取。

6区是通过RandomAccessFile类对文件进行操作。

----

重要提示:

LineNumberInputStream,StringBufferInputStream已经废除!大家不要再用!

StringBufferInputStream,This class does not properly convert characters into bytes!

StringBufferInputStream,Deprecated. This class incorrectly assumes that bytes adequately represent characters!

----------------关心IO,就是关心你的JAVA前途之路!-----------------------

DataInputStream流中已经没有readLine()整个方法!

替换为: BufferedReader d=new BufferedReader(new InputStreamReader(in));

--------把字节流转换为字符流接入缓存读取字符流中,再进行处理!

这个方法很大的优势!

----------------------

-----------------Why use character streams?------------------

The primary advantage of character streams is that they make it easy to write programs that are not dependent upon a specific character encoding, and are therefore easy to internationalize.

Java stores strings in Unicode, an international standard character encoding that is capable of representing most of the world's written languages. Typical user-readable text files, however, use encodings that are not necessarily related to Unicode, or even to ASCII, and there are many such encodings. Character streams hide the complexity of dealing with these encodings by providing two classes that serve as bridges between byte streams and character streams. The InputStreamReader class implements a character-input stream that reads bytes from a byte-input stream and converts them to characters according to a specified encoding. Similarly, the OutputStreamWriter class implements a character-output stream that converts characters into bytes according a specified encoding and writes them to a byte-output stream.

A second advantage of character streams is that they are potentially much more efficient than byte streams. The implementations of many of Java's original byte streams are oriented around byte-at-a-time read and write operations. The character-stream classes, in contrast, are oriented around buffer-at-a-time read and write operations. This difference, in combination with a more efficient locking scheme, allows the character stream classes to make up for the added overhead of encoding conversion in many cases.

----------标准设备System.in读取数据------------------

-----------------------------------------------------

读取字节:BufferedInputStream

读取字符:BufferedReader + InputStreamReader

----------------------------------------------

import java.io.*;

public class systemin

{

public static void main(String args[])

{ try{ //流转换!

BufferedReader is=new BufferedReader(new InputStreamReader(System.in))

String inputline=null;

while((inputline=is.readLine())!=null)

System.out.println(inputline);

is.close();

}

catch(IOException e)

{ System,out.println("IOXE: "+e);

}

}

}

--------------------------------------------------------------------------------

-----------------标准输出System.out是一个打印流PrintStream---------------------

import java.io.*;

public class PrintStandardOutput {

public static void main(String[] args) {

String myAnswer = "No, and that's final,";

System.out.println("Hello World of Java");

System.out.println("The answer is " + myAnswer + " at this time.");

PrintWriter pw = new PrintWriter(System.out);

pw.println("The answer is " + myAnswer + " at this time.");

int i = 42;

pw.println(i + '=' + " the answer.");

pw.println("Note: " + i + '=' + " the answer.");

pw.println(i + "=" + " the answer.");

pw.println(i + ('=' + " the answer."));

pw.close();

}

}

-----------------------------------------------------------------------------------

-----------------------要读取(输出到—)一个文本文件-----------------------------

BufferedReader is=new BufferedReader(new FileReader("xxxx.text"));读取

BufferedOutputStream byteout=new BufferedOutputStream(new FileOutputStream("XX.dat"));

// 写出到文本!

-----------------------------------------------

---------------利用 BufferedReader--FileReader读取文本文件!-----------

---------------在IO中始终要注意是字节流还是字符流----------------------

-----------------------------------------------------------------------

import java.io.*;

import java.awt.*;

import javax.swing.*;

import java.awt.event.*;

class filewindow extends JFrame implements ActionListener

{

JTextArea text;

BufferedReader in;

JButton button;

FileReader file;

filewindow()

{

super("文件字符流");

Container con=getContentPane();

text=new JTextArea(50,50);

text.setBackground(Color.blue);

try{

File f=new File("E:\\a.txt");

file=new FileReader(f);

in=new BufferedReader(file);

/**BufferedReader(Reader in)构造函数,

*文件自字符读取流FileReader接入BufferedReader

*流中,以便用BufferedReader的对象方法readLine()高效成行读取!

*/

}

catch(FileNotFoundException e){}

catch(IOException e){}

button=new JButton("读取");

button.addActionListener(this);

con.setLayout(new BorderLayout());

setSize(300,200);

setVisible(true);

con.add(text,"Center");

con.add(button,"South");

addWindowListener(new WindowAdapter()

{public void windowClosing(WindowEvent e)

{setVisible(false);System.exit(0);}});

}

public void actionPerformed(ActionEvent e)

{

String s;

if(e.getSource()==button)

try{

while((s=in.readLine())!=null)

text.append(s+'\n');

//在这里大家还可以用BufferString来暂时保存读取的字符数据!

}

catch(IOException e1){}

}

//---------main()----------

public static void main(String args[])

{

filewindow win=new filewindow();

win.pack();

}

}

-------------------RandomAccessFile随机读取文件---------------

import java.io.*;

public class RandomRead

{

final static String FILENAME="E:\\a.txt";

protected String fileName;

protected RandomAccessFile seeker;

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

RandomRead r = new RandomRead(FILENAME);

System.out.println("Offset is " + r.readOffset());

System.out.println("Message is \"" + r.readMessage() + "\".");

}

/** Constructor: save filename, construct RandomAccessFile */

public RandomRead(String fname) throws IOException {

fileName = fname;

seeker = new RandomAccessFile(fname, "rw");

}

/** Read the Offset field, defined to be at location 0 in the file. */

public int readOffset() throws IOException {

seeker.seek(0);

seeker.writeChars(FILENAME); // move to very beginning

return seeker.readInt(); // and read the offset

}

/** Read the message at the given offset */

public String readMessage() throws IOException {

seeker.seek(120); // move to where

return seeker.readLine(); // and read the String

}

}

写得很辛苦,我本来不想再说什么了,但本着对技术负责的精神还是说出来.

对于I/O的理解属于3级水平(如果java IO有十级的话)

错误太多.

对于I/O层次不熟悉

java IO主要包括

java.io包和java.nio包.

java.io主要从四个接口延伸:

字节:

InputStream/OutputStream,其下为封装,过滤,特定对象处理的具体实现类.

字符:

Reader/Writer(原文中连Writer接口全都写成Write,足以说明根本不了解这了接口,如果你经常使用Writer接口怎么会连Writer和Write都分不清,不是一处失误,而是全部都是Write)

以上四个接口中,底层全部是操作字节的阻塞方式流.

java.nio主要以块操作块(Buffer)为主,通过可以设定的阻塞和非阴塞模式,极大地提过了数据输出输

入的性能,而且将Channel通过选选择器模式的控制,可以实现在同一输出输入通道上多用户并发进行数据传输入.比如一个Socket端口可以同时被无限多(理论上不受限制)个客户端并发访问.就是经典的I/O多路复用技术.

0
0
分享到:
评论

相关推荐

    java之精髓IO流

    ### Java之精髓IO流 #### 一、Input和Output 在Java编程中,输入输出(Input/Output,简称IO)是处理数据交换的核心技术之一。Java的IO系统提供了丰富的类库来支持各种类型的输入输出操作,包括文件读写、网络通信...

    java IO 流浅谈

    ### Java IO流浅谈 #### 一、Java IO流概述 Java IO流是Java编程语言中用于处理输入输出...Java IO流的学习需要不断实践才能真正掌握其精髓,建议通过编写实际的代码来加深理解。希望本文能为您的学习之路提供帮助。

    java io技术精髓

    Java IO技术的精髓在于理解和灵活运用这些流及其组合,以满足各种数据处理需求。无论是简单的文件读写,还是复杂的网络通信,Java IO都有相应的工具和机制来支持。通过深入理解流的概念和使用方式,开发者能够更高效...

    java IO 类层次图

    ### Java IO 类层次结构解析 #### 一、概述 Java IO(Input/Output)系统是Java平台中的一个重要组成部分,用于处理程序与外部设备之间的数据交换。...希望本文能帮助您更好地理解和掌握Java IO系统的精髓。

    Java技术精髓Java技术精髓

    4. 核心类库:Java标准版(Java SE)提供了一套庞大的类库,包括集合框架、IO流、网络编程、多线程等。熟练掌握ArrayList、LinkedList、HashMap等集合容器的使用,了解IO流的字节流和字符流,以及Socket编程,可以...

    j0601IO_chicken_Java-IO_prettyjtt_

    Java IO(Input/Output)是Java编程语言中用于处理输入和输出操作的重要部分。这个"j0601IO_chicken_Java-IO_prettyjtt_"标题可能指的是一个关于Java IO...通过实践项目和解决实际问题,可以更好地掌握Java IO的精髓。

    javaIO操作入门

    Java IO(Input/Output)操作是Java编程中的一个重要部分,它允许程序与外部资源进行数据交换,如磁盘、网络、内存等。...通过实践编写读写文件、网络通信等示例程序,可以更好地掌握Java IO的精髓。

    Java 技术精髓

    5. **IO与NIO**:Java的IO流系统用于读写文件和网络通信,而NIO(New Input/Output)提供了一种非阻塞I/O模型,提高了数据传输性能。 6. **反射与注解**:反射允许程序在运行时检查和操作类、接口、方法等,而注解...

    java技术精髓(可帮助正在设计或建立企业级java系统的技术人员节省时间)

    1. **内存管理与垃圾回收**:Java的自动内存管理是其魅力之一,但同时也可能导致性能问题。理解如何调整堆内存大小、新生代和老年代的比例,以及如何优化垃圾回收策略,对于提高系统的响应速度至关重要。 2. **JVM...

    第10章 Java IO系统.pdf

    Java 1.0引入了基础的IO流库,而在Java 1.1中,库进行了扩展,增加了许多新特性。 10.1 输入和输出 Java的IO类主要分为输入流(InputStream)和输出流(OutputStream)两大类。InputStream的所有子类提供了读取数据...

    候捷的java精髓

    4. **IO流**:涵盖输入输出流的分类、使用和文件操作,包括字符流和字节流,以及缓冲流、转换流等高级用法。 5. **多线程**:讲解线程的创建、同步和通信,包括synchronized关键字、wait()、notify()和join()方法的...

    Java入门到精髓实例板PPT接(11-21章)

    第16章至第21章的内容可能会涵盖反射、泛型、枚举、注解、IO流的高级用法、NIO(非阻塞I/O)等进阶主题。反射允许我们在运行时动态获取类的信息和调用方法;泛型则提供了类型安全,增强了代码的可读性和可维护性;...

    Java高级编程核心内容讲解大全

    Java作为一门广泛使用的编程语言,其高级编程内容涵盖了众多领域,包括但不限于面向对象设计、并发处理、内存管理、反射机制、泛型、IO流、网络编程等。本讲解大全将聚焦于这些核心主题,帮助致力于Java深层次研究的...

    java学习从入门到深入的经典书籍,Head+First+Java,think+in+java

    同时,你还会接触到Java标准库,其中包含大量实用类和接口,如Collections框架,用于处理数组和集合数据结构,以及IO流API,用于文件操作和数据传输。 除了理论知识,实践是提高编程技能的关键。通过阅读书籍并结合...

    java编程思想thinking in java

    8. **IO流**:Java的IO流体系提供了读写数据的抽象,涵盖了字符流和字节流,以及输入流和输出流。NIO(New IO)进一步增强了IO性能,支持非阻塞I/O。 9. **多线程**:Java内置对多线程的支持,允许程序同时执行多个...

    Java记事本程序 (Java程序设计入门实例,本人老师)

    综上所述,Java记事本程序是一个综合性的学习项目,涵盖了Java基础语法、IO操作、GUI编程、设计模式等多个方面的内容,对于初学者来说,它是一个很好的实践平台,有助于理解和掌握Java编程的精髓。通过分析和实现这...

    java开发实战经典

    5. **IO流**:理解输入输出流的概念,学习File类、字节流、字符流、缓冲流、对象序列化等,以及NIO(New IO)的相关内容。 6. **多线程**:讲解线程的创建方式(Thread类和Runnable接口)、线程同步(synchronized...

    java程序代码

    - Java的IO流系统支持对文件、网络和内存的数据读写,包括字节流和字符流。 - NIO(非阻塞I/O)提供了一种更高效的I/O模型,适用于高并发场景。 7. **多线程** - Java内置了对多线程的支持,可以通过实现...

    java核心技术第九版

    这本书深入浅出地讲解了Java语言的核心概念和技术,旨在帮助读者掌握Java编程的基础与精髓。书中涵盖了广泛的Java知识,包括语法、面向对象编程、集合框架、多线程、I/O流、网络编程、数据库连接等。 1. **Java语法...

    SE_JAVA_EXP_E046.zip

    由于文件名为"SE_JAVA_EXP_E046",我们可以推测这可能是系列练习题中的第46个,可能涉及到一些进阶主题,例如面向对象编程、异常处理、多线程、集合框架或者IO流等。 在Java编程中,面向对象编程(Object-Oriented ...

Global site tag (gtag.js) - Google Analytics