java IO详解(转)
1. Abstract:
Java将I/O分为高阶I/O与低阶I/O,高阶I/O在使用上提供更多的读写方法,如读写
int、double、String的资料型态,而低阶的I/O大部份只提供write、read的byte[]存取,因为程式大部份的资料都是以字串或
其它主要型态资料来运算,因此低阶的I/O在使用上不利於程式设计,所以Java将许多好用的方法全部集合成高阶I/O;
换言之,低阶I/O的主要工作是负责与媒体资料作存取,高阶I/O类别主要作资料型态的转换及提供一些特殊的功能。在使用Java
I/O时要谨记的一个重要原则是,在建立一个I/O之前必需先用低阶I/O类别来存取媒体资料(如档案或pipe),之後再使用高阶I/O来控制低阶I
/O类别的动作,这种一层又一层的架构称I/O
Chain。底下为Java的I/O架构图,第一个为以byte为单位的I/O,第二个则是以char为单位。
2. File I/O:
A. FileInputStream & FileOutputStream
FileInputStream是读取档案用的类别,其建构式有叁个:
public FileInputStream(String strFilename) throws FileNotFoundException
public FileInputStream(File fIn) throws FileNotFoundException
public FileInputStream(FileDescriptor fdObj)
在这里我只讲第一个,这是最直觉的方式,如下的范例1,会一次从e:\test.txt读10个bytes,将读入的结果输出到标准输出设备,直到档案结
束。在这个范例中要注意的是,available会传回输入串流中还有多少个bytes,read则会根据buffer的大小来决定一次读几个
bytes,并将实际读到的byte数传回。
===== 范例 1 =====
import java.io.*;
public class FIn {
public FIn() {
try {
FileInputStream fis = new FileInputStream("e:/in.txt");
while (fis.available() > 0) {
byte[] b = new byte[10];
int nResult = fis.read(b);
if (nResult == -1) break;
System.out.println(new String(b));
}
fis.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
FIn fIn = new FIn();
}
}
FileOutputStream是写入档案用的类别,其建构式有四个:
Public FileOutputStream(String strFilename) throws FileNotFoundException
Public FileOutputStream(File fOut) throws FileNotFound Exception
Public FileOutputStream(FileDescriptor fdObj)
public FileOutputStream(String name, boolean append) throws FileNotFoundException
第四个和第一个的差别只在於当档案存在时,第一个会将原来的档案内容覆盖,第四个则可以选择覆盖或将新内容接在原内容後面。范例2以建构式一讲解如何写入
一个档案…在这个范例中要注意的是,fIn每个读10个bytes,但是最後一次不一定会读10个bytes,因此,fOut在write时,要指明要写
几个bytes到档案中,否则最後一次仍会写入10个bytes,因Java在new byte时会先将内容先填0,所以後面的几个bytes会是0。
===== 范例2 =====
import java.io.*;
public class FOut {
public FOut() {
try {
FileInputStream fIn = new FileInputStream("e:/in.txt");
FileOutputStream fOut = new FileOutputStream("e:/out.txt");
while (fIn.available() > 0) {
byte[] b = new byte[10];
int nResult = fIn.read(b);
if (nResult == -1) break;
fOut.write(b, 0, nResult);
}
fIn.close();
fOut.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
FOut FOut1 = new FOut();
}
}
B. FileReader & FileWriter
FileReader和FileInputStream最大不同在於,FileInputStream读取的单位是
byte,FileReader读取的单位是char。另外要注意的是,在FileInputStream中以available来判断是否还有资料可读
取,在FileReader中是以ready来判断,
但是,available是传回还有多少个bytes可以读取,ready则传回true或false,当传回true时表示,下次read时保证不会停顿,当传回false时,表示下次read时”可能”停顿,所谓可能是指不保证不会停顿。
Ps. 测试时,in.txt里放些中文字就可以看出以byte和以char为单位有什麽不同。
===== 范例 3 =====
import java.io.*;
public class chFIn {
public chFIn() {
try {
FileReader rdFile = new FileReader("e:/in.txt");
while (rdFile.ready()) {
char[] chIn = new char[10];
int nResult = rdFile.read(chIn);
if (nResult == -1) break;
System.out.println(chIn);
}
rdFile.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
chFIn chFIn1 = new chFIn();
}
}
FileWriter和FileOutputStream的最大不同也在於写入单位的不同,FileOutputStream为byte,FileWriter为char。
===== 范例 4 =====
import java.io.*;
public class chFOut {
public chFOut() {
try {
FileReader rdFile = new FileReader("e:/in.txt");
FileWriter wrFile = new FileWriter("e:/out.txt");
while (rdFile.ready()) {
char[] chIn = new char[10];
int nResult = rdFile.read(chIn);
if (nResult == -1) break;
wrFile.write(chIn, 0, nResult);
}
rdFile.close();
wrFile.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
chFOut chFOut1 = new chFOut();
}
}
C. BufferedReader & BufferedWriter
File I/O是相当耗时的作业,通常电脑在做处理时,者会建立一个缓冲区,一次读取或写入一个区块,借由减少I/O次数,来节省时间 ,在Java中的BufferedReader和BufferedWriter就是提供这样的缓冲功能。
在
范例5中,我们将FileReader导向BufferedReader,将FileWriter导向BufferedWriter,来达到区块读取、写
入的目的。BufferedReader提供的readLine一次可以读取一行,当遇到档尾时,会传回null。BufferedWriter提供的
newLine会产生列尾符号,这个列尾符号随作业系统的不同而不同,在Windows上为\r\n,在Unix上为\n,在Mac上为\r,这个符号是
依据line.separator系统性质而来的。需注意的是,如果将BufferedWriter应用到网路程式时,绝对不要使用newLine,因为
绝大多数的网路协定都是以\r\n为列尾,不会因作业系统不同而异。
===== 范例 5 =====
import java.io.*;
public class bufIn {
public bufIn() {
try {
FileReader rdFile = new FileReader("e:/in.txt");
BufferedReader brdFile = new BufferedReader(rdFile);
FileWriter wrFile = new FileWriter("e:/out.txt");
BufferedWriter bwrFile = new BufferedWriter(wrFile);
String strLine;
while ((strLine = brdFile.readLine()) != null) {
bwrFile.write(strLine);
bwrFile.newLine();
}
brdFile.close();
bwrFile.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
bufIn bufIn1 = new bufIn();
}
}
D. File
在档案处理方面,程式不只是要对档案做读、写,有时也需要得知档案的属性,或删除、移动、更名,有时则是要找出或列出某目录下的某些档案,针对这些运作,Java提供了File这个类别。底下的范例,说明如何使用File类别。
a. 如何得知档案属性:
在范例6中需注意的是lastModified传回的最後更改时间是自1970/1/1
00:00:00算起的时间,单位为毫秒,所以要用Date将它转换成日期、时间;
另外getCanonicalPath和getAbsolutePath得到的值在Windows上会是一样的,在Unix可能就会不一样。
===== 范例 6 =====
import java.io.*;
import java.util.*;
public class FileSpy {
public FileSpy(String strFilename) {
File fFile = new File(strFilename);
if (fFile.exists()) {
System.out.println("Name: " + fFile.getName());
System.out.println("Absolute path: " + fFile.getAbsolutePath());
try {
System.out.println("Canonical path: " + fFile.getCanonicalPath());
}
catch (IOException e) {
e.printStackTrace();
}
if (fFile.canWrite()) System.out.println(fFile.getName() + " is writable");
if (fFile.canRead()) System.out.println(fFile.getName() + " is readable");
if (fFile.isFile()) {
System.out.println(fFile.getName() + " is a file");
}
else if (fFile.isDirectory()) {
System.out.println(fFile.getName() + " is a directory");
}
else {
System.out.println("What is this?");
}
long lngMilliseconds = fFile.lastModified();
if (lngMilliseconds !=0) System.out.println("last modified at " + new Date(lngMilliseconds));
long lngLen = fFile.length();
if (lngLen !=0) System.out.println("size: " + lngLen);
}
else
System.out.println("file not found");
}
public static void main(String[] args) {
if (args.length == 1) {
FileSpy fileSpy1 = new FileSpy(args[0]);
}
else
System.out.println("Usage: java FileSpy Filename");
}
}
b. 建立、删除、移动、更名:
File类别提供了createNewFile、renameTo、delete作为建立
(createNewFile)、删除(delete)、移动、更名(renameTo)之用,使用方式如下:
(移动和更名都用renameTo,就如在Unix上档案搬移和更名都用mv一样)
===== 范例 7 =====
import java.io.*;
public class OperateFile {
public OperateFile() {
//create new file
File fNewFile = new File("C:/newfile.txt");
try {
if (fNewFile.exists() == false) {
if (fNewFile.createNewFile() == true) {
System.out.println("create c:/newfile.txt success");
}
else {
System.out.println("create c:/newfile.txt fail");
}
}
else {
System.out.println("file already exists");
}
}
catch (IOException e) {
e.printStackTrace();
}
//rename file
File fRenameFile = new File("c:/renamefile.txt");
fNewFile.renameTo(fRenameFile);
//remove file
File fRemoveFile = new File("d:/" + fRenameFile.getName());
fRenameFile.renameTo(fRemoveFile);
//delete file
try {
File fDelFile = new File(fRemoveFile.getCanonicalPath());
fDelFile.delete();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
OperateFile operateFile1 = new OperateFile();
}
}
c. 找出某特定目录里的所有档案:
File类别提供的list和listFiles都可以列出某特定目录里的所有档案,其中list传回的是String[],listFiles传回的是File[],这两个函式都会传回所有的档案和目录。
===== 范例 8 =====
import java.io.*;
public class ListAllFiles {
public ListAllFiles(String strDir) {
File fDir = new File(strDir);
File[] fAllFiles = fDir.listFiles();
for(int i=0; i
if (fAllFiles.isFile())
System.out.println("File: " + fAllFiles.getName());
else
System.out.println("Dir: " + fAllFiles.getName());
}
}
public static void main(String[] args) {
ListAllFiles listAllFiles1 = new ListAllFiles(args[0]);
}
}
3. Network I/O:
Java对网路的支援只有TCP/IP和UDP/IP,提供的类别有URL、URLConnection、Socket、ServerSocket,在这里我只打算用ServerSocket、Socket为例,来说明Network I/O。
基本上,Java的I/O不管在任何的媒体上都是将它们视为stream,所以,网路I/O和档案I/O原理也是一致的,底下的两个程式分别为server socket及client socket。在看范例之前,可以再复习一下前面的abstract…
===== 范例 9 =====
import java.net.*;
import java.io.*;
public class myServer {
public myServer(String strPort) {
int nPort = new Integer(strPort).intValue();
try {
ServerSocket ss = new ServerSocket(nPort);
Socket s = ss.accept();
OutputStream out = s.getOutputStream();
PrintStream psOut = new PrintStream(out);
String strResponse = "Hello " + s.getInetAddress() + " on port " + s.getPort() + "\r\n";
strResponse += "This is " + s.getLocalAddress() + " on port " + s.getLocalPort() + "\r\n";
psOut.print(strResponse);
s.close();
ss.close();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
myServer myServer1 = new myServer(args[0]);
}
}
===== 范例 10 =====
import java.net.*;
import java.io.*;
public class myClient {
public myClient(String strIP, String strPort) {
int nPort = new Integer(strPort).intValue();
try {
Socket s = new Socket(strIP, nPort);
InputStream in = s.getInputStream();
BufferedInputStream bisIn = new BufferedInputStream(in);
while (bisIn.available() > 0) {
byte[] b = new byte[30];
int nLen = bisIn.read(b);
System.out.println(new String(b, 0, nLen));
}
}
catch (UnknownHostException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
myClient myClient1 = new myClient(args[0], args[1]);
}
}
4. Object Serialization:
A. 所谓Object
Serialization就是把物件的”状态”储存成一系列的位元组,而这些位元组在稍候可用来恢复物件。更简单的说,Object
Serialization是让物件可以以物件为储存单位。在Java中,任何物件要能Serialization,必须implements
Serializable这个Interface,以下是一个简单的程式范例,可以将物件储存到e:\point.ser,或从e:\point.ser
将物件恢复原值。
===== 范例 11 =====
import java.io.*;
public class ThreeDPoint implements Serializable
{
private double m_dblX, m_dblY, m_dblZ;
public ThreeDPoint(double x, double y, double z)
{
m_dblX = x;
m_dblY = y;
m_dblZ = z;
}
public void PrintXYZ()
{
System.out.println("X: " + m_dblX);
System.out.println("Y: " + m_dblY);
System.out.println("Z: " + m_dblZ);
}
public static void main(String[] args)
{
if (args[0].equalsIgnoreCase("w")) {
ThreeDPoint threeDPoint1 = new ThreeDPoint(10 ,20, 30);
try {
FileOutputStream fout = new FileOutputStream("e:\\point.ser");
ObjectOutputStream oout = new ObjectOutputStream(fout);
oout.writeObject(threeDPoint1);
oout.close();
System.out.println("write:");
threeDPoint1.PrintXYZ();
}
catch (Exception e) {
e.printStackTrace();
}
}
else if (args[0].equalsIgnoreCase("r")) {
try {
FileInputStream fin = new FileInputStream("e:\\point.ser");
ObjectInputStream oin = new ObjectInputStream(fin);
Object o = oin.readObject();
ThreeDPoint threeDPoint1 = (ThreeDPoint) o;
oin.close();
System.out.println("read:");
threeDPoint1.PrintXYZ();
}
catch (Exception e) {
}
}
} //end of main
}
B. 在Java中,一个实作某特定介面的类别,其子类别也因继承的原故而被视为实作了该介面,因此,许多没有明确宣告实作Serializable介面的类别,事实上也是可以被Serialization的。
C. 并非每个实作了Serializable介面的物件都可以被Serialization,如果这个物件继承图上的祖先,有其中一个是不可以被Serialization,那麽这个物件就不可以被Serialization。
5. Formated I/O:
在
Java的I/O里,并没有所谓的型别,不管是int、long、double…最後都是以String输出,所以如果要让数字以特定格式输出,需透过
Java提供的两个类别java.text.NumberFormat和java.text.DecimalFormat将数字格式化後再输出。
范
例12简要说明NumberFormat如何使用,在开始使用NumberFormat时,应先用getInstance取得NumberFormat的
实体,范例12中的setMaximumIntegerDigits和setMinimumFractionDigits是用来设定整数和小数的位数,另
外还有setMinimumIntegerDigits和setMaximumFractionDigits也是同样功能。这些设定如有冲突,Java以
最後设定的为准。
===== 范例 12 =====
import java.text.*;
public class myFormat {
public myFormat() {
NumberFormat nf = NumberFormat.getInstance();
double dblNum = Math.PI;
System.out.println(dblNum);
nf.setMaximumIntegerDigits(5);
nf.setMinimumFractionDigits(4);
System.out.println("PI: " + nf.format(dblNum));
}
public static void main(String[] args) {
myFormat myFormat1 = new myFormat();
}
}
另
一个类别DecimalFormat是继承NumberFormat的子类别,它提供了更强的格式化功能,透过设定pattern,可以使我们的输出更多
样化,至於Java提供的pattern有那些? 在API Document中有详细说明!
范例13仅举其一,说明DecimalFormat如何使用。
===== 范例 13 =====
import java.text.*;
public class myDecimalFormat {
public myDecimalFormat() {
DecimalFormat df = new DecimalFormat("0000.000");
double dblNum = 123.45;
System.out.println("dblNum: " + dblNum);
System.out.println("dblNum: " + df.format(dblNum));
}
public static void main(String[] args) {
myDecimalFormat myDecimalFormat1 = new myDecimalFormat();
}
}
分享到:
相关推荐
Java IO 详解 Java IO(Input/Output)是 Java 语言中用于处理输入输出操作的类库,提供了大量的类和方法来实现文件、网络、字节流等方面的输入输出操作。下面对 Java IO 中的重要知识点进行详细说明。 一、File ...
### Java IO详解知识点 #### 一、Java IO系统概述 - **Java I/O系统的重要性**:Java I/O系统是Java编程中的基础组成部分之一,用于处理数据的输入与输出。理解和熟练掌握Java I/O系统对于开发高质量的应用程序至...
### Java IO 详解 #### 一、Java IO体系概述 Java IO(Input/Output)是Java编程语言中处理输入输出的基础。它主要包括两大类:字节流和字符流。字节流主要处理二进制数据,如图片、音频等;字符流则用于处理文本...
Java 中的 IO 详解 Java IO 是指应用程序对外部设备的数据输入和输出,在程序中,键盘被当作输入文件,显示器被当作输出文件使用。Java 语言定义了许多类专门负责各种方式的输入输出,这些类都被放在 java.io 包中...
### Java IO详解 #### 1. 什么是IO 在计算机科学中,IO(Input/Output,输入/输出)指的是程序与外部系统之间进行数据交换的过程。在Java中,IO操作主要通过`java.io`包来实现,这个包包含了用于文件读写、标准...
Java IO 是Java平台中用于处理输入输出操作的重要部分,它提供了丰富的类库,使得开发者能够高效地读写数据。在Java中,IO是以流为基础进行的,数据被串行化写入输出流或从输入流读取。Java的IO体系分为字节流和字符...
Java IO 之字节流和字符流的区别 Java 中的 IO 操作是指对文件、网络或其他输入/输出设备的读写操作。Java 中的 IO 操作可以分为两大类:字节流和字符流。字节流和字符流是 Java 中的两种基本的 IO 操作方式,它们...
JavaIO文件复制优化——JavaIO优化详解(下载可用)。个人经导师指导并认可通过的98分大作业设计项目,适用人群:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业或毕业设计,作为“参考资料”使用。...
Java_IO流详解 Java 的核心库 java.io 提供了全面的 IO 接口,包括文件读写、标准设备输出等。Java 中 IO 是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。在项目开发中,IO 是非常...
JavaIO流详解归纳 Java 的核心库 java.io 提供了全面的 IO 接口,包括文件读写、标准设备输出等。Java 中 IO 是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。在项目开发中,IO 是非常...
Java 中的 IO 流详解 Java 中的 IO 流是指在 Java 语言中对输入输出操作的抽象,主要用于实现程序与外部设备和其他计算机之间的交流,尤其是对磁盘文件的操作。IO 流的概念是在 1984 年由 C 语言第一次引入的,后来...
### Java IO流详解 #### 一、流的概述与分类 在Java中,流是一种抽象概念,用于描述数据从一个地方传输到另一个地方的过程。它主要用于处理数据输入和输出,例如从磁盘读取文件、向网络发送数据或从键盘接收用户...
java IO部分详解各种流的解析例如 InputStream
### Java IO流详解 #### 一、Java IO流概述 Java IO流是Java标准库中的一个重要组成部分,主要用于处理数据的输入输出操作。根据处理的数据类型不同,Java IO流被分为两大类:字节流(byte streams)和字符流...
### JAVA IO流详解 #### 一、Java IO流概述 Java IO流是Java程序与外部设备之间进行数据交互的重要方式之一。Java的核心库`java.io`提供了丰富的接口用于实现文件读写、标准设备输入输出等功能。Java IO流的设计...
Java IO流详解
JAVA IO流是Java编程中用于处理输入输出操作的重要工具。IO流主要分为两大类,即输入流(Input Streams)和输出流(Output Streams),它们用于读取或写入数据到不同的数据源,比如文件、网络连接或内存中的字节数组。在...
Java IO 流的理解和使用。 Java 的 IO 模块是其强大的特性之一,它提供了丰富的类和接口用于处理输入和输出操作。IO 流在 Java 中扮演着至关重要的角色,尤其是在处理文件、网络通信和系统间的数据交换时。Java 的 ...