基础知识
1.文件操作
Java语言统一将每个文件都视为一个顺序字节流。每个文件或者结束于一个文件结束标志,或者根据系统维护管理数据中所纪录的具体字节数来终止。当一个文件打开时,一个对象就被创建,同时创建一个流和该对象关联。
基于Java的平台无关性特点,Java的文件访问机制也是独立于文件系统。为了克服在Windows 和 UNIX系统下,不同的路径分隔符. Windows使用”\”, Unix使用”/”, File类提供了 file.separator静态值来解决分隔符的问题。而绝对路径的约定,在UNIX平台”/”为绝对路径,在Windows平台”E:\”为绝对路径。
Java对文件的操作可通过File和RandomAccessFile类来实现。在文件操作中,java.io.File类是重要类,它提供创建文件和目录以及访问文件信息的有关描述和操作,使用File类注意:它是通过某个路径创建一个File类,并不需要真正存在这个目录或文件,而是通过这个对象来保存对文件和目录的引用。即利用文件名和路径名来实例化一个文件类。
RandomAccessFile类可以处理任何类型的数据文件。该类可以对多种格式的文件进行访问操作,它支持对文件的随机访问,即可以在文件的任意位置上进行数据存取操作。其特点:实现对文件的非顺序方式随机存取;既是输入流,也是输出流, 通过参数决定流的类型。
文件操作中可能出现的异常包括:
l_ IllegalArgumentException,参数不吻合
l_ IOException,输入/输出错误
l_ SecurityException,读写模式不对
l_FileNotFoundException,文件未找到
2.JAVA流
流指一个数据序列,是一种逻辑上的虚拟结构,一端是数据源端,另一端是数据目的端。流的两端都有一定的数据缓冲区用来暂存数据, 数据到达后先保存在缓冲中, 等需要的时候再读取. 发送端也是等缓冲中一定数量的数据后再发送. 这样的设计可以有效的提高传输效率,如图1-1所示。
流分为输入流(Input Stream)和输出流(Output Stream),在Java中相应提供了两个抽象(abstract)的流操作类InputStream和OutputStream, 并且以这些类为基础, 派生了许多类用于I/O的具体操作
在Java.io包中提供了60多个流相关类,从功能上分为:输入流和输出流;从流结构上可分为:字节流和字符流。
I/O操作的一般步骤如下:
1) 使用引入语句引入java.io包,import java.io.*;
2) 根据不同的数据源和I/O任务,建立字节或者字符流;
3) 若需要对字节或字符流信息组织加工为数据,在已建字节或字符流对象上构建数据流对象;
4) 用输入输出对象类的成员方法进行读写操作,需要时设置读写位置指针;
5) 关闭流对象。
3.文件压缩
在进行网络传输时,为了得到更快的传输速度,经常将待发送的数据进行压缩。在java.util.zip类库包中提供了标准读写zip和gzip文件方法。
l_ZipFile类用于创建一个压缩文件的描述,类似与File类。
l_ ZipEntry类用于创建一个压缩文件的入口描述
Public InputStream getInputStream(ZipEntry entry) throws IOException
遗憾的是,使用Java自带的类 java.util.zip进行文件/目录的压缩的话,有一点不足,不支持中文的名件/目录命名,当待压缩文件名称中,出现中文或非ASIIC码字符时,就会出错。
目前一般的Ant.jar类库中也有zip类,import org.apache.tools.zip.*,能够解决不支持中文文件目录的问题,同时,Ant的获得途径也比较多,一般的应用服务器中有这个包,可在tomcat5.X中找到ant.jar类库包。
类及方法
1.File常用方法
boolean |
canRead() 判断文件是否可读 |
boolean |
canWrite()判断文件是否可写 |
boolean |
createNewFile() 创建新文件 |
boolean |
delete() 删除文件 |
getAbsoluteFile() 获得绝对文件类型 |
|
getAbsolutePath() 获得绝对路径名 |
|
getCanonicalFile() 获得标准文件类型 |
|
getCanonicalPath()获得标准文件路径 |
|
getName() 获得文件名 |
|
getParent() 获得父路径名 |
|
getPath() 获得路径名 |
|
boolean |
isDirectory() 判断是否为目录 |
boolean |
isFile()判断是否为文件 |
boolean |
isHidden()判断是否为隐藏 |
long |
lastModified()最后修改时间 |
long |
length() 获得文件长度 |
String[] |
list() 获得目录中文件名列表 |
String[] |
list(FilenameFilter filter) 获得目录中指定字符文件列表 |
File[] |
listFiles() 列出文件类型列表 |
boolean |
mkdir() 创建目录 |
boolean |
|
boolean |
setLastModified(long time)更改最后文件修改时间 |
boolean |
setReadOnly() 设置文件为只读 |
2.RamdomAccessFile常用方法
void |
close() 关闭该文件流,释放资源 |
long |
getFilePointer() 获得文件当前指针 |
long |
length() 获得文件长度 |
int |
read() 读取数据 |
int |
read(byte[] b) 读取数据至数组 |
int |
read(byte[] b, int off, int len) 读取数据至数组指定位置 |
boolean |
readBoolean() 读取boolean 数据 |
byte |
readByte() 读取有符号8bit数据 |
char |
readChar() 读取Unicod字符 |
void |
readFully(byte[] b) 读取数据byte数组 |
int |
readInt()读取有符号32bit integer数值 |
readLine()按行读取数据 |
|
readUTF()读取字符串 |
|
void |
seek(long pos) 指针跳过指定字符数 |
void |
setLength(long newLength)设置文件长度 |
int |
skipBytes(int n) 跳过指定长度的字节数 |
void |
write(byte[] b) 保存字节数组至文件 |
void |
write(byte[] b, int off, int len) 保存字节数组指定长度至文件 |
void |
write(int b)保存int数值 |
void |
writeBoolean(boolean v) 保存boolean数值 |
void |
writeByte(int v) 保存byte数值 |
void |
writeBytes(String s) 保存字符串数值 |
void |
writeChar(int v) 保存char数值 |
void |
writeChars(String s) 保存字符串数值 |
void |
writeInt(int v) 保存int数值 |
void |
3.FileInputStream常用方法
int |
available() 判断该文件是否可读取, |
void |
close() 关闭输入流 |
getFD() 获得输入流的文件描述对象 |
|
int |
read() 读取一个字节 |
int |
read(byte[] b)读取一个字节数组 |
int |
read(byte[] b, int off, int len) 读取指定长度的数据到指定数据的位置 |
long |
skip(long n) 跳过一定数量的字节 |
4.FileOutputStream常用方法
void |
close() 关闭输出流 |
getFD() 获得该流的文件描述对象 |
|
void |
write(byte[] b) 输出字节数组 |
void |
write(byte[] b, int off, int len) 输出字节数组中指定数据 |
void |
write(int b) 输出一个整数(字符) |
5.DataInputStream常用方法
int |
read(byte[] b) 从输入流读取数据至字节数组中。 |
int |
read(byte[] b, int off, int len) 从输入流读取数据至字节数组中指定位置和长度。 |
boolean |
readBoolean() 读取boolean类型数据 |
byte |
readByte() 读取byte类型数据 |
char |
readChar() 读取char类型数据 |
int |
readInt()读取int类型数据 |
readUTF()读取UTF类型数据 |
|
int |
skipBytes(int n) 在输入流跳过指定长度字节数。 |
6.DataOutputStream常用方法
void |
flush() 立刻输出 |
int |
size() 返回输出流字节数 |
void |
write(byte[] b, int off, int len)输出数组中指定位置和长度的byte数 |
void |
write(int b)输出int类型数据 |
void |
writeBoolean(boolean v) 输出boolean类型数据 |
void |
writeByte(int v) 输出byte类型数据 |
void |
writeBytes(String s) 以字节形式输出String类型数据 |
void |
writeChar(int v) 输出char类型数据 |
void |
writeChars(String s) 输出String类型数据 |
void |
writeInt(int v) 输出int类型数据 |
void |
7.ZipFile常用方法
void |
close() 关闭 |
entries() 返回ZIP文件列表 |
|
protected void |
finalize() 保证ZIP操作正确完成 |
getInputStream(ZipEntry entry) 获得ZIP输入流 |
|
getName()获得ZIP文件名 |
|
int |
size()获得ZIP文件包内被压缩的文件数量 |
代码示例
File类方法练习
1 import java.io.*; 2 class exp_4_2{ 3 public static void main(String [] args){ 4 try{ 5 File myFile = new File("d:\f-disk\test.xml"); 6 System.out.println(myFile.getName() + "是目录?"+myFile.( )); 7 System.out.println("可读/写?" + 8 myFile.canRead() + "/"+myFile.( )); 9 System.out.println("文件字节长度"+myFile.length()); 10 System.out.println(_________________); 11 System.out.println(myFile.getParent()); 12 System.out.println(myFile.getAbsolutePath()); 13 File newFile = new File("testNew.java"); 14 myFile.renameTo(newFile); 15 System.out.println("修改该文件名为:testNew.java"); 16 System.out.println("目录中有以下文件:"); 17 File myDir = new File(myFile.getParent()); 18 String [] files = myDir.( ); 19 for(int i=0; i<files.length; i++){ 20 System.out.println(files[i]); 21 } 22 }catch(Exception e){ 23 System.err.println(e.toString()); 24 } 25 } 26 }
输入字符和数据
1 //注意C3的输出结果,解释为什么会得到该结果 2 import java.io.*; 3 class exp_4_1a{ 4 public static void main(String [] args){ 5 try{ 6 int c1 = System.in.read(); 7 System.out.println("c1 = " + c1); 8 char c2 = (char)c1; 9 System.out.println("c2 = " + c2); 10 char c3 = (char)System.in.read(); 11 System.out.println("c3 = " + c3); 12 }catch(Exception e){ 13 System.err.println(e.getMessage()); 14 } 15 } 16 } 17 ############################################# 18 import java.io.*; 19 class exp_4_1b{ 20 public static void main(String args[])throws IOException{ 21 BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 22 System.out.print("输入一个整数:"); 23 String str = br.readLine(); 24 int i = Integer.parseInt(str); 25 System.out.print("输入一个实数:"); 26 String str = br.readLine(); 27 float f = Float.parseFloat(str); 28 System.out.println("它们的和是" + ( i + f)); 29 } 30 } 31 ############################################# 32 import java.util.*; 33 public class exp_4_1c{ 34 public static void main(String args[]){ 35 System.out.println("请输入若干个数,每输入一个数用回车确认"); 36 System.out.println("最后输入一个非数字结束输入操作"); 37 Scanner reader=new Scanner(System.in); 38 double sum=0; 39 int m=0; 40 while(reader.hasNextDouble()){ 41 double x=reader.nextDouble(); 42 m=m+1; 43 sum=sum+x; 44 } 45 System.out.println("%d个数的和为%f/n",m,sum); 46 System.out.println("%d个数的平均值是%f/n",m,sum/m); 47 } }
显示程序文件当前所在的目录树结构
1 import java.io.*; 2 3 class exp_4_2{ 4 public static void main(String args[]){ 5 File dir = new File(System.getProperty("user.dir")); //获得程序当前运行路径 6 File filename = null; 7 8 if(dir.isDirectory()){ 9 System.out.println("Directory of " + dir); 10 String listing[] = dir.list(); 11 12 for(int i=0;i<listing.length;i++){ 13 System.out.println(" " + listing[i]); 14 15 filename = new File(listing[i]); 16 17 if(filename.isDirectory()){ 18 19 String listing2[] = filename.list(); 20 for(int j=0;j<listing2.length;j++){ 21 System.out.println(" " +" " + listing2[j]); 22 } 23 } 24 } 25 } } }
保存数据,发现并修改其中错误
1 import java.io.*; 2 class exp_4_3{ 3 public static void main(String args[]){ 4 try{ 5 OutputStream fos = new FileOutputStream("fib.dat"); 6 DataOutputStream dos = new DataOutputStream(fos); 7 int i = 1, j = 1; 8 for(int count =0;count<20;count++){ 9 dos.writeInt(i); 10 int k = i + j; 11 i = j; 12 j = k; 13 } 14 dos.flush(); 15 dos.close(); 16 fos.close(); 17 }catch(Exception e){ 18 System.err.println(e.toString()); 19 } 20 try{ 21 InputStream fis = new FileInputStream("fib.dat"); 22 DataInputStream dis = new DataInputStream(fis); 23 int k = 0; 24 while(k != -1){ 25 k = dis.readInt(); 26 System.out.println(k); 27 } 28 dis.close(); 29 fis.close(); 30 }catch(Exception e){ 31 System.err.println(e.toString()); 32 } } }
合并文件
1 import java.io.*; 2 import java.util.*; 3 //该类提供了对向量的包装,返回根据文件名打开的FileInputStream. 4 class InputStreamEnumerator implements Enumeration { 5 PRivate Enumeration files; 6 public InputStreamEnumerator(Vector files) { 7 this.files = files.elements(); 8 } 9 public boolean hasMoreElements() { 10 return files.hasMoreElements(); 11 } 12 public FileInputStream nextElement() { 13 try { 14 return new FileInputStream(files.nextElement().toString()); 15 } catch (IOException e) { 16 return null; 17 } 18 } 19 } 20 class exp_4_4 { 21 public static void main(String args[]) 22 throws IOException { 23 int c; 24 Vector files = new Vector(); 25 files.addElement("c:/java/1.txt"); 26 files.addElement("c:/java/2.txt"); 27 InputStreamEnumerator e = new InputStreamEnumerator(files); 28 InputStream input = new SequenceInputStream(e); 29 while ((c = input.read()) != -1) { 30 System.out.print((char) c); 31 } 32 input.close(); 33 } }
通过网络传输指定文件
服务端:
1 服务器端实现代码: 2 import java.io.*; 3 import java.net.*; 4 5 public class FileServer{ 6 public static void main(String[] args)throws Exception{ 7 //创建文件流用来读取文件中的数据 8 File file=new File("lishengjie.jpg"); 9 FileInputStream fos=new FileInputStream(file); 10 11 //创建网络服务器接受客户请求 12 ServerSocket ss=new ServerSocket(3108); 13 Socket client=ss.accept(); 14 15 //创建网络输出流并提供数据包装器 16 OutputStream netOut=client.getOutputStream(); 17 OutputStream doc=new DataOutputStream(new 18 BufferedOutputStream(netOut)); 19 20 //创建文件读取缓冲区 21 byte[] buf=new byte[2048]; 22 int num=fos.read(buf); 23 while(num!=(-1)){ //是否读完文件 24 doc.write(buf,0,num); //把文件数据写出网络缓冲区 25 doc.flush(); //刷新缓冲区把数据写往客户端 26 num=fos.read(buf); //继续从文件中读取数据 27 } 28 fos.close(); 29 doc.close(); 30 } 31 }
客户端:
1 客户方实现代码: 2 import java.io.*; 3 import java.net.*; 4 5 public class FileClient{ 6 public static void main(String[] args)throws Exception{ 7 //使用本地文件系统接受网络数据并存为新文件 8 File file=new File("newFile.jpg"); 9 file.createNewFile(); 10 RandomAccessFile raf=new RandomAccessFile(file,"rw"); 11 12 // 通过Socket连接文件服务器 13 Socket server=new Socket(InetAddress.getLocalHost(),3108); 14 //创建网络接受流接受服务器文件数据 15 InputStream netIn=server.getInputStream(); 16 InputStream in=new DataInputStream(new 17 BufferedInputStream(netIn)); 18 19 //创建缓冲区缓冲网络数据 20 byte[] buf=new byte[2048]; 21 int num=in.read(buf); 22 while(num!=(-1)){ //是否读完所有数据 23 raf.write(buf,0,num); //将数据写往文件 24 raf.skipBytes(num); //顺序写文件字节 25 num=in.read(buf); //继续从网络中读取文件 26 } 27 in.close(); 28 raf.close(); 29 } 30 }
文件压缩和解压缩,尝试压缩和解压缩带子目录的目录,解决汉字显示问题
压缩:
1 import java.text.*; 2 import java.util.zip.*; 3 import java.io.*; 4 class Zipper{ 5 String zipTarget; 6 String zipSource; 7 Zipper(String fileTarget, String fileSource){ 8 zipTarget = fileTarget; 9 zipSource = fileSource; 10 } 11 public void compress(){ 12 try{ 13 FileOutputStream fout = new FileOutputStream(zipTarget); 14 ZipOutputStream zout = new ZipOutputStream(fout); 15 zout.setLevel(9); 16 File file = new File(zipSource); 17 if(file.isDirectory()){ 18 String [] fileList = file.list(); 19 for(int i=0;i<fileList.length; i++){ 20 ZipEntry ze = new ZipEntry(fileList[i]); 21 System.out.println("正在压缩文件 " + fileList[i]); 22 FileInputStream fin = new FileInputStream(file+"\"+fileList[i]); 23 zout.putNextEntry(ze); 24 int c = -1; 25 while((c = fin.read()) != -1){ 26 zout.write(c); 27 } 28 fin.close(); 29 } 30 } 31 zout.closeEntry(); 32 zout.close(); 33 }catch(Exception e){ 34 System.err.println(e.toString()); 35 } 36 } 37 public static void main(String [] args){ 38 Zipper z = new Zipper("history.zip", "zip"); 39 z.compress(); 40 } 41 }
解压:
1 import java.util.*; 2 import java.text.*; 3 import java.util.zip.*; 4 import java.io.*; 5 6 class UnZipper{ 7 String zipSource; 8 UnZipper(String zipFile){ 9 zipSource = zipFile; 10 } 11 12 public void unCompress(){ 13 try{ 14 ZipFile zf = new ZipFile(zipSource); 15 Enumeration es = zf.entries(); 16 System.out.println("开始解压缩"); 17 while(es.hasMoreElements()){ 18 ZipEntry ze = (ZipEntry)es.nextElement(); 19 System.out.println("当前解压文件为:" + ze.getName()); 20 if(ze.isDirectory()){ 21 File ff = new File("newZip", ze.getName()); 22 ff.mkdirs(); 23 }else{ 24 InputStream in = zf.getInputStream(ze); 25 File ff = new File("newZip", ze.getName()); 26 File fp = ff.getParentFile(); 27 fp.mkdirs(); 28 FileOutputStream fout = new FileOutputStream(ff); 29 int c; 30 while((c = in.read()) != -1)fout.write(c); 31 } 32 } 33 }catch(Exception e){ 34 System.err.println(e.toString()); 35 } 36 } 37 38 public static void main(String [] args){ 39 UnZipper uz = new UnZipper("history.zip"); 40 uz.unCompress(); 41 } 42 }